]> git.openstreetmap.org Git - rails.git/blobdiff - vendor/gems/composite_primary_keys-1.1.0/lib/composite_primary_keys/attribute_methods.rb
Freezing composite primary key so that we can apply TomH's patch to it, and that...
[rails.git] / vendor / gems / composite_primary_keys-1.1.0 / lib / composite_primary_keys / attribute_methods.rb
diff --git a/vendor/gems/composite_primary_keys-1.1.0/lib/composite_primary_keys/attribute_methods.rb b/vendor/gems/composite_primary_keys-1.1.0/lib/composite_primary_keys/attribute_methods.rb
new file mode 100644 (file)
index 0000000..a0e3331
--- /dev/null
@@ -0,0 +1,84 @@
+module CompositePrimaryKeys
+  module ActiveRecord
+    module AttributeMethods #:nodoc:
+      def self.append_features(base)
+        super
+        base.send(:extend, ClassMethods)
+      end
+
+      module ClassMethods
+        # Define an attribute reader method.  Cope with nil column.
+        def define_read_method(symbol, attr_name, column)
+          cast_code = column.type_cast_code('v') if column
+          cast_code = "::#{cast_code}" if cast_code && cast_code.match('ActiveRecord::.*')
+          access_code = cast_code ? "(v=@attributes['#{attr_name}']) && #{cast_code}" : "@attributes['#{attr_name}']"
+
+          unless self.primary_keys.include?(attr_name.to_sym)
+            access_code = access_code.insert(0, "missing_attribute('#{attr_name}', caller) unless @attributes.has_key?('#{attr_name}'); ")
+          end
+
+          if cache_attribute?(attr_name)
+            access_code = "@attributes_cache['#{attr_name}'] ||= (#{access_code})"
+          end
+
+          evaluate_attribute_method attr_name, "def #{symbol}; #{access_code}; end"
+        end
+
+        # Evaluate the definition for an attribute related method
+        def evaluate_attribute_method(attr_name, method_definition, method_name=attr_name)
+          unless primary_keys.include?(method_name.to_sym)
+            generated_methods << method_name
+          end
+
+          begin
+            class_eval(method_definition, __FILE__, __LINE__)
+          rescue SyntaxError => err
+            generated_methods.delete(attr_name)
+            if logger
+              logger.warn "Exception occurred during reader method compilation."
+              logger.warn "Maybe #{attr_name} is not a valid Ruby identifier?"
+              logger.warn "#{err.message}"
+            end
+          end
+        end
+      end
+
+      # Allows access to the object attributes, which are held in the @attributes hash, as though they
+      # were first-class methods. So a Person class with a name attribute can use Person#name and
+      # Person#name= and never directly use the attributes hash -- except for multiple assigns with
+      # ActiveRecord#attributes=. A Milestone class can also ask Milestone#completed? to test that
+      # the completed attribute is not nil or 0.
+      #
+      # It's also possible to instantiate related objects, so a Client class belonging to the clients
+      # table with a master_id foreign key can instantiate master through Client#master.
+      def method_missing(method_id, *args, &block)
+        method_name = method_id.to_s
+
+        # If we haven't generated any methods yet, generate them, then
+        # see if we've created the method we're looking for.
+        if !self.class.generated_methods?
+          self.class.define_attribute_methods
+
+          if self.class.generated_methods.include?(method_name)
+            return self.send(method_id, *args, &block)
+          end
+        end
+
+        if self.class.primary_keys.include?(method_name.to_sym)
+          ids[self.class.primary_keys.index(method_name.to_sym)]
+        elsif md = self.class.match_attribute_method?(method_name)
+          attribute_name, method_type = md.pre_match, md.to_s
+          if @attributes.include?(attribute_name)
+            __send__("attribute#{method_type}", attribute_name, *args, &block)
+          else
+            super
+          end
+        elsif @attributes.include?(method_name)
+          read_attribute(method_name)
+        else
+          super
+        end
+      end
+    end
+  end
+end