Permalink
Browse files

git-svn-id: http://svn.viney.net.nz/things/rails/plugins/active_recor…

…d_defaults@295 20afb1e0-9c0e-0410-9884-91ed27886737
  • Loading branch information...
jonathan
jonathan committed Sep 14, 2007
2 parents 9c566a6 + d99e480 commit 87e636573c82fae95746e10ac4fc7b08f0504bbf
Showing with 82 additions and 28 deletions.
  1. +6 −0 CHANGELOG
  2. +10 −3 README
  3. +45 −12 lib/active_record_defaults.rb
  4. +2 −2 test/abstract_unit.rb
  5. +3 −0 test/active_record_defaults_test.rb
  6. +6 −2 test/fixtures/person.rb
  7. +10 −9 test/schema.rb
View
@@ -1,3 +1,9 @@
+[25 Jul 07]
+
+* Using a symbol as a default value will cause the return value of the method with that name to be the default.
+
+* Documentation updates.
+
[24 Nov 06]
* Make plugin work with composed_of [Problem reported by Dan Kubb]
View
13 README
@@ -1,5 +1,12 @@
-Active Record Defaults
-======================
+= Active Record Defaults
+
+If you find this plugin useful, please consider a donation to show your support!
+
+ http://www.paypal.com/cgi-bin/webscr?cmd=_send-money
+
+ Email address: jonathan.viney@gmail.com
+
+== Instructions
Allow you to easily specify default values for attributes on new model objects. Eg:
@@ -29,7 +36,7 @@ The default value is only used if the attribute is not present in the attributes
== Installation
- script/plugin install http://svn.viney.net.nz/things/rails/plugins/activerecord_defaults
+ script/plugin install http://svn.viney.net.nz/things/trunk/rails_plugins/active_record_defaults
== Help
@@ -11,18 +11,28 @@ def self.included(base)
end
module ClassMethods
- # Define default values for attributes on new records. Requires a hash of <tt>attribute => value</tt> pairs,
- # or a single attribute with an associated block.
- # The value can be a specific object, like a string or an integer, or a Proc that returns the default value when called.
+ # Define default values for attributes on new records. Requires a hash of <tt>attribute => value</tt> pairs, or a single attribute with an associated block.
+ # If the value is a block, it will be called to retrieve the default value.
+ # If the value is a symbol, a method by that name will be called on the object to retrieve the default value.
+ #
+ # The following code demonstrates the different ways default values can be specified. Defaults are applied in the order they are defined.
#
# class Person < ActiveRecord::Base
- # defaults :name => 'My name', :city => Proc.new { 'My city' }
+ # defaults :name => 'My name', :city => lambda { 'My city' }
#
- # defaults :birthdate do |person|
+ # default :birthdate do |person|
# Date.today if person.wants_birthday_today?
# end
+ #
+ # default :favourite_colour => :default_favourite_colour
+ #
+ # def default_favourite_colour
+ # "Blue"
+ # end
# end
- #
+ #
+ # The <tt>defaults</tt> and the <tt>default</tt> methods behave the same way. Use whichever is appropriate.
+ #
# The default values are only used if the key is not present in the given attributes.
#
# p = Person.new
@@ -32,6 +42,25 @@ module ClassMethods
# p = Person.new(:name => nil)
# p.name # nil
# p.city # "My city"
+ #
+ # == Default values for belongs_to associations
+ #
+ # Default values can also be specified for an association. For instance:
+ #
+ # class Student < ActiveRecord::Base
+ # belongs_to :school
+ # default :school => lambda { School.new }
+ # end
+ #
+ # In this scenario, if a school_id was provided in the attributes hash, the default value for the association will be ignored:
+ #
+ # s = Student.new
+ # s.school # => #<School: ...>
+ #
+ # s = Student.new(:school_id => nil)
+ # s.school # => nil
+ #
+ # Similarly, if a default value is specified for the foreign key and an object for the association is provided, the default foreign key is ignored.
def defaults(defaults, &block)
default_objects = case
when defaults.is_a?(Hash)
@@ -41,7 +70,7 @@ def defaults(defaults, &block)
Default.new(defaults, block)
else
- raise "pass either a hash of attribute/default pairs, or a single attribute with a block"
+ raise "pass either a hash of attribute/value pairs, or a single attribute with a block"
end
write_inheritable_array :attribute_defaults, [*default_objects]
@@ -53,8 +82,12 @@ def defaults(defaults, &block)
module InstanceMethods
def initialize_with_defaults(attributes = nil)
initialize_without_defaults(attributes)
-
- attribute_keys = (attributes || {}).keys.map(&:to_s)
+ apply_default_attribute_values(attributes)
+ yield self if block_given?
+ end
+
+ def apply_default_attribute_values(attributes)
+ attribute_keys = (attributes || {}).keys.map!(&:to_s)
if attribute_defaults = self.class.read_inheritable_attribute(:attribute_defaults)
attribute_defaults.each do |default|
@@ -73,8 +106,6 @@ def initialize_with_defaults(attributes = nil)
end
defaults if respond_to?(:defaults)
-
- yield self if block_given?
end
end
@@ -86,7 +117,9 @@ def initialize(attribute, value)
end
def value(record)
- if @value.respond_to?(:call)
+ if @value.is_a?(Symbol)
+ record.send(@value)
+ elsif @value.respond_to?(:call)
@value.call(record)
else
@value
View
@@ -20,9 +20,9 @@
require File.dirname(__FILE__) + '/../lib/active_record_defaults'
-config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
+ActiveRecord::Base.configurations = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + '/debug.log')
-ActiveRecord::Base.establish_connection(config[ENV['DB'] || 'mysql'])
+ActiveRecord::Base.establish_connection(ENV['DB'] || 'mysql')
load(File.dirname(__FILE__) + '/schema.rb')
@@ -16,6 +16,7 @@ def test_defaults_for_new_record
assert_equal 'Sean', p.first_name
assert_equal 'Fitzpatrick', p.last_name
assert_equal 2, p.lucky_number
+ assert_equal 'Blue', p.favourite_colour
end
def test_default_ignored_if_key_present
@@ -27,6 +28,7 @@ def test_default_ignored_if_key_present
assert_equal 'New Zealand', p.country
assert_equal 'Sean', p.first_name
assert_equal 'Fitzpatrick', p.last_name
+ assert_equal 'Blue', p.favourite_colour
end
def test_existing_records_unchanged
@@ -45,6 +47,7 @@ def test_defaults_on_create
assert_equal 'Sean', p.first_name
assert_equal 'Fitzpatrick', p.last_name
assert_equal 2, p.lucky_number
+ assert_equal 'Blue', p.favourite_colour
end
def test_defaults_from_method
View
@@ -7,14 +7,18 @@ class Person < ActiveRecord::Base
'Fitzpatrick'
end
- defaults :lucky_number => lambda { 2 }
+ defaults :lucky_number => lambda { 2 }, :favourite_colour => :default_favourite_colour
def defaults
self.birthdate = Date.new(2006, 10, lucky_number) if lucky_number?
end
+ def default_favourite_colour
+ "Blue"
+ end
+
# Include an aggregate reflection to check compatibility
- composed_of :address, :mapping => [%w{address_suburb suburb}, %{address_city city}]
+ composed_of :address, :mapping => [%w(address_suburb suburb), %{address_city city}]
belongs_to :school
end
View
@@ -1,14 +1,15 @@
ActiveRecord::Schema.define :version => 0 do
create_table :people, :force => true do |t|
- t.column :first_name, :string
- t.column :middle_name, :string
- t.column :last_name, :string
- t.column :city, :string
- t.column :country, :string
- t.column :birthdate, :date
- t.column :lucky_number, :integer
- t.column :type, :string
- t.column :school_id, :integer
+ t.column :first_name, :string
+ t.column :middle_name, :string
+ t.column :last_name, :string
+ t.column :city, :string
+ t.column :country, :string
+ t.column :birthdate, :date
+ t.column :lucky_number, :integer
+ t.column :favourite_colour, :string
+ t.column :type, :string
+ t.column :school_id, :integer
end
create_table :schools, :force => true do |t|

0 comments on commit 87e6365

Please sign in to comment.