diff options
Diffstat (limited to 'activerecord/lib/active_record')
7 files changed, 56 insertions, 61 deletions
diff --git a/activerecord/lib/active_record/associations/builder/singular_association.rb b/activerecord/lib/active_record/associations/builder/singular_association.rb index 62d48d3a2c..638a2ec72a 100644 --- a/activerecord/lib/active_record/associations/builder/singular_association.rb +++ b/activerecord/lib/active_record/associations/builder/singular_association.rb @@ -29,16 +29,16 @@ module ActiveRecord::Associations::Builder def define_constructors name = self.name - model.redefine_method("build_#{name}") do |*params| - association(name).build(*params) + model.redefine_method("build_#{name}") do |*params, &block| + association(name).build(*params, &block) end - model.redefine_method("create_#{name}") do |*params| - association(name).create(*params) + model.redefine_method("create_#{name}") do |*params, &block| + association(name).create(*params, &block) end - model.redefine_method("create_#{name}!") do |*params| - association(name).create!(*params) + model.redefine_method("create_#{name}!") do |*params, &block| + association(name).create!(*params, &block) end end end diff --git a/activerecord/lib/active_record/associations/collection_association.rb b/activerecord/lib/active_record/associations/collection_association.rb index 525ac65722..902ad8cb64 100644 --- a/activerecord/lib/active_record/associations/collection_association.rb +++ b/activerecord/lib/active_record/associations/collection_association.rb @@ -423,9 +423,13 @@ module ActiveRecord raise NotImplementedError end + def create_scope + scoped.scope_for_create.stringify_keys + end + def build_record(attributes, options) - record = reflection.build_association - record.assign_attributes(scoped.scope_for_create, :without_protection => true) + record = reflection.build_association(attributes, options) + record.assign_attributes(create_scope.except(*record.changed), :without_protection => true) record.assign_attributes(attributes, options) record end diff --git a/activerecord/lib/active_record/associations/singular_association.rb b/activerecord/lib/active_record/associations/singular_association.rb index 877ddf3ee1..ce1f2a5543 100644 --- a/activerecord/lib/active_record/associations/singular_association.rb +++ b/activerecord/lib/active_record/associations/singular_association.rb @@ -17,27 +17,28 @@ module ActiveRecord replace(record) end - def create(attributes = {}, options = {}) - build(attributes, options).tap { |record| record.save } + def create(attributes = {}, options = {}, &block) + build(attributes, options, &block).tap { |record| record.save } end - def create!(attributes = {}, options = {}) - build(attributes, options).tap { |record| record.save! } + def create!(attributes = {}, options = {}, &block) + build(attributes, options, &block).tap { |record| record.save! } end def build(attributes = {}, options = {}) - record = reflection.build_association - record.assign_attributes( - scoped.scope_for_create.except(klass.primary_key), - :without_protection => true - ) - record.assign_attributes(attributes, options) + record = reflection.build_association(attributes, options) + record.assign_attributes(create_scope.except(*record.changed), :without_protection => true) + yield(record) if block_given? set_new_record(record) record end private + def create_scope + scoped.scope_for_create.stringify_keys.except(klass.primary_key) + end + def find_target scoped.first.tap { |record| set_inverse_instance(record) } end diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index f4beeceb61..0a460bc086 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -701,11 +701,11 @@ module ActiveRecord schemas = schema_search_path.split(/,/).map { |p| quote(p) }.join(',') result = query(<<-SQL, name) SELECT distinct i.relname, d.indisunique, d.indkey, t.oid - FROM pg_class t, pg_class i, pg_index d + FROM pg_class t + INNER JOIN pg_index d ON t.oid = d.indrelid + INNER JOIN pg_class i ON d.indexrelid = i.oid WHERE i.relkind = 'i' - AND d.indexrelid = i.oid AND d.indisprimary = 'f' - AND t.oid = d.indrelid AND t.relname = '#{table_name}' AND i.relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname IN (#{schemas}) ) ORDER BY i.relname @@ -820,19 +820,13 @@ module ActiveRecord # given table's primary key. result = exec_query(<<-end_sql, 'SCHEMA').rows.first SELECT attr.attname, seq.relname - FROM pg_class seq, - pg_attribute attr, - pg_depend dep, - pg_namespace name, - pg_constraint cons - WHERE seq.oid = dep.objid - AND seq.relkind = 'S' - AND attr.attrelid = dep.refobjid - AND attr.attnum = dep.refobjsubid - AND attr.attrelid = cons.conrelid - AND attr.attnum = cons.conkey[1] - AND cons.contype = 'p' - AND dep.refobjid = '#{quote_table_name(table)}'::regclass + FROM pg_class seq + INNER JOIN pg_depend dep ON seq.oid = dep.objid + INNER JOIN pg_attribute attr ON attr.attrelid = dep.refobjid AND attr.attnum = dep.refobjsubid + INNER JOIN pg_constraint cons ON attr.attrelid = cons.conrelid AND attr.attnum = cons.conkey[1] + WHERE seq.relkind = 'S' + AND cons.contype = 'p' + AND dep.refobjid = '#{quote_table_name(table)}'::regclass end_sql # [primary_key, sequence] @@ -845,16 +839,11 @@ module ActiveRecord def primary_key(table) row = exec_query(<<-end_sql, 'SCHEMA', [[nil, table]]).rows.first SELECT DISTINCT(attr.attname) - FROM pg_attribute attr, - pg_depend dep, - pg_namespace name, - pg_constraint cons - WHERE attr.attrelid = dep.refobjid - AND attr.attnum = dep.refobjsubid - AND attr.attrelid = cons.conrelid - AND attr.attnum = cons.conkey[1] - AND cons.contype = 'p' - AND dep.refobjid = $1::regclass + FROM pg_attribute attr + INNER JOIN pg_depend dep ON attr.attrelid = dep.refobjid AND attr.attnum = dep.refobjsubid + INNER JOIN pg_constraint cons ON attr.attrelid = cons.conrelid AND attr.attnum = cons.conkey[1] + WHERE cons.contype = 'p' + AND dep.refobjid = $1::regclass end_sql row && row.first diff --git a/activerecord/lib/active_record/locking/optimistic.rb b/activerecord/lib/active_record/locking/optimistic.rb index cdedcde0eb..3afa257a76 100644 --- a/activerecord/lib/active_record/locking/optimistic.rb +++ b/activerecord/lib/active_record/locking/optimistic.rb @@ -3,16 +3,17 @@ module ActiveRecord # == What is Optimistic Locking # # Optimistic locking allows multiple users to access the same record for edits, and assumes a minimum of - # conflicts with the data. It does this by checking whether another process has made changes to a record since - # it was opened, an ActiveRecord::StaleObjectError is thrown if that has occurred and the update is ignored. + # conflicts with the data. It does this by checking whether another process has made changes to a record since + # it was opened, an <tt>ActiveRecord::StaleObjectError</tt> exception is thrown if that has occurred + # and the update is ignored. # - # Check out ActiveRecord::Locking::Pessimistic for an alternative. + # Check out <tt>ActiveRecord::Locking::Pessimistic</tt> for an alternative. # # == Usage # - # Active Records support optimistic locking if the field <tt>lock_version</tt> is present. Each update to the - # record increments the lock_version column and the locking facilities ensure that records instantiated twice - # will let the last one saved raise a StaleObjectError if the first was also updated. Example: + # Active Records support optimistic locking if the field +lock_version+ is present. Each update to the + # record increments the +lock_version+ column and the locking facilities ensure that records instantiated twice + # will let the last one saved raise a +StaleObjectError+ if the first was also updated. Example: # # p1 = Person.find(1) # p2 = Person.find(1) @@ -36,10 +37,10 @@ module ActiveRecord # You're then responsible for dealing with the conflict by rescuing the exception and either rolling back, merging, # or otherwise apply the business logic needed to resolve the conflict. # - # You must ensure that your database schema defaults the lock_version column to 0. + # You must ensure that your database schema defaults the +lock_version+ column to 0. # # This behavior can be turned off by setting <tt>ActiveRecord::Base.lock_optimistically = false</tt>. - # To override the name of the lock_version column, invoke the <tt>set_locking_column</tt> method. + # To override the name of the +lock_version+ column, invoke the <tt>set_locking_column</tt> method. # This method uses the same syntax as <tt>set_table_name</tt> module Optimistic extend ActiveSupport::Concern @@ -68,9 +69,9 @@ module ActiveRecord result = super # If the locking column has no default value set, - # start the lock version at zero. Note we can't use - # locking_enabled? at this point as @attributes may - # not have been initialized yet + # start the lock version at zero. Note we can't use + # <tt>locking_enabled?</tt> at this point as + # <tt>@attributes</tt> may not have been initialized yet. if lock_optimistically && result.include?(self.class.locking_column) result[self.class.locking_column] ||= 0 @@ -137,10 +138,9 @@ module ActiveRecord module ClassMethods DEFAULT_LOCKING_COLUMN = 'lock_version' - # Is optimistic locking enabled for this table? Returns true if the - # +lock_optimistically+ flag is set to true (which it is, by default) - # and the table includes the +locking_column+ column (defaults to - # +lock_version+). + # Returns true if the +lock_optimistically+ flag is set to true + # (which it is, by default) and the table includes the + # +locking_column+ column (defaults to +lock_version+). def locking_enabled? lock_optimistically && columns_hash[locking_column] end diff --git a/activerecord/lib/active_record/locking/pessimistic.rb b/activerecord/lib/active_record/locking/pessimistic.rb index 862cf8f72a..4c4c1bf5a1 100644 --- a/activerecord/lib/active_record/locking/pessimistic.rb +++ b/activerecord/lib/active_record/locking/pessimistic.rb @@ -3,7 +3,7 @@ module ActiveRecord # Locking::Pessimistic provides support for row-level locking using # SELECT ... FOR UPDATE and other lock types. # - # Pass <tt>:lock => true</tt> to ActiveRecord::Base.find to obtain an exclusive + # Pass <tt>:lock => true</tt> to <tt>ActiveRecord::Base.find</tt> to obtain an exclusive # lock on the selected rows: # # select * from accounts where id=1 for update # Account.find(1, :lock => true) @@ -21,7 +21,7 @@ module ActiveRecord # yuko.save! # end # - # You can also use ActiveRecord::Base#lock! method to lock one record by id. + # You can also use <tt>ActiveRecord::Base#lock!</tt> method to lock one record by id. # This may be better if you don't need to lock every row. Example: # # Account.transaction do diff --git a/activerecord/lib/active_record/railties/controller_runtime.rb b/activerecord/lib/active_record/railties/controller_runtime.rb index 9e3b3429e4..fb3fd34665 100644 --- a/activerecord/lib/active_record/railties/controller_runtime.rb +++ b/activerecord/lib/active_record/railties/controller_runtime.rb @@ -1,4 +1,5 @@ require 'active_support/core_ext/module/attr_internal' +require 'active_record/log_subscriber' module ActiveRecord module Railties |