Module: Cistern::Attributes::InstanceMethods

Included in:
Collection, Model, Singular
Defined in:
lib/cistern/attributes.rb

Instance Method Summary collapse

Instance Method Details

#_dump(level) ⇒ Object



117
118
119
# File 'lib/cistern/attributes.rb', line 117

def _dump(level)
  Marshal.dump(attributes)
end

#attributesObject



163
164
165
# File 'lib/cistern/attributes.rb', line 163

def attributes
  @attributes ||= {}
end

#attributes=(attributes) ⇒ Object



167
168
169
# File 'lib/cistern/attributes.rb', line 167

def attributes=(attributes)
  @attributes = attributes
end

#changedObject



255
256
257
# File 'lib/cistern/attributes.rb', line 255

def changed
  @changes ||= {}
end

#dirty?Boolean

Returns:

  • (Boolean)


247
248
249
# File 'lib/cistern/attributes.rb', line 247

def dirty?
  changed.any?
end

#dirty_attributesObject



251
252
253
# File 'lib/cistern/attributes.rb', line 251

def dirty_attributes
  changed.inject({}) { |r,(k,(_,v))| r.merge(k => v) }
end

#dupObject



171
172
173
174
175
# File 'lib/cistern/attributes.rb', line 171

def dup
  copy = super
  copy.attributes= copy.attributes.dup
  copy
end

#identityObject



177
178
179
# File 'lib/cistern/attributes.rb', line 177

def identity
  send(self.class.instance_variable_get('@identity'))
end

#identity=(new_identity) ⇒ Object



181
182
183
# File 'lib/cistern/attributes.rb', line 181

def identity=(new_identity)
  send("#{self.class.instance_variable_get('@identity')}=", new_identity)
end

#merge_attributes(new_attributes = {}) ⇒ Object



185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
# File 'lib/cistern/attributes.rb', line 185

def merge_attributes(new_attributes = {})
  protected_methods  = (Cistern::Model.instance_methods - [:connection, :identity, :collection])
  ignored_attributes = self.class.ignored_attributes
  class_attributes   = self.class.attributes
  class_aliases      = self.class.aliases

  new_attributes.each do |_key, value|
    string_key = _key.kind_of?(String) ? _key : _key.to_s
    symbol_key = case _key
          when String
            _key.to_sym
          when Symbol
            _key
          else
            string_key.to_sym
          end

    # find nested paths
    value.is_a?(::Hash) && class_attributes.each do |name, options|
      if options[:squash] && options[:squash].first == string_key
        send("#{name}=", {symbol_key => value})
      end
    end

    unless ignored_attributes.include?(symbol_key)
      if class_aliases.has_key?(symbol_key)
        class_aliases[symbol_key].each do |aliased_key|
          send("#{aliased_key}=", value)
        end
      end

      assignment_method = "#{string_key}="
      if !protected_methods.include?(symbol_key) && self.respond_to?(assignment_method, true)
        send(assignment_method, value)
      end
    end
  end
  changed.clear
  self
end

#new_record?Boolean

Returns:

  • (Boolean)


226
227
228
# File 'lib/cistern/attributes.rb', line 226

def new_record?
  !identity
end

#read_attribute(name) ⇒ Object



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/cistern/attributes.rb', line 121

def read_attribute(name)
  options = self.class.attributes[name] || {}
  # record the attribute was accessed
  begin
    self.class.attributes[name.to_s.to_sym][:coverage_hits] += 1
  rescue
    nil
  end

  default = options[:default]

  unless default.nil?
    default = Marshal.load(Marshal.dump(default))
  end

  attributes.fetch(name.to_s.to_sym, default)
end

#requires(*args) ⇒ Object

check that the attributes specified in args exist and is not nil



231
232
233
234
235
236
237
238
# File 'lib/cistern/attributes.rb', line 231

def requires(*args)
  missing = missing_attributes(args)
  if missing.length == 1
    raise(ArgumentError, "#{missing.first} is required for this operation")
  elsif missing.any?
    raise(ArgumentError, "#{missing[0...-1].join(", ")} and #{missing[-1]} are required for this operation")
  end
end

#requires_one(*args) ⇒ Object



240
241
242
243
244
245
# File 'lib/cistern/attributes.rb', line 240

def requires_one(*args)
  missing = missing_attributes(args)
  if missing.length == args.length
    raise(ArgumentError, "#{missing[0...-1].join(", ")} or #{missing[-1]} are required for this operation")
  end
end

#write_attribute(name, value) ⇒ Object



139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/cistern/attributes.rb', line 139

def write_attribute(name, value)
  options = self.class.attributes[name] || {}

  transform = Cistern::Attributes.transforms[options[:squash] ? :squash : :none] ||
    Cistern::Attributes.default_transform

  parser = Cistern::Attributes.parsers[options[:type]] ||
    options[:parser] ||
    Cistern::Attributes.default_parser

  transformed = transform.call(name, value, options)

  new_value = parser.call(transformed, options)
  attribute = name.to_s.to_sym

  previous_value = attributes[attribute]

  attributes[attribute] = new_value

  changed!(attribute, previous_value, new_value)

  new_value
end