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

In many ways, flex_columns models its behavior after ActiveRecord — for example, automatic generation of attribute methods. However, flex_columns offers an option ActiveRecord doesn't: you can make attribute methods private by default.

This is a deliberate choice, as ActiveRecord's "everything is public" design choice makes true encapsulation very difficult — any code, anywhere in the system, can easily set any ActiveRecord column to any value at all. By allowing fields to be private, flex_columns can help ensure that access is only done via valid code paths.

If you add :visibility => :private to a particular field in a flex column, then the generated methods for that column will be marked as private. If you add :visibility => :private to the flex column itself, then all generated methods for that column will be marked as private, unless you individually mark them as public.

For example:

class User < ActiveRecord::Base
  flex_column :user_attributes do
    field :maximum_emails_per_week, :visibility => :private
    field :background_color
  end

  flex_column :more_attributes, :visibility => :private do
    field :foo
    field :bar, :visibility => :public
  end
end

my_user = User.find(...)

my_user.maximum_emails_per_week                     # NoMethodError: private method 'maximum_emails_per_week' called
my_user.user_attributes.maximum_emails_per_week     # NoMethodError: private method 'maximum_emails_per_week' called
my_user.maximum_emails_per_week = 3                 # NoMethodError: private method 'maximum_emails_per_week=' called
my_user.user_attributes.maximum_emails_per_week = 3 # NoMethodError: private method 'maximum_emails_per_week=' called
my_user.background_color                            # fine

my_user.foo                                         # NoMethodError: private method 'foo' called
my_user.foo = 3                                     # NoMethodError: private method 'foo=' called
my_user.bar                                         # fine
my_user.bar = 'some value'                          # fine

Note that if you want to use Ruby's private or public method to change the visibility of one of these methods (for example, to make a reader public, but a writer private), it's slightly tricky. So that method overriding will work properly, these methods are actually defined on a module that's included into the flex-column class and ActiveRecord class; you can't simply say private :foo, for example. Instead, you must first override the method (a simple call to super works fine), and then make that method public or private.

Clone this wiki locally