Module: FlexColumns::Including::IncludeFlexColumns
- Extended by:
- ActiveSupport::Concern
- Defined in:
- lib/flex_columns/including/include_flex_columns.rb
Overview
IncludeFlexColumns defines the methods on ActiveRecord::Base that get triggered when you say ‘include_flex_columns_from’ on an ActiveRecord model. Note, however, that it is not simply directly included into ActiveRecord::Base; rather, it’s included only when you actually make that declaration, and included into the specific model class itself. (This helps avoid pollution or conflict on any ActiveRecord models that have not used this functionality.)
This module works in a pretty different way from FlexColumns::HasFlexColumns, which is the corresponding module that gets included when you declare a flex column with flex_column :foo do ... end
. That module builds up an object representation of the flex column itself and of all its fields, and then holds onto these objects and uses them to do its work. This module, on the other hand, actively and aggressively defines the appropriate methods when you call #include_flex_columns_from, but does not create or hold onto any object representation of the included columns. This is for two reasons: first off, there’s a lot more complexity in defining a flex column itself than in simply including one. Secondly, and more subtly, defining a flex column is a process with a decided start and end – the contents of the block passed to flex_column
. Including fields, however, is a component part of a class that’s defined using the Ruby class
keyword, and which can get reopened and redefined at any given time. Thus, we really have no choice but to aggressively define methods when include_flex_columns_from
is called; holding onto an object representation would largely just ensure that that object representation grew incorrect over time in development mode, as columns get defined and redefined over time.
(A corollary of this is that, in Rails development mode, depending on how classes get reloaded, it’s possible that if you remove an include_flex_columns_from
declaration from a model, the defined methods won’t actually disappear until you restart your server. There’s really not much we can do about this, since there’s no Ruby hook that says “someone is defining methods on class X” – nor would one make any sense, since you can re-open classes at any time and as many times as you want in Ruby.)
In comments below, we’re working with the following example:
class UserDetail < ActiveRecord::Base
self.primary_key = :user_id
belongs_to :user
flex_column :details do
field :background_color
field :likes_peaches
end
end
class User < ActiveRecord::Base
has_one :detail
include_flex_columns_from :detail
end
Defined Under Namespace
Modules: ClassMethods
Instance Method Summary collapse
-
#_flex_column_included_object_for(column_name) ⇒ Object
This is the method that gets called by generated delegated methods via FlexColumns::ActiveRecord::Base#_flex_column_object_for, and called in order to retrieve the correct flex-column object for a column.
Instance Method Details
#_flex_column_included_object_for(column_name) ⇒ Object
This is the method that gets called by generated delegated methods via FlexColumns::ActiveRecord::Base#_flex_column_object_for, and called in order to retrieve the correct flex-column object for a column. In other words, the generated method User#background_color looks something like:
def background_color
flex_column_object = _flex_column_object_for(:details)
flex_column_object.background_color
end
61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/flex_columns/including/include_flex_columns.rb', line 61 def _flex_column_included_object_for(column_name) # Fetch the association that this column is included from. association = self.class._flex_column_is_included_from(column_name) if association # Get the associated object. We automatically will build the associated object, if necessary; this is so that # you don't have to either actively create associated objects ahead of time, just in case you need them later, # or litter your code with checks to see if those objects exist already or not. associated_object = send(association) || send("build_#{association}") return associated_object.send(column_name) else raise FlexColumns::Errors::NoSuchColumnError.new(%{Class #{self.class.name} knows nothing of a flex column named #{column_name.inspect}.}) end end |