module Cistern::Associations
Public Class Methods
extended(klass)
click to toggle source
Calls superclass method
# File lib/cistern/associations.rb, line 4 def self.extended(klass) def klass.association_overlay @association_overlay ||= const_set(:Associations, Module.new) end klass.send(:include, klass.association_overlay) super end
Public Instance Methods
associations()
click to toggle source
Lists the associations defined on the resource @return [Hash{Symbol=>Array}] mapping of association type to name
# File lib/cistern/associations.rb, line 16 def associations @associations ||= Hash.new { |h, k| h[k] = [] } end
belongs_to(name, *args, &block)
click to toggle source
Define an assocation that references a model. @param name [Symbol] name of association and corresponding reader. @param scope [Proc] returning a {Cistern::Model} that is evaluated within the context of the model. @return [Cistern::Model] as defined by {#scope} @example
class Firm < Law::Model identity :registration_id belongs_to :leader, -> { cistern.employees.get(:ceo) } end
# File lib/cistern/associations.rb, line 77 def belongs_to(name, *args, &block) name_sym = name.to_sym reader_method = name writer_method = "#{name}=" options = args.last.is_a?(::Hash) ? args.pop : {} scope = args.first || block attribute name_sym, options.merge(writer: false, reader: false) association_overlay.module_eval do define_method reader_method do model = instance_exec(&scope) attributes[name_sym] = model.attributes model end end association_overlay.module_eval do define_method writer_method do |model| previous_value = attributes[name_sym] new_value = model.respond_to?(:attributes) ? model.attributes : model attributes[name_sym] = new_value changed!(name_sym, previous_value, new_value) new_value end end associations[:belongs_to] << name_sym end
has_many(name, *args, &block)
click to toggle source
Define an assocation that references a collection. @param name [Symbol] name of association and corresponding reader and writer. @param scope [Proc] returning {Cistern::Collection} instance to load models into. {#scope} is evaluated within the
context of the model.
@return [Cistern::Collection] as defined by {#scope} @example
class Firm < Law::Model identity :registration_id has_many :lawyers, -> { cistern.associates(firm_id: identity) } end
# File lib/cistern/associations.rb, line 30 def has_many(name, *args, &block) name_sym = name.to_sym reader_method = name writer_method = "#{name}=" options = args.last.is_a?(::Hash) ? args.pop : {} scope = args.first || block attribute name_sym, options.merge(writer: false, reader: false, type: :array) association_overlay.module_eval do define_method reader_method do collection = instance_exec(&scope) records = attributes[name_sym] || [] collection.load(records) if records.any? collection end end association_overlay.module_eval do define_method writer_method do |models| previous_value = attributes[name_sym] new_value = attributes[name_sym] = Array(models).map do |model| model.respond_to?(:attributes) ? model.attributes : model end changed!(name_sym, previous_value, new_value) new_value end end associations[:has_many] << name_sym end