Module: Cistern::Attributes::InstanceMethods

Included in:
Model
Defined in:
lib/cistern/attributes.rb

Instance Method Summary collapse

Instance Method Details

#attributesObject



170
171
172
# File 'lib/cistern/attributes.rb', line 170

def attributes
  @attributes ||= {}
end

#changedObject



263
264
265
# File 'lib/cistern/attributes.rb', line 263

def changed
  @changes ||= {}
end

#clone_attributesObject



129
130
131
# File 'lib/cistern/attributes.rb', line 129

def clone_attributes
  Marshal.load Marshal.dump(attributes)
end

#dirty?Boolean

Returns:

  • (Boolean)


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

def dirty?
  changed.any?
end

#dirty_attributesObject



259
260
261
# File 'lib/cistern/attributes.rb', line 259

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

#dirty_request_attributesObject



275
276
277
# File 'lib/cistern/attributes.rb', line 275

def dirty_request_attributes
  request_attributes(dirty_attributes)
end

#dupObject



174
175
176
# File 'lib/cistern/attributes.rb', line 174

def dup
  super.tap { |m| m.set_attributes attributes.dup }
end

#identityObject



178
179
180
181
182
# File 'lib/cistern/attributes.rb', line 178

def identity
  key = self.class.identity

  public_send(key) if key
end

#identity=(new_identity) ⇒ Object



184
185
186
187
188
189
190
191
192
# File 'lib/cistern/attributes.rb', line 184

def identity=(new_identity)
  key = self.class.identity

  if key
    public_send("#{key}=", new_identity)
  else
    fail ArgumentError, 'Identity not specified'
  end
end

#merge_attributes(new_attributes = {}) ⇒ Object Also known as: attributes=

Update model’s attributes. New attributes take precedence over existing attributes.

This is bst called within a Model#save, when #new_attributes represents a recently presented remote resource. #dirty_attributes is cleared after merging.

Parameters:

  • new_attributes (Hash) (defaults to: {})

    attributes to merge with current attributes



200
201
202
203
204
205
206
# File 'lib/cistern/attributes.rb', line 200

def merge_attributes(new_attributes = {})
  _merge_attributes(new_attributes)

  changed.clear

  self
end

#new_record?Boolean

Returns:

  • (Boolean)


221
222
223
# File 'lib/cistern/attributes.rb', line 221

def new_record?
  identity.nil?
end

#read_attribute(name) ⇒ Object



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/cistern/attributes.rb', line 133

def read_attribute(name)
  key = name.to_sym

  options = self.class.attributes[key]
  default = options[:default]

  # record the attribute was accessed
  if defined?(Cistern::Coverage) && options[:coverage_hits]
    options[:coverage_hits] += 1
  end

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

  attributes.fetch(key, default)
end

#request_attributes(set = attributes) ⇒ Object



267
268
269
270
271
272
273
# File 'lib/cistern/attributes.rb', line 267

def request_attributes(set = attributes)
  set.inject({}) do |a,(k,v)|
    aliases = self.class.attributes[k.to_sym][:aliases]
    aliases << k if aliases.empty?
    aliases.each_with_object(a) { |n,r| r[n.to_s] = v }
  end
end

#requires(*args) ⇒ Hash

Require specification of certain attributes

Returns:

  • (Hash)

    of matching attributes

Raises:

  • (ArgumentError)

    if any requested attribute does not have a value



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

def requires(*args)
  missing, required = missing_attributes(args)

  if missing.length == 1
    fail(ArgumentError, "#{missing.keys.first} is required for this operation")
  elsif missing.any?
    fail(ArgumentError, "#{missing.keys[0...-1].join(', ')} and #{missing.keys[-1]} are required for this operation")
  end

  required
end

#requires_one(*args) ⇒ Hash

Require specification of one or more attributes.

Returns:

  • (Hash)

    of matching attributes

Raises:

  • (ArgumentError)

    if no requested attributes have values



245
246
247
248
249
250
251
252
253
# File 'lib/cistern/attributes.rb', line 245

def requires_one(*args)
  missing, required = missing_attributes(args)

  if missing.length == args.length
    fail(ArgumentError, "#{missing.keys[0...-1].join(', ')} or #{missing.keys[-1]} are required for this operation")
  end

  required
end

#stage_attributes(new_attributes = {}) ⇒ Object

Update model’s attributes. New attributes take precedence over existing attributes.

This is best called within a Model#update, when #new_attributes represents attributes to be presented to a remote service. #dirty_attributes will contain the valid portion of #new_attributes

Parameters:

  • new_attributes (Hash) (defaults to: {})

    attributes to merge with current attributes



216
217
218
219
# File 'lib/cistern/attributes.rb', line 216

def stage_attributes(new_attributes = {})
  _merge_attributes(new_attributes)
  self
end

#write_attribute(name, value) ⇒ Object



149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/cistern/attributes.rb', line 149

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

  transform = options[:transform]

  parser = options[:parser]

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

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

  previous_value = read_attribute(name)

  attributes[attribute] = new_value

  changed!(attribute, previous_value, new_value)

  new_value
end