Module: NormalizeIt::ClassMethods
- Defined in:
- lib/normalize_it.rb
Overview
normalize_it makes it easy to seamlessly manage database tables that have been normalized.
Example:
create_table :customer_statuses, :force => true do |t| t.string :customer_status end
create_table :email_addresses, :force => true do |t| t.string :email_address end
create_table :customers, :force => true do |t| t.string :name t.integer :customer_status_id t.integer :email_address_id end
class CustomerStatus < ActiveRecord::Base normalizes :customers, :with_field => :customer_status validates :customer_status, :presence => true validates_uniqueness_of :customer_status end
class EmailAddress < ActiveRecord::Base normalizes :customers, :allow_inserts => true validates :email_address, :presence => true validates_uniqueness_of :email_address end
class Customer < ActiveRecord::Base has_normalized :customer_status has_normalized :email_address, :allow_inserts => true end
after calling normalizes:
* if :allow_inserts is false (default), a :with_field argument must be passed in
** new objects of CustomerStatus may not be created by the app
** CustomerStatus objects may be referenced by [] notation, eg CustomerStatus[:new] or CustomerStatus['new']
** CustomerStatus is given a has_many association to Customer, has_many may be passed in to normalizes
* if :allow_inserts is true
** only the has_many association is set up
** [] notation may be used only if the :with_field option is passed
after calling has_normalized:
* if :allow_inserts is false (default)
** customer.customer_status = 'new' will only search for CustomerStatus['new'] and assign it if it is found
* if :allow_inserts is true
** customer.email_address = '[email protected]' will search for the email address, and create it if not found
* all columns on the normalized tables are delegated to the parent object. e.g. customer.email_address
* static rails-like finders may be used. e.g. Customer.find_by_email_address '[email protected]'
* new objects may be initialized either with attributes or through later assignment. e.g. Customer.new(:email_address => '[email protected]')
Instance Attribute Summary collapse
-
#_normalized_models ⇒ Object
readonly
Returns the value of attribute _normalized_models.
Instance Method Summary collapse
Instance Attribute Details
#_normalized_models ⇒ Object (readonly)
Returns the value of attribute _normalized_models.
63 64 65 |
# File 'lib/normalize_it.rb', line 63 def _normalized_models @_normalized_models end |
Instance Method Details
#has_normalized(model, options = {}) ⇒ Object
65 66 67 68 69 70 71 72 73 74 75 76 77 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 |
# File 'lib/normalize_it.rb', line 65 def has_normalized(model, = {}) include NormalizeIt::BaseClassMethods @_normalized_models ||= [] allow_inserts = .try(:delete, :allow_inserts) || false opts = { :class_name => model.to_s.camelize, :autosave => true, :foreign_key => model.to_s.foreign_key }.merge!() belongs_to "__#{opts[:class_name].underscore}".to_sym, opts validates "__#{opts[:class_name].underscore}".to_sym, :presence => true validates_associated "__#{opts[:class_name].underscore}".to_sym @_normalized_models << opts.merge( { :allow_inserts => allow_inserts } ) opts[:class_name].constantize.content_columns.each do |column| next if ['created_at', 'updated_at'].include?(column.name) delegate "#{column.name}", "#{column.name}?", :to => "__#{opts[:class_name].underscore}".to_sym if allow_inserts delegate "#{column.name}=", :to => "__#{opts[:class_name].underscore}".to_sym else self.class_eval do define_method "#{column.name}=" do |value| self.send("__#{opts[:class_name].underscore}=", value.is_a?(opts[:class_name].constantize) ? value : opts[:class_name].constantize[value] ) end end end eval " def self.find_by_\#{column.name} value\n self.send(\"find_by_\#{opts[:foreign_key]}\",\n \#{opts[:class_name]}.send(\"find_by_\#{column.name}\", value)\n )\n end\n def self.find_all_by_\#{column.name} value\n self.send(\"find_all_by_\#{opts[:foreign_key]}\",\n \#{opts[:class_name]}.send(\"find_by_\#{column.name}\", value)\n )\n end\n NEWFINDERS\n end\n\n before_validation :handle_normalized_objects if allow_inserts\nend\n" |
#normalizes(model, options = {}) ⇒ Object
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/normalize_it.rb', line 108 def normalizes(model, = {}) include NormalizeIt::NormalizedClassMethods allow_inserts = .try(:delete, :allow_inserts) || false if !allow_inserts normalized_field = .try(:delete, :with_field) raise NormalizeItException, "Normalized field must be specified on static tables!" unless normalized_field before_create :disallow_create unless allow_inserts if normalized_field eval " def self.[] value\n @@\#{self.name.underscore.pluralize} ||= HashWithIndifferentAccess.new\n @@\#{self.name.underscore.pluralize}[value] ||= find_by_\#{normalized_field.to_s}(value.to_s)\n @@\#{self.name.underscore.pluralize}[value]\n end\n HASHNOTATIONACCESS\n end\n end\n has_many model, options\nend\n" |