Instance Methods

OccamsRecords results are just plain structs; they don't have methods from your Rails models. (Separating your persistence layer from your domain is good thing!) But sometimes you need a few methods. OccamsRecord provides two ways of accomplishing this.

Injecting modules

You may also specify one or more modules to be included in your results:

module MyOrderMethods
  def description
    "#{order_number} - #{date}"
  end
end

module MyProductMethods
  def expensive?
    price > 100
  end
end

orders = OccamsRecord.
  query(Order.all, use: MyOrderMethods).
  eager_load(:line_items) {
    eager_load(:product, use: [MyProductMethods, OtherMethods])
  }.
  find_each { |order|
    puts order.description # MyOrderMethods#description
    puts order.line_items[0].product.expensive? # MyProductMethods#expensive?
  }

ActiveRecord fallback mode

This is an ugly hack of last resort if you can’t easily extract a method from your model into a shared module. Plugins, like carrierwave, are a good example. When you call a method that doesn’t exist on an OccamsRecord result, it will initialize an ActiveRecord object and forward the method call to it.

The active_record_fallback option must be passed either :lazy or :strict (recommended). :strict enables ActiveRecord’s strict loading option, helping you avoid N+1 queries in your model code. :lazy allows them. (:strict is only available for ActiveRecord 6.1 and later.)

The following will forward any nonexistent methods for Order and Product records:

orders = OccamsRecord.
  query(Order.all, active_record_fallback: :strict).
  eager_load(:line_items) {
    eager_load(:product, active_record_fallback: :strict)
  }.
  run