Feeder is in charge of returning an array of items rated by users (feed). If there is a watching user (current_user), the Ratings should be from all users being influencers except for a watching user.Scroll is given by a gem. It gives a cursor for each rating so that infinite scrolls will work.I see this pattern quite frequently in my code: one if statement where very little changes. How can this be refactored?class Feederdef self.most_recent_created(watching_user=nil, current_cursor)    next_cursor = nil    feed = []    influencers_ids = User.any_in(roles: [influencer]).distinct(:_id)    if watching_user        Rating.not_from(watching_user).but_from(influencers_ids).over_zero.desc(:created_at).limit(IMOS_PER_PAGE).scroll(current_cursor) do |rating, cursor|          next_cursor = cursor          imo = Imo.new(rating)          imo_presenter = ImoPresenter.new(imo, watching_user)          feed.push(imo_presenter)        end    else      Rating.from(influencers_ids).over_zero.desc(:created_at).limit(IMOS_PER_PAGE).scroll(current_cursor) do |rating, cursor|        next_cursor = cursor        imo = Imo.new(rating)        imo_presenter = ImoPresenter.new(imo)        feed.push(imo_presenter)      end    end    feed.push(next_cursor.to_s)  endend
Feeder for returning an array of items rated by users
ruby;ruby on rails
I'm working on the assumption that Rating is an ActiveRecord subclass, and you're using scopes to compose a query. Scopes return a proxy object which you can further scope, and then you coalesce them into a query. I'm not familiar with scroll but I'm assuming that it is what does that in this case.class Feeder  def self.most_recent_created(watching_user = nil, current_cursor)    influencers_ids = User.any_in(roles: [influencer]).distinct(:_id)You can use a pattern like this to progressively build a query proxy based on some series of if conditions:    proxy = Rating.from(influencers_ids).over_zero.desc(:created_at).limit(IMOS_PER_PAGE)    proxy = proxy.not_from(watching_user) if watching_userAnd then once you have your proxy built, you can just call your coalescing method on it and handle it as you normally would:    feed = []    next_cursor = nil    proxy.scroll(current_cursor) do |rating, cursor|      next_cursor = cursor      feed << ImoPresenter.new(Imo.new(rating), watching_user)    end    feed.push(next_cursor.to_s)  endendMore generally, composable queries via scopes can be leveraged to dramatically reduce code duplication. Start with something like:proxy = MyModelAnd then start composing your scope based on some conditions:proxy = proxy.some_scope(param) if condition?proxy = proxy.another_scope if other_condition?proxy = proxy.yet_another_scope unless third_condition?And then finally process your query:proxy.each {|record| ... }If you find that you're duplicating parts of that composition, then you can condense them into a single scope. So if you find that you're always writing:proxy = proxy.some_scope(param) if condition?proxy = proxy.another_scope if other_condition?Just condense it into a scope:scope :compound_scope, ->(param) {  proxy = self  proxy = proxy.some_scope(param) if condition?  proxy = proxy.another_scope if other_condition?  proxy}Then you would use compound_scope in your controller code, avoiding code re-use.