Rails控制器重构DRY代码



我一直在想办法重构这个难看的控制器

  def video_games
  @video_games_released = Item.video_games.released.group_by { 
    |item| [item.release_date.try(:strftime, "%B %d, %Y"), item.time_diff_components].join()
  }
  @video_games_coming_soon = Item.video_games.coming_soon.group_by { 
    |item| [item.release_date.try(:strftime, "%B %d, %Y"), item.time_diff_components].join()
  }
  @video_games_unknown = Item.video_games.unknown.group_by { 
    |item| [item.release_date.try(:strftime, "%B %d, %Y"), item.time_diff_components].join()
  }
end
def movies
  @movies_coming_soon = Item.movies.coming_soon.group_by { 
    |item| [item.release_date.try(:strftime, "%B %d, %Y"), item.time_diff_components].join()
  } 
  @movies_released = Item.movies.released.group_by { 
    |item| [item.release_date.try(:strftime, "%B %d, %Y"), item.time_diff_components].join()
  }
  @movies_unknown = Item.movies.unknown.group_by { 
    |item| [item.release_date.try(:strftime, "%B %d, %Y"), item.time_diff_components].join()
  }
end
def tv
  @tv_coming_soon = Item.tv.coming_soon.group_by { 
    |item| [item.release_date.try(:strftime, "%B %d, %Y"), item.time_diff_components].join()
  }
  @tv_released = Item.tv.released.group_by { 
    |item| [item.release_date.try(:strftime, "%B %d, %Y"), item.time_diff_components].join()
  }
  @tv_unknown = Item.tv.unknown.group_by { 
    |item| [item.release_date.try(:strftime, "%B %d, %Y"), item.time_diff_components].join()
  }  
end

我想去掉重复,特别是group_by方法

我已经尝试进入模型并创建一个方法

 def group_by_month
   self.group_by { 
     |item| [item.release_date.try(:strftime, "%B %d, %Y"), item.time_diff_components].join()
   } 
 end

我试过了,但似乎没有工作

我不是rails专家,我真的在努力学习如何重构代码和保持代码干燥

所以我在khaled_gomaa建议的帮助下重构了这段代码

我在

中创建了一个演示者
app/presenters/items/index_presenter.rb
module Items
class IndexPresenters
  def initialize(item)
    @item = item
  end
   def released
     @item.released.group_by(&date_group)
   end
   def coming_soon
     @item.coming_soon.group_by(&date_group)
   end
   def unknown
     @item.unknown.group_by(&date_group)
   end
   def date_group 
     lambda { |item| [item.release_date.try(:strftime, "%B %d, %Y"), item.time_diff_components].join()}
   end
 end
end

then in my controller

def video_games
  @presenter = Items::IndexPresenters.new(Item.video_games)
end
def movies
  @presenter = Items::IndexPresenters.new(Item.movies)
end
def tv
  @presenter = Items::IndexPresenters.new(Item.tv)
end

和我的观点

%h2 Movies Released
= render 'items', item: @presenter.released
%h2 Movies Coming Soon
= render 'items', item: @presenter.coming_soon
%h2 Movies Unknown
= render 'items', item: @presenter.unknown

欢迎任何进一步的建议!谢谢你!

可以使用groupupdate gem它将在数据库级别为您提供此功能

这是最简单的方法

如果你想这样做,以了解更多关于rails

你有一个明显的块,你反复使用

{ 
     |item| [item.release_date.try(:strftime, "%B %d, %Y"), item.time_diff_components].join()
   }

你可以保存它并在需要的时候调用它

date_group = lambda { |item| [item.release_date.try(:strftime, "%B %d, %Y"), item.time_diff_components].join()}

,当你需要使用它时,你可以使用

Item.tv.coming_soon.group_by(&date_group)

你可能想把这个块保存在你可以方便访问的地方

最新更新