Module: Cistern::Attributes::InstanceMethods

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

Instance Method Summary collapse

Instance Method Details

#attributesObject



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

def attributes
  @attributes ||= {}
end

#attributes=(attributes) ⇒ Object



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

def attributes=(attributes)
  @attributes = attributes
end

#changedObject



267
268
269
# File 'lib/cistern/attributes.rb', line 267

def changed
  @changes ||= {}
end

#dirty?Boolean

Returns:

  • (Boolean)


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

def dirty?
  changed.any?
end

#dirty_attributesObject



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

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

#dumpObject



121
122
123
# File 'lib/cistern/attributes.rb', line 121

def dump
  Marshal.dump(attributes)
end

#dupObject



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

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

#identityObject



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

def identity
  key = self.class.instance_variable_get('@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.instance_variable_get('@identity')

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

#merge_attributes(new_attributes = {}) ⇒ Object



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
225
226
227
228
229
230
231
232
233
234
235
236
# File 'lib/cistern/attributes.rb', line 194

def merge_attributes(new_attributes = {})
  protected_methods  = (Cistern::Model.instance_methods - PROTECTED_METHODS)
  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.is_a?(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

    next if ignored_attributes.include?(symbol_key)

    if class_aliases.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

  changed.clear

  self
end

#new_record?Boolean

Returns:

  • (Boolean)


238
239
240
# File 'lib/cistern/attributes.rb', line 238

def new_record?
  identity.nil?
end

#read_attribute(name) ⇒ Object



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

def read_attribute(name)
  key = name.to_s.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

#requires(*args) ⇒ Object

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



243
244
245
246
247
248
249
250
# File 'lib/cistern/attributes.rb', line 243

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

#requires_one(*args) ⇒ Object



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

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

#write_attribute(name, value) ⇒ Object



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

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