Skip to content

Instantly share code, notes, and snippets.

@Aupajo
Last active December 7, 2016 02:34
Show Gist options
  • Save Aupajo/0d174614adfcd1348b83 to your computer and use it in GitHub Desktop.
Save Aupajo/0d174614adfcd1348b83 to your computer and use it in GitHub Desktop.
Mutable Chain

MutableChain

class MutableChain
  attr_reader :subject

  def initialize(subject)
    @subject = subject
  end

  def method_missing(method_name, *args, &block)
    if subject.respond_to?(method_name)
      @subject = subject.send(method_name, *args, &block)
    else
      super
    end
  end

  def respond_if_missing?(method_name, include_private = false)
    subject.respond_to?(method_name, include_private) || super
  end
end

Before

Complex construction of an ActiveRecord::Relation. Each scope returns a new relation, but we're really trying to chain them together to build one complex chain:

def results
  criteria = Booking.confirmed

  if filter == :pick_ups
    criteria = criteria.origin(location) if location
    criteria = criteria.start_time_between(date_range)
  elsif filter == :drop_offs
    criteria = criteria.destination(location) if location
    criteria = criteria.end_time_between(date_range)
  else
    criteria = criteria.origin_or_destination(location) if location
    criteria = criteria.start_or_end_time_between(date_range)
  end

  criteria = criteria.includes(:drivers)

  criteria.page(page)
end

After

Methods can now be chained without variable reassignment:

def results
  criteria = MutableChain.new(Booking)
  
  criteria.confirmed

  if filter == :pick_ups
    criteria.origin(location) if location
    criteria.start_time_between(date_range)
  elsif filter == :drop_offs
    criteria.destination(location) if location
    criteria.end_time_between(date_range)
  else
    criteria.origin_or_destination(location) if location
    criteria.start_or_end_time_between(date_range)
  end

  criteria.includes(:drivers)

  criteria.page(page)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment