Skip to content

Controlling Method Delegation

Andrew Geweke edited this page Dec 13, 2013 · 3 revisions

When you define a flex column, by default, delegate methods are generated on the enclosing model class for both the fields you define (reader and writer methods) and any custom methods you define:

class User < ActiveRecord::Base
  flex_column :user_attributes do
    field :maximum_emails_per_week
    field :background_color

    def more_emails!
      self.maximum_emails_per_week += 1
    end
  end
end

my_user = User.find(...)
my_user.maximum_emails_per_week = 7
my_user.more_emails!
my_user.maximum_emails_per_week # => 8
my_user.background_color = :green

If, however, you pass :delegate => false to the declaration of the flex column, no such methods will be generated at all:

class User < ActiveRecord::Base
  flex_column :user_attributes do
    field :maximum_emails_per_week
    field :background_color

    def more_emails!
      self.maximum_emails_per_week += 1
    end
  end
end

my_user = User.find(...)
my_user.maximum_emails_per_week = 7     # => NoMethodError
my_user.more_emails!                    # => NoMethodError
my_user.maximum_emails_per_week         # => NoMethodError
my_user.background_color = :green       # => NoMethodError

my_user.user_attributes.maximum_emails_per_week = 7
my_user.user_attributes.more_emails!
my_user.user_attributes.maximum_emails_per_week # => 8
my_user.user_attributes.background_color = :green

If you want to delegate some methods and not others, simply pass :delegate => false, and then create delegate methods yourself — or use ActiveSupport's #delegate method to make it easy for you.

If you pass :prefix => 'foo' (argument must be a String or Symbol), then all delegated methods will be prefixed with the given string, followed by an underscore. For example:

class User < ActiveRecord::Base
  flex_column :user_attributes, :prefix => 'foo' do
    field :maximum_emails_per_week
    field :background_color

    def more_emails!
      self.maximum_emails_per_week += 1
    end
  end
end

my_user = User.find(...)
my_user.foo_maximum_emails_per_week = 7
my_user.foo_more_emails!
my_user.foo_maximum_emails_per_week # => 8
my_user.foo_background_color = :green

but:

my_user.user_attributes.maximum_emails_per_week # => 8
my_user.user_attributes.more_emails!
my_user.user_attributes.maximum_emails_per_week # => 9

...and so on.

Clone this wiki locally