Module: ActiveRecord::Base::CompositeInstanceMethods

Defined in:
lib/composite_primary_keys/base.rb

Instance Method Summary collapse

Instance Method Details

#destroyObject



180
181
182
183
184
185
186
187
188
189
# File 'lib/composite_primary_keys/base.rb', line 180

def destroy
  if persisted?
    # CPK
    # self.class.unscoped.where(self.class.arel_table[self.class.primary_key].eq(id)).delete_all
    self.class.unscoped.where(ids_hash).delete_all
  end

  @destroyed = true
  freeze
end

#idObject Also known as: ids

A model instance’s primary keys is always available as model.ids whether you name it the default ‘id’ or set it to something else.



96
97
98
99
# File 'lib/composite_primary_keys/base.rb', line 96

def id
  attr_names = self.class.primary_keys
  CompositePrimaryKeys::CompositeKeys.new(attr_names.map { |attr_name| read_attribute(attr_name) })
end

#id=(ids) ⇒ Object

Sets the primary ID.



125
126
127
128
129
130
131
132
133
# File 'lib/composite_primary_keys/base.rb', line 125

def id=(ids)
  ids = ids.split(CompositePrimaryKeys::ID_SEP) if ids.is_a?(String)
  ids.flatten!
  unless ids.is_a?(Array) and ids.length == self.class.primary_keys.length
    raise "#{self.class}.id= requires #{self.class.primary_keys.length} ids"
  end
  [primary_keys, ids].transpose.each {|key, an_id| write_attribute(key , an_id)}
  id
end

#id_before_type_castObject

:nodoc:

Raises:



113
114
115
# File 'lib/composite_primary_keys/base.rb', line 113

def id_before_type_cast #:nodoc:
  raise CompositeKeyError, CompositePrimaryKeys::ActiveRecord::Base::NOT_IMPLEMENTED_YET
end

#ids_hashObject



102
103
104
105
106
107
# File 'lib/composite_primary_keys/base.rb', line 102

def ids_hash
  self.class.primary_key.zip(ids).inject(Hash.new) do |hash, (key, value)|
    hash[key] = value
    hash
  end
end

#initialize_copy(other) ⇒ Object

Cloned objects have no id assigned and are treated as new records. Note that this is a “shallow” clone as it copies the object’s attributes only, not its associations. The extent of a “deep” clone is application specific and is therefore left to the application to implement according to its need.



153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/composite_primary_keys/base.rb', line 153

def initialize_copy(other)
  # Think the assertion which fails if the after_initialize callback goes at the end of the method is wrong. The
  # deleted clone method called new which therefore called the after_initialize callback. It then went on to copy
  # over the attributes. But if it's copying the attributes afterwards then it hasn't finished initializing right?
  # For example in the test suite the topic model's after_initialize method sets the author_email_address to
  # [email protected]. I would have thought this would mean that all cloned models would have an author email address
  # of [email protected]. However the test_clone test method seems to test that this is not the case. As a result the
  # after_initialize callback has to be run *before* the copying of the atrributes rather than afterwards in order
  # for all tests to pass. This makes no sense to me.
  callback(:after_initialize) if respond_to_without_attributes?(:after_initialize)
  cloned_attributes = other.clone_attributes(:read_attribute_before_type_cast)
  # CPK
  #cloned_attributes.delete(self.class.primary_key)
  self.class.primary_key.each {|key| cloned_attributes.delete(key.to_s)}

  @attributes = cloned_attributes
  clear_aggregation_cache
  @attributes_cache = {}
  @new_record = true
  ensure_proper_type

  if scope = self.class.send(:current_scoped_methods)
    create_with = scope.scope_for_create
    create_with.each { |att,value| self.send("#{att}=", value) } if create_with
  end
end

#quoted_idObject

:nodoc:



117
118
119
120
121
122
# File 'lib/composite_primary_keys/base.rb', line 117

def quoted_id #:nodoc:
  [self.class.primary_keys, ids].
    transpose.
    map {|attr_name,id| quote_value(id, column_for_attribute(attr_name))}.
    to_composite_ids
end

#to_paramObject



109
110
111
# File 'lib/composite_primary_keys/base.rb', line 109

def to_param
  id.to_s
end

#update(attribute_names = @attributes.keys) ⇒ Object



191
192
193
194
195
196
197
# File 'lib/composite_primary_keys/base.rb', line 191

def update(attribute_names = @attributes.keys)
  attributes_with_values = arel_attributes_values(false, false, attribute_names)
  return 0 if attributes_with_values.empty?
  # CPK
  # self.class.unscoped.where(self.class.arel_table[self.class.primary_key].eq(id)).arel.update(attributes_with_values)
  self.class.unscoped.where(ids_hash).arel.update(attributes_with_values)
end

#update_attribute(name, value) ⇒ Object

Raises:

  • (ActiveRecordError)


135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/composite_primary_keys/base.rb', line 135

def update_attribute(name, value)
  raise ActiveRecordError, "#{name.to_s} is marked as readonly" if self.class.readonly_attributes.include? name.to_s

  changes = {}

  if name
    name = name.to_s
    send("#{name}=", value)
    changes[name] = read_attribute(name)
  end

  @changed_attributes.except!(*changes.keys)
  self.class.update_all(changes, ids_hash) == 1
end