Module: Zermelo::Records::InstMethods

Included in:
Zermelo::Record
Defined in:
lib/zermelo/records/instance_methods.rb

Overview

module renamed to avoid ActiveSupport::Concern deprecation warning

Instance Method Summary collapse

Instance Method Details

#destroyObject



166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/zermelo/records/instance_methods.rb', line 166

def destroy
  raise "Record was not persisted" unless persisted?

  run_callbacks :destroy do

    assoc_classes = self.class.send(:associated_classes)
    index_attrs   = self.class.send(:with_index_data) {|d| d.keys }

    self.class.lock(*assoc_classes) do
      self.class.send(:with_associations, self) do |assoc|
        assoc.send(:on_remove)
      end

      self.class.transaction do
        self.class.delete_id(@attributes['id'])
        index_attrs.each do |att|
          idx = self.class.send("#{att}_index")
          idx.delete_id( @attributes['id'], @attributes[att.to_s])
        end

        self.class.attribute_types.each_pair {|name, type|
          key = Zermelo::Records::Key.new(:klass => self.class,
            :id => self.id, :name => name.to_s, :type => type, :object => :attribute)
          backend.clear(key)
        }

        record_key = Zermelo::Records::Key.new(:klass => self.class,
            :id => self.id)
        backend.purge(record_key)
      end
    end
  end
end

#initialize(attrs = {}) ⇒ Object



10
11
12
13
14
15
16
# File 'lib/zermelo/records/instance_methods.rb', line 10

def initialize(attrs = {})
  @is_new = true
  @attributes = self.class.attribute_types.keys.inject({}) do |memo, ak|
    memo[ak.to_s] = attrs[ak]
    memo
  end
end

#key_dumpObject



200
201
202
203
204
205
206
207
208
209
210
211
212
213
# File 'lib/zermelo/records/instance_methods.rb', line 200

def key_dump
  inst_keys = []

  attr_key = attribute_keys.values.first
  unless attr_key.nil?
    inst_keys += [backend.key_to_backend_key(attr_key), attr_key]
  end

  self.class.send(:with_associations, self) do |assoc|
    inst_keys += assoc.key_dump
  end

  Hash[*inst_keys]
end

#load(id) ⇒ Object



22
23
24
25
# File 'lib/zermelo/records/instance_methods.rb', line 22

def load(id)
  self.id = id
  refresh
end

#persisted?Boolean

Returns:

  • (Boolean)


18
19
20
# File 'lib/zermelo/records/instance_methods.rb', line 18

def persisted?
  !@is_new
end

#refreshObject



27
28
29
30
31
32
33
34
35
36
37
38
39
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
# File 'lib/zermelo/records/instance_methods.rb', line 27

def refresh
  # AM::Dirty -- private method 'clear_changes_information' in 4.2.0+,
  # private method 'reset_changes' in 4.1.0+, internal state before that
  if self.respond_to?(:clear_changes_information, true)
    clear_changes_information
  elsif self.respond_to?(:reset_changes, true)
    reset_changes
  else
    @previously_changed.clear unless @previously_changed.nil?
    @changed_attributes.clear
  end

  attr_types = self.class.attribute_types

  @attributes = {'id' => self.id}

  attrs = nil

  self.class.lock do
    class_key = self.class.send(:class_key)

    # TODO: check for record existence in backend-agnostic fashion
    # TODO fail if id not found
    @is_new = false

    attr_types = self.class.attribute_types.reject {|k, v| k == :id}

    attrs_to_load = attr_types.collect do |name, type|
      Zermelo::Records::Key.new(:klass => self.class,
        :id => self.id, :name => name, :type => type, :object => :attribute)
    end

    result = backend.get_multiple(*attrs_to_load)
    attrs = result[class_key][self.id] unless result.empty?
  end

  @attributes.update(attrs) unless attrs.nil? || attrs.empty?
  true
end

#saveObject



160
161
162
163
164
# File 'lib/zermelo/records/instance_methods.rb', line 160

def save
  save!
rescue Zermelo::Records::Errors::RecordInvalid, Zermelo::Records::Errors::RecordNotSaved
  false
end

#save!Object



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
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
150
151
152
153
154
155
156
157
158
# File 'lib/zermelo/records/instance_methods.rb', line 78

def save!
  return unless @is_new || self.changed?
  self.id ||= self.class.generate_id
  raise Zermelo::Records::Errors::RecordInvalid.new(self) unless valid?

  creating = !self.persisted?
  saved = false

  sort_val = nil
  case self
  when Zermelo::Records::Ordered
    sort_attr = self.class.instance_variable_get('@sort_attribute')
    raise 'Ordered record types must define_sort_attribute' if sort_attr.nil?
    sort_val = @attributes[sort_attr.to_s]
    raise "Value required for sort_attribute #{sort_attr}" if sort_val.nil?
  end

  run_callbacks( (creating ? :create : :update) ) do

    idx_attrs = self.class.send(:with_index_data) do |d|
      d.each_with_object({}) do |(name, data), memo|
        memo[name.to_s] = data.index_klass
      end
    end

    self.class.transaction do

      apply_attribute = proc {|att, attr_key, old_new|
        backend.set(attr_key, old_new.last) unless att.eql?('id')

        if idx_attrs.has_key?(att)
          # update indices
          if creating
            self.class.send("#{att}_index").add_id( @attributes['id'], old_new.last)
          else
            self.class.send("#{att}_index").move_id( @attributes['id'], old_new.first,
                            self.class.send("#{att}_index"), old_new.last)
          end
        end
      }

      attr_keys = attribute_keys

      if creating
        attr_keys.each_pair do |att, attr_key|
          apply_attribute.call(att, attr_key, [nil, @attributes[att]])
        end
      else
        self.changes.each_pair do |att, old_new|
          apply_attribute.call(att, attr_keys[att], old_new)
        end
      end

      # ids is a set/sorted set, so update won't create duplicates
      # NB influxdb backend doesn't need this

      # FIXME distinguish between this in the class methods?
      case self
      when Zermelo::Records::Ordered
        self.class.add_id(@attributes['id'], sort_val)
      when Zermelo::Records::Unordered
        self.class.add_id(@attributes['id'])
      end
    end

    @is_new = false
    saved = true
  end

  raise Zermelo::Records::Errors::RecordNotSaved.new(self) unless saved

  # AM::Dirty -- private method in 4.1.0+, internal state before that
  if self.respond_to?(:changes_applied, true)
    changes_applied
  else
    @previously_changed = changes
    @changed_attributes.clear
  end

  true
end

#update_attributes(attributes = {}) ⇒ Object

TODO limit to only those attribute names defined in define_attributes



68
69
70
71
72
73
74
75
76
# File 'lib/zermelo/records/instance_methods.rb', line 68

def update_attributes(attributes = {})
  attributes.each_pair do |att, v|
    unless value == @attributes[att.to_s]
      @attributes[att.to_s] = v
      send("#{att}_will_change!")
    end
  end
  save
end