【问题标题】:Rails Controller Refactor DRY CodeRails 控制器重构 DRY 代码
【发布时间】:2014-03-25 17:01:15
【问题描述】:

我一直在努力寻找一种方法来重构这个丑陋的控制器

  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 专家,我真的很想学习如何重构代码并保持干货

【问题讨论】:

    标签: ruby-on-rails refactoring dry


    【解决方案1】:

    所以我在 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
    

    然后在我的控制器中

    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
    

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

    【讨论】:

      【解决方案2】:

      你可以使用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)
      

      您可能希望将此块保存在您可以轻松访问的某个地方

      【讨论】:

      • 这是一个很好的建议......但是没有一种简单的方法来重构它吗?不过,感谢您对 gem 的提醒……我想知道是否有一种在不使用 gem 的情况下重构此代码的好方法。仅用于学习目的...谢谢!
      • 添加更多 cmets 以获得更多说明
      • 谢谢你,这就是我要找的... date_group (&date_group) 前面的 & 是什么意思
      • 它用于将块作为参数传递它的 ruby​​ 语法
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-17
      • 1970-01-01
      相关资源
      最近更新 更多