Module: Cistern::Attributes::InstanceMethods

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

Instance Method Summary collapse

Instance Method Details

#attributesObject



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

def attributes
  @attributes ||= {}
end

#attributes=(attributes) ⇒ Object



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

def attributes=(attributes)
  @attributes = attributes
end

#changedObject



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

def changed
  @changes ||= {}
end

#dirty?Boolean

Returns:

  • (Boolean)


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

def dirty?
  changed.any?
end

#dirty_attributesObject



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

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

#dirty_request_attributesObject



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

def dirty_request_attributes
  request_attributes(dirty_attributes)
end

#dumpObject



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

def dump
  Marshal.dump(attributes)
end

#dupObject



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

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

#identityObject



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

def identity
  key = self.class.identity

  public_send(key) if key
end

#identity=(new_identity) ⇒ Object



187
188
189
190
191
192
193
194
195
# File 'lib/cistern/attributes.rb', line 187

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

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



203
204
205
206
207
208
209
# File 'lib/cistern/attributes.rb', line 203

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

  changed.clear

  self
end

#new_record?Boolean

Returns:

  • (Boolean)


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

def new_record?
  identity.nil?
end

#read_attribute(name) ⇒ Object



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

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



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

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



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

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



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

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



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

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

#write_attribute(name, value) ⇒ Object



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

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