Module: DattsRight::InstanceMethods
- Defined in:
- lib/datts_right/instance_methods.rb
Instance Method Summary collapse
- #add_definition(key, value) ⇒ Object
- #add_definitions(*args) ⇒ Object
- #add_dynamic_attribute(name, object_type, value = nil) ⇒ Object (also: #add_datt)
- #add_dynamic_attribute!(name, object_type, value = nil) ⇒ Object (also: #add_datt!)
- #attributes=(new_attributes, guard_protected_attributes = true) ⇒ Object
- #create_dynamic_attribute_definition_if_needed ⇒ Object
-
#defined? ⇒ Boolean
Returns true if this is defined by any other class.
-
#defined_by?(arg) ⇒ Boolean
Returns true if the calling instance is defined by the argument.
-
#defines ⇒ Object
Returns an array of symbols of the classes that this defines.
-
#defines?(klass = nil) ⇒ Boolean
Returns true if this defines any other class.
- #defining_record ⇒ Object
-
#dynamic_attribute?(attr) ⇒ Boolean
Determines if the given attribute is a dynamic attribute.
-
#dynamic_attribute_details(key) ⇒ Object
(also: #datt_details)
Give users access to the cache.
-
#inherit_definition! ⇒ Object
Adds dynamic attributes to inheriting model, based on the definition of the defining model.
-
#read_dynamic_attribute(attr_name) ⇒ Object
(also: #read_datt)
Like AR::Base#read_attribute.
- #remove_definition(key) ⇒ Object
- #remove_definitions(*array) ⇒ Object
- #remove_dynamic_attribute(name) ⇒ Object (also: #remove_datt)
-
#sync_definition! ⇒ Object
Adds and removes dynamic attributes based on the defining record.
- #update_definition(key, new_values = {}) ⇒ Object
- #update_definitions(hash = {}) ⇒ Object
- #update_dynamic_attributes(attributes) ⇒ Object
- #update_dynamic_attributes!(attributes) ⇒ Object
-
#write_dynamic_attribute(attr_name, value) ⇒ Object
(also: #write_datt, #update_dynamic_attribute)
Like AR::Base#write_attribute.
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method_id, *args, &body) ⇒ Object (private)
307 308 309 310 311 312 313 314 315 316 317 318 |
# File 'lib/datts_right/instance_methods.rb', line 307 def method_missing(method_id, *args, &body) begin super(method_id, *args, &body) rescue NoMethodError => e attr_name = method_id.to_s.sub(/\=$/, '') if dynamic_attribute?(attr_name) method_id.to_s =~ /\=$/ ? write_dynamic_attribute(attr_name, args[0]) : read_dynamic_attribute(attr_name) else raise NoMethodError end end end |
Instance Method Details
#add_definition(key, value) ⇒ Object
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 |
# File 'lib/datts_right/instance_methods.rb', line 125 def add_definition(key, value) if key key = key.to_sym #puts "add_definition(:#{key}, #{value.inspect}). current definition: #{definition.nil?}" if [:defines].nil? || [:defines].empty? raise NoDefinitionError else #puts ":definition is true, so let's see if definition[:#{key}] already exists" # Checking definition straight seems to cause a problem. Is this a bug with Rails? # The problem was like this (assuming definition was actually nil): # definition.nil? # false # definition.inspect # nil # definition.class.name # NilClass # # How in the world can .nil? return false when it was nil?? dynamic_attribute_definition.definition ||= {} if definition[key] raise AlreadyDefined, "#{key} is already defined" else definition.merge!({key => value}) end end else raise AttributeKeyRequired end end |
#add_definitions(*args) ⇒ Object
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 179 180 |
# File 'lib/datts_right/instance_methods.rb', line 153 def add_definitions(*args) attributes = args attributes.compact! if attributes#remove the nil items #puts "args after compacting: #{attributes.inspect}" attributes.flatten! if args.first.is_a?(Array) && attributes #puts "args after flattening: #{attributes.inspect}" attributes.each do |item| #puts "Working on #{item.inspect} is is a hash? (#{item.is_a?(Hash)}) or something else?" item.each do |k, v| #puts "Working on this k,v pair: #{k.inspect} => #{v.inspect}" if v.is_a?(Hash) # item is like :robot => {:object_type => "text"}, :robot@ => {:object_type => "text"} #puts "#{v} IS a hash" add_definition k, v else # v is not a hash; item is like {"name"=>"A key", "attr_key"=>"a_key"}, {"name"=>"B key", "attr_key"=>"b_key"} # Sometimes the item is a ActiveRecord::HashWithIndifferentAccess, which doesn't have the method symbolize_keys!, so we do it manually #item = item.symbolize_keys # {:name=>"A key", :description=>"asd", :attr_key=>"a_key"} #puts "item is symbolized: #{item.inspect}" attr_key = item.delete("attr_key") #puts "This is the attr_key: #{attr_key}" if attr_key # we only want to work on it if there's an attr_key attr_key = attr_key.to_sym #puts "Adding: :#{attr_key}, #{item.inspect}" add_definition(attr_key, item) end end end end end |
#add_dynamic_attribute(name, object_type, value = nil) ⇒ Object Also known as: add_datt
3 4 5 6 7 8 9 10 11 12 |
# File 'lib/datts_right/instance_methods.rb', line 3 def add_dynamic_attribute(name, object_type, value=nil) key = name.to_s.underscore return false if self.class.columns_hash[key] # if key already exists as a normal attribute unless dynamic_attribute?(key) new_dynamic_attribute = dynamic_attributes.new :attr_key => key, :object_type => object_type, "#{object_type}_value".to_sym => value @dynamic_attributes_cache[key.to_sym] = new_dynamic_attribute return new_dynamic_attribute end return false end |
#add_dynamic_attribute!(name, object_type, value = nil) ⇒ Object Also known as: add_datt!
14 15 16 17 18 |
# File 'lib/datts_right/instance_methods.rb', line 14 def add_dynamic_attribute!(name, object_type, value=nil) dynamic_attribute = add_dynamic_attribute(name, object_type, value) dynamic_attribute.save if dynamic_attribute key = name.to_s.underscore end |
#attributes=(new_attributes, guard_protected_attributes = true) ⇒ Object
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 |
# File 'lib/datts_right/instance_methods.rb', line 82 def attributes=(new_attributes, guard_protected_attributes = true) return unless new_attributes.is_a?(Hash) attributes = new_attributes.stringify_keys multi_parameter_attributes = [] attributes = sanitize_for_mass_assignment(attributes) if guard_protected_attributes attributes.each do |k, v| if k.include?("(") multi_parameter_attributes << [ k, v ] else #respond_to?(:"#{k}=") ? send(:"#{k}=", v) : raise(UnknownAttributeError, "unknown attribute: #{k}") begin #puts "Attempt to set super #{k} to #{v}" #puts "Checking to see if #{self.inspect} responds to #{k}= ........... #{self.class.name}##{self.class.respond_to?(:"#{k}=")}, or the record itself: #{respond_to?(:"#{k}=")}" respond_to?(:"#{k}=") ? send(:"#{k}=", v) : raise(ActiveRecord::UnknownAttributeError, "unknown attribute: #{k}") #send("#{k}=", v) #puts "Set super #{k} to #{v}" rescue ActiveRecord::UnknownAttributeError => e #puts "ActiveRecord::UnknownAttributeError was raised: #{e}, so we now check to see if '#{k}' is dynamic_attribute" if dynamic_attribute?(k) write_dynamic_attribute("#{k}", v) else raise ActiveRecord::UnknownAttributeError, "unknown attribute: #{k}" end end end end assign_multiparameter_attributes(multi_parameter_attributes) end |
#create_dynamic_attribute_definition_if_needed ⇒ Object
119 120 121 122 123 |
# File 'lib/datts_right/instance_methods.rb', line 119 def create_dynamic_attribute_definition_if_needed if self.defines? DynamicAttributeDefinition.create :attribute_defineable_id => self.id, :attribute_defineable_type => self.class.name, :definition => {} end end |
#defined? ⇒ Boolean
Returns true if this is defined by any other class
269 270 271 |
# File 'lib/datts_right/instance_methods.rb', line 269 def defined? self.class.defined? end |
#defined_by?(arg) ⇒ Boolean
Returns true if the calling instance is defined by the argument
274 275 276 |
# File 'lib/datts_right/instance_methods.rb', line 274 def defined_by?(arg) self.class.defined_by?(arg) end |
#defines ⇒ Object
Returns an array of symbols of the classes that this defines
279 280 281 |
# File 'lib/datts_right/instance_methods.rb', line 279 def defines self.class.defines end |
#defines?(klass = nil) ⇒ Boolean
Returns true if this defines any other class
264 265 266 |
# File 'lib/datts_right/instance_methods.rb', line 264 def defines?(klass=nil) self.class.defines?(klass) end |
#defining_record ⇒ Object
114 115 116 117 |
# File 'lib/datts_right/instance_methods.rb', line 114 def defining_record return nil if [:of].nil? send [:of].to_s end |
#dynamic_attribute?(attr) ⇒ Boolean
Determines if the given attribute is a dynamic attribute.
35 36 37 |
# File 'lib/datts_right/instance_methods.rb', line 35 def dynamic_attribute?(attr) !@dynamic_attributes_cache[attr.to_sym].nil? end |
#dynamic_attribute_details(key) ⇒ Object Also known as: datt_details
Give users access to the cache
30 31 32 |
# File 'lib/datts_right/instance_methods.rb', line 30 def dynamic_attribute_details(key) @dynamic_attributes_cache[key] end |
#inherit_definition! ⇒ Object
Adds dynamic attributes to inheriting model, based on the definition of the defining model.
class InheritingModel < AR::Base
has_dynamic_attributes :of => :defining_model
end
The DefiningModel should have the code:
class DefiningModel < AR::Base
has_dynamic_attributes :defines => [:inheriting_model]
end
Example:
@defining_model.add_definitions(:name => {:object_type => "string"}, :body => {:object_type => "text"})
@defining_model.save
InheritingModel.create # creates an instance with dynamic attributes: name and body, that are "string" and "text", respectively
Calling this method manually only adds to the inheriting instance you call it on. If you remove some definitions from the defining model, then you call @inheriting_model.inherit_definition!@, the new definitions will be added. If there are no new definitions, nothing will happen.
239 240 241 242 243 244 245 246 247 248 249 250 |
# File 'lib/datts_right/instance_methods.rb', line 239 def inherit_definition! #puts "In inherit_definition" #puts "------- #{dynamic_attributes_options[:of]}" #dynamic_attribute_definition.create if dynamic_attributes_options[:definition] if self.defined? && defining_record defining_record.definition.each do |k, v| datt = add_dynamic_attribute(k, v[:object_type]) datt.dynamic_attribute_definition #puts "Added #{datt.inspect}" end end end |
#read_dynamic_attribute(attr_name) ⇒ Object Also known as: read_datt
Like AR::Base#read_attribute
60 61 62 63 64 65 66 |
# File 'lib/datts_right/instance_methods.rb', line 60 def read_dynamic_attribute(attr_name) attr_name = attr_name.to_sym if dynamic_attribute?(attr_name) #puts "Reading #{attr_name}. The whole cache: #{@dynamic_attributes_cache.inspect}" @dynamic_attributes_cache[attr_name].value end end |
#remove_definition(key) ⇒ Object
206 207 208 209 210 211 212 213 |
# File 'lib/datts_right/instance_methods.rb', line 206 def remove_definition(key) if key key = key.to_sym raise NoDefinitionError unless self.defines? raise NotDefinedError, "#{key} is not defined" unless definition && definition[key] definition.delete(key) end end |
#remove_definitions(*array) ⇒ Object
215 216 217 218 219 220 221 |
# File 'lib/datts_right/instance_methods.rb', line 215 def remove_definitions(*array) if array array.each do |a| remove_definition a end end end |
#remove_dynamic_attribute(name) ⇒ Object Also known as: remove_datt
20 21 22 23 24 25 26 27 |
# File 'lib/datts_right/instance_methods.rb', line 20 def remove_dynamic_attribute(name) # Remove from the cache @dynamic_attributes_cache.delete(name.to_sym) # Then remove from the db dynamic_attribute = dynamic_attributes.find_by_attr_key(name.to_s) dynamic_attribute.destroy if dynamic_attribute end |
#sync_definition! ⇒ Object
Adds and removes dynamic attributes based on the defining record
253 254 255 256 257 258 259 260 261 |
# File 'lib/datts_right/instance_methods.rb', line 253 def sync_definition! defining_record.definition.each do |k, v| add_dynamic_attribute(k, v[:object_type]) if dynamic_attribute_details(k).nil? end @dynamic_attributes_cache.each do |k, v| #puts "Remove #{k}?" remove_dynamic_attribute(k) if v.definer.nil? end end |
#update_definition(key, new_values = {}) ⇒ Object
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 |
# File 'lib/datts_right/instance_methods.rb', line 182 def update_definition(key, new_values={}) raise NoDefinitionError unless self.defines? raise NotDefinedError, "#{key} is not defined" unless definition && definition[key] attr_key = new_values.symbolize_keys[:attr_key] new_values.each do |k, v| definition[key][k] = v unless k.to_s == "attr_key" end #puts "attr_key is #{attr_key}, key is #{key}" if attr_key && attr_key != key.to_s #puts "Adding definition: #{attr_key} => #{definition[key]}" add_definition(attr_key, definition[key]) #puts "Removing definition: #{key} => #{definition[key]}" remove_definition(key) end end |
#update_definitions(hash = {}) ⇒ Object
200 201 202 203 204 |
# File 'lib/datts_right/instance_methods.rb', line 200 def update_definitions(hash={}) hash.each do |k, v| update_definition k, v end end |
#update_dynamic_attributes(attributes) ⇒ Object
39 40 41 42 43 44 45 46 47 48 |
# File 'lib/datts_right/instance_methods.rb', line 39 def update_dynamic_attributes(attributes) # The following transaction covers any possible database side-effects of the # attributes assignment. For example, setting the IDs of a child collection. with_transaction_returning_status do attributes.symbolize_keys.each do |k, v| self.write_dynamic_attribute(k, v) end save end end |
#update_dynamic_attributes!(attributes) ⇒ Object
50 51 52 53 54 55 56 57 |
# File 'lib/datts_right/instance_methods.rb', line 50 def update_dynamic_attributes!(attributes) with_transaction_returning_status do attributes.symbolize_keys.each do |k, v| self.write_dynamic_attribute(k, v) end save! end end |
#write_dynamic_attribute(attr_name, value) ⇒ Object Also known as: write_datt, update_dynamic_attribute
Like AR::Base#write_attribute
69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/datts_right/instance_methods.rb', line 69 def write_dynamic_attribute(attr_name, value) #puts "attempting to write: #{attr_name} = #{value}" attr_name = attr_name.to_sym if dynamic_attribute?(attr_name) #puts "#{attr_name} is a dynamic_attribute" #puts "Writing @dynamic_attributes_cache[:#{attr_name}].value = #{value}" dynamic_attribute = @dynamic_attributes_cache[attr_name] dynamic_attribute.value = value #puts "In write_dynamic_attribute. Full cache: #{@dynamic_attributes_cache.inspect}" return dynamic_attribute.value end end |