module FlexColumns::Including::IncludeFlexColumns::ClassMethods

Public Instance Methods

_flex_column_is_included_from(flex_column_name) click to toggle source

Returns the name of the association from which a flex column of the given name was included.

# File lib/flex_columns/including/include_flex_columns.rb, line 83
def _flex_column_is_included_from(flex_column_name)
  @_included_flex_columns_map[flex_column_name]
end
_flex_columns_include_flex_columns_dynamic_methods_module() click to toggle source

The DynamicMethodsModule on which we define all methods generated by included flex columns.

# File lib/flex_columns/including/include_flex_columns.rb, line 78
def _flex_columns_include_flex_columns_dynamic_methods_module
  @_flex_columns_include_flex_columns_dynamic_methods_module ||= FlexColumns::Util::DynamicMethodsModule.new(self, :FlexColumnsIncludedColumnsMethods)
end
include_flex_columns_from(*args, &block) click to toggle source

Includes methods from the given flex column or flex columns into this class.

args should be a list of association names from which you want to include columns. It can also end in an options Hash, which can contain:

:prefix

If set, included method names will be prefixed with the given string (followed by an underscore). If not set, the prefix defined on each flex column, if any, will be used; you can override this by explicitly passing nil here.

:visibility

If set to :private, included methods will be marked private, meaning they can only be accessed from inside this model. This can be used to ensure random code across your system can’t directly manipulate flex-column fields.

:delegate

If set to false or nil, then only the method that accesses the flex column itself (above, User#details) will be created; other methods (User#background_color, User#likes_peaches) will not be automatically delegated.

# File lib/flex_columns/including/include_flex_columns.rb, line 101
      def include_flex_columns_from(*args, &block)
        # Grab our options, and validate them as necessary...
        options = args.pop if args[-1] && args[-1].kind_of?(Hash)
        options ||= { }

        options.assert_valid_keys(:prefix, :visibility, :delegate)

        case options[:prefix]
        when nil, String, Symbol then nil
        else raise ArgumentError, "Invalid value for :prefix: #{options[:prefix].inspect}"
        end

        unless [ :public, :private, nil ].include?(options[:visibility])
          raise ArgumentError, "Invalid value for :visibility: #{options[:visibility].inspect}"
        end

        unless [ true, false, nil ].include?(options[:delegate])
          raise ArgumentError, "Invalid value for :delegate: #{options[:delegate].inspect}"
        end

        association_names = args

        @_included_flex_columns_map ||= { }

        # Iterate through each association...
        association_names.each do |association_name|
          # Get the association and make sure it's of the right type...
          association = reflect_on_association(association_name.to_sym)
          unless association
            raise ArgumentError, %{You asked #{self.name} to include flex columns from association #{association_name.inspect},
but this class doesn't seem to have such an association. Associations it has are:

  #{reflect_on_all_associations.map(&:name).sort_by(&:to_s).join(", ")}}
          end

          unless [ :has_one, :belongs_to ].include?(association.macro)
            raise ArgumentError, %{You asked #{self.name} to include flex columns from association #{association_name.inspect},
but that association is of type #{association.macro.inspect}, not :has_one or :belongs_to.

We can only include flex columns from an association of these types, because otherwise
there is no way to know which target object to include the data from.}
          end

          # Grab the target model class, and make sure it has one or more flex columns...
          target_class = association.klass
          if (! target_class.respond_to?(:has_any_flex_columns?)) || (! target_class.has_any_flex_columns?)
            raise ArgumentError, %{You asked #{self.name} to include flex columns from association #{association_name.inspect},
but the target class of that association, #{association.klass.name}, has no flex columns defined.}
          end

          # Call through and tell those flex columns to create the appropriate methods.
          target_class._all_flex_column_names.each do |flex_column_name|
            @_included_flex_columns_map[flex_column_name] = association_name

            flex_column_class = target_class._flex_column_class_for(flex_column_name)
            flex_column_class.include_fields_into(_flex_columns_include_flex_columns_dynamic_methods_module, association_name, self, options)
          end
        end
      end