Module: MotionPrime::ModelAssociationMixin::ClassMethods

Defined in:
motion-prime/models/_association_mixin.rb

Instance Method Summary collapse

Instance Method Details

#bag(name) ⇒ Nil

Defines bag associated with model, creates accessor for bag

Parameters:

  • name (String)
    • the name of bag

Returns:

  • (Nil)


40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'motion-prime/models/_association_mixin.rb', line 40

def bag(name)
  define_method(name) do |*args, &block|
    # use users_bag(true) to reload bag
    return _bags[name] if _bags[name] && args[0] != true
    bag_key = bag_key_for(name)
    if bag_key.present?
      bag = self.class.store.bagsWithKeysInArray([bag_key]).first
    end
    unless bag
      bag = Bag.bag
      self.info[name] = bag.key
    end

    _bags[name] = bag
  end

  define_method((name + "=").to_sym) do |*args, &block|
    bag = self.send(name)
    case args[0]
    when Bag
      bag.clear
      bag += args[0].saved.values
    when Array
      bag.clear
      bag += args[0]
    else
      raise StoreError, "Unexpected type assigned to bags, must be an Array or MotionPrime::Bag, now: #{args[0].class}"
    end
    bag
  end
end

#belongs_to(association_name, options = {}) ⇒ Object



151
152
153
154
155
156
157
158
159
# File 'motion-prime/models/_association_mixin.rb', line 151

def belongs_to(association_name, options = {})
  self._associations ||= {}
  self._associations[association_name] = {
    type: :belongs_to_one,
    class_name: association_name.classify
  }.merge(options)

  self.send(:attr_accessor, association_name)
end

#has_many(association_name, options = {}) ⇒ Nil

Defines has many association for model, creates accessor for association

Parameters:

  • name (String)
    • the name of association

Returns:

  • (Nil)


107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'motion-prime/models/_association_mixin.rb', line 107

def has_many(association_name, options = {})
  bag_name = "#{association_name}_bag"
  self.bag bag_name.to_sym

  self._associations ||= {}
  self._associations[association_name] = options.merge(type: :many)

  define_method("#{association_name}_attributes=") do |value|
    bags_attributes = self.send(bag_name).to_a.inject({}) do |result, item|
      result[item.id] = item.bags_attributes if item.id
      result
    end
    self.send(bag_name).clear

    pending_save_counter = 0
    collection = value.inject({}) do |result, attrs|
      model = association_name.classify.constantize.new
      model.info.merge!(bags_attributes.fetch(attrs[:id], {}))
      model.fetch_with_attributes(attrs)
      unique_key = model.id || "pending_#{pending_save_counter+=1}"
      result.merge(unique_key => model)
    end
    association_data = collection.values
    self.send(:"#{bag_name}=", association_data)
    association_data
  end
  define_method("#{association_name}=") do |value|
    self.send(bag_name).clear
    self.send(:"#{bag_name}=", value)
  end
  define_method("#{association_name}") do |*args|
    bag = self.send(:"#{bag_name}")
    collection_options = {
      association_name: association_name,
      inverse_relation: {
        type: :has_one,
        name: self.class_name_without_kvo.demodulize.underscore,
        instance: self
      }
    }
    AssociationCollection.new(bag, collection_options, *args)
  end
end

#has_one(association_name, options = {}) ⇒ Nil

Defines has one association for model, creates accessor for association

Parameters:

  • name (String)
    • the name of association

Returns:

  • (Nil)


76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'motion-prime/models/_association_mixin.rb', line 76

def has_one(association_name, options = {})
  bag_name = "#{association_name.pluralize}_bag"
  self.bag bag_name.to_sym

  self._associations ||= {}
  self._associations[association_name] = options.merge(type: :one)

  define_method("#{association_name}=") do |value|
    bag = self.send(bag_name)
    bag.clear
    bag << value
    value
  end
  define_method("#{association_name}_attributes=") do |value|
    bags_attributes = self.send(association_name).try(:bags_attributes) || {}
    self.send(bag_name).clear
    association = association_name.classify.constantize.new
    association.info.merge!(bags_attributes)
    association.fetch_with_attributes(value)
    self.send(:"#{bag_name}") << association
    association
  end
  define_method("#{association_name}") do
    self.send(:"#{bag_name}").to_a.first
  end
end