lib/anchormodel/model_mixin.rb in anchormodel-0.1.3 vs lib/anchormodel/model_mixin.rb in anchormodel-0.1.4

- old
+ new

@@ -7,90 +7,12 @@ class_attribute :anchormodel_attributes, default: {}.freeze end class_methods do # Creates an attribute linking to an Anchormodel. The attribute should be - # present in the DB and the column should be named the same as `attribute_name.` - # @param attribute_name [String,Symbol] The name and database column of the attribute - # @param anchormodel_class [Class] Class of the Anchormodel (omit if attribute `:foo_bar` holds a `FooBar`) - # @param optional [Boolean] If true, a presence validation is added to the model. - # @param model_readers [Boolean] If true, the model is given an ActiveRecord::Enum style method `my_model.my_key?` reader for each key in the anchormodel - # @param model_writers [Boolean] If true, the model is given an ActiveRecord::Enum style method `my_model.my_key!` writer for each key in the anchormodel - # @param model_scopes [Boolean] If true, the model is given an ActiveRecord::Enum style scope `MyModel.mykey` for each key in the anchormodel - # @param model_methods [Boolean, NilClass] If non-nil, this mass-assigns and overrides `model_readers`, `model_writers` and `model_scopes` - def belongs_to_anchormodel(attribute_name, anchormodel_class = nil, optional: false, model_readers: true, - model_writers: true, model_scopes: true, model_methods: nil) - anchormodel_class ||= attribute_name.to_s.classify.constantize - attribute_name = attribute_name.to_sym - attribute = Anchormodel::Attribute.new(self, attribute_name, anchormodel_class, optional) - - # Mass configurations if model_methods was specfied - unless model_methods.nil? - model_readers = model_methods - model_writers = model_methods - model_scopes = model_methods - end - - # Register attribute - self.anchormodel_attributes = anchormodel_attributes.merge({ attribute_name => attribute }).freeze - - # Add presence validation if required - unless optional - validates attribute_name, presence: true - end - - # Make casting work - # Define serializer/deserializer - active_model_type_value = Anchormodel::ActiveModelTypeValue.new(attribute) - - # Overwrite reader to force building anchors at every retrieval - define_method(attribute_name.to_s) do - active_model_type_value.deserialize(read_attribute(attribute_name)) - end - - # Override writer to fail early when an invalid target value is specified - define_method("#{attribute_name}=") do |new_value| - write_attribute(attribute_name, active_model_type_value.serialize(new_value)) - end - - # Supply serializer and deserializer - attribute attribute_name, active_model_type_value - - # Create ActiveRecord::Enum style reader directly in the model if asked to do so - # For a model User with anchormodel Role with keys :admin and :guest, this creates user.admin? and user.guest? (returning true iff role is admin/guest) - if model_readers - anchormodel_class.all.each do |entry| - if respond_to?(:"#{entry.key}?") - fail("Anchormodel reader #{entry.key}? already defined for #{self}, add `model_readers: false` to `belongs_to_anchormodel :#{attribute_name}`.") - end - define_method(:"#{entry.key}?") do - public_send(attribute_name.to_s) == entry - end - end - end - - # Create ActiveRecord::Enum style writer directly in the model if asked to do so - # For a model User with anchormodel Role with keys :admin and :guest, this creates user.admin! and user.guest! (setting the role to admin/guest) - if model_writers - anchormodel_class.all.each do |entry| - if respond_to?(:"#{entry.key}!") - fail("Anchormodel writer #{entry.key}! already defined for #{self}, add `model_writers: false` to `belongs_to_anchormodel :#{attribute_name}`.") - end - define_method(:"#{entry.key}!") do - public_send(:"#{attribute_name}=", entry) - end - end - end - - # Create ActiveRecord::Enum style scope directly in the model class if asked to do so - # For a model User with anchormodel Role with keys :admin and :guest, this creates user.admin! and user.guest! (setting the role to admin/guest) - if model_scopes - anchormodel_class.all.each do |entry| - if respond_to?(entry.key) - fail("Anchormodel scope #{entry.key} already defined for #{self}, add `model_scopes: false` to `belongs_to_anchormodel :#{attribute_name}`.") - end - scope(entry.key, -> { where(attribute_name => entry.key) }) - end - end + # present in the DB and the column should be of type String and named the same as `attribute_name`. + # @see Anchormodel::Util#install_methods_in_model Parameters + def belongs_to_anchormodel(*args, **kwargs) + Anchormodel::Util.install_methods_in_model(self, *args, **kwargs) end end end