diff options
-rw-r--r-- | actionview/Rakefile | 2 | ||||
-rw-r--r-- | activerecord/CHANGELOG.md | 14 | ||||
-rw-r--r-- | activerecord/lib/active_record/associations/builder/association.rb | 19 | ||||
-rw-r--r-- | activerecord/lib/active_record/associations/builder/belongs_to.rb | 41 | ||||
-rw-r--r-- | activerecord/lib/active_record/associations/builder/collection_association.rb | 10 | ||||
-rw-r--r-- | activerecord/lib/active_record/associations/builder/has_and_belongs_to_many.rb | 4 | ||||
-rw-r--r-- | activerecord/lib/active_record/associations/builder/has_many.rb | 2 | ||||
-rw-r--r-- | activerecord/lib/active_record/associations/builder/has_one.rb | 10 | ||||
-rw-r--r-- | activerecord/lib/active_record/associations/builder/singular_association.rb | 8 | ||||
-rw-r--r-- | activerecord/lib/active_record/persistence.rb | 14 | ||||
-rw-r--r-- | activerecord/lib/active_record/reflection.rb | 16 | ||||
-rw-r--r-- | guides/CHANGELOG.md | 4 | ||||
-rw-r--r-- | guides/source/documents.yaml | 7 | ||||
-rw-r--r-- | guides/source/maintenance_policy.md | 59 | ||||
-rw-r--r-- | rails.gemspec | 1 |
15 files changed, 150 insertions, 61 deletions
diff --git a/actionview/Rakefile b/actionview/Rakefile index e1cb4b5be0..d56fe9ea76 100644 --- a/actionview/Rakefile +++ b/actionview/Rakefile @@ -11,7 +11,7 @@ task :test => ["test:template", "test:integration:action_pack", "test:integratio namespace :test do task :isolated do - Dir.glob("test/{active_record,template}/**/*_test.rb").all? do |file| + Dir.glob("test/{actionpack,activerecord,template}/**/*_test.rb").all? do |file| sh(Gem.ruby, '-w', '-Ilib:test', file) end or raise "Failures" end diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index b40cdc9c16..08803f823c 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -10,7 +10,7 @@ * Objects intiantiated using a null relationship will now retain the attributes of the where clause. - Fixes: #11676, #11675, #11376 + Fixes #11676, #11675, #11376. *Paul Nikitochkin*, *Peter Brown*, *Nthalk* @@ -27,7 +27,7 @@ * `ActiveRecord::ConnectionAdapters.string_to_time` respects string with timezone (e.g. Wed, 04 Sep 2013 20:30:00 JST). - Fixes: #12278 + Fixes #12278. *kennyj* @@ -74,7 +74,7 @@ where constraints and at least of them is not `Arel::Nodes::Equality`, generates invalid SQL expression. - Fixes: #11963 + Fixes #11963. *Paul Nikitochkin* @@ -247,13 +247,13 @@ to allow the connection adapter to properly determine how to quote the value. This was affecting certain databases that use specific column types. - Fixes: #6763 + Fixes #6763. *Alfred Wong* * rescue from all exceptions in `ConnectionManagement#call` - Fixes #11497 + Fixes #11497. As `ActiveRecord::ConnectionAdapters::ConnectionManagement` middleware does not rescue from Exception (but only from StandardError), the Connection @@ -275,7 +275,7 @@ * Remove extra decrement of transaction deep level. - Fixes: #4566 + Fixes #4566. *Paul Nikitochkin* @@ -295,7 +295,7 @@ * Remove extra select and update queries on save/touch/destroy ActiveRecord model with belongs to reflection with option `touch: true`. - Fixes: #11288 + Fixes #11288. *Paul Nikitochkin* diff --git a/activerecord/lib/active_record/associations/builder/association.rb b/activerecord/lib/active_record/associations/builder/association.rb index 6de0331851..783a86d4a3 100644 --- a/activerecord/lib/active_record/associations/builder/association.rb +++ b/activerecord/lib/active_record/associations/builder/association.rb @@ -31,8 +31,8 @@ module ActiveRecord::Associations::Builder builder = new(name, scope, options, &block) reflection = builder.build(model) - builder.define_accessors model - builder.define_callbacks model, reflection + builder.define_accessors model, reflection + define_callbacks model, reflection builder.define_extensions model reflection end @@ -79,8 +79,8 @@ module ActiveRecord::Associations::Builder def define_extensions(model) end - def define_callbacks(model, reflection) - add_before_destroy_callbacks(model, name) if options[:dependent] + def self.define_callbacks(model, reflection) + add_before_destroy_callbacks(model, reflection) if reflection.options[:dependent] Association.extensions.each do |extension| extension.build model, reflection end @@ -93,7 +93,7 @@ module ActiveRecord::Associations::Builder # # Post.first.comments and Post.first.comments= methods are defined by this method... - def define_accessors(model) + def define_accessors(model, reflection) mixin = model.generated_feature_methods define_readers(mixin) define_writers(mixin) @@ -115,17 +115,18 @@ module ActiveRecord::Associations::Builder CODE end - def valid_dependent_options + def self.valid_dependent_options raise NotImplementedError end private - def add_before_destroy_callbacks(model, name) - unless valid_dependent_options.include? options[:dependent] - raise ArgumentError, "The :dependent option must be one of #{valid_dependent_options}, but is :#{options[:dependent]}" + def self.add_before_destroy_callbacks(model, reflection) + unless valid_dependent_options.include? reflection.options[:dependent] + raise ArgumentError, "The :dependent option must be one of #{valid_dependent_options}, but is :#{reflection.options[:dependent]}" end + name = reflection.name model.before_destroy lambda { |o| o.association(name).handle_dependency } end end diff --git a/activerecord/lib/active_record/associations/builder/belongs_to.rb b/activerecord/lib/active_record/associations/builder/belongs_to.rb index 4e88b50ec5..9d55ec850e 100644 --- a/activerecord/lib/active_record/associations/builder/belongs_to.rb +++ b/activerecord/lib/active_record/associations/builder/belongs_to.rb @@ -8,21 +8,17 @@ module ActiveRecord::Associations::Builder super + [:foreign_type, :polymorphic, :touch] end - def constructable? - !options[:polymorphic] - end - - def valid_dependent_options + def self.valid_dependent_options [:destroy, :delete] end - def define_callbacks(model, reflection) + def self.define_callbacks(model, reflection) super - add_counter_cache_callbacks(model, reflection) if options[:counter_cache] - add_touch_callbacks(model, reflection) if options[:touch] + add_counter_cache_callbacks(model, reflection) if reflection.options[:counter_cache] + add_touch_callbacks(model, reflection) if reflection.options[:touch] end - def define_accessors(mixin) + def define_accessors(mixin, reflection) super add_counter_cache_methods mixin end @@ -33,18 +29,18 @@ module ActiveRecord::Associations::Builder return if mixin.method_defined? :belongs_to_counter_cache_after_create mixin.class_eval do - def belongs_to_counter_cache_after_create(association, reflection) - if record = send(association.name) + def belongs_to_counter_cache_after_create(reflection) + if record = send(reflection.name) cache_column = reflection.counter_cache_column record.class.increment_counter(cache_column, record.id) @_after_create_counter_called = true end end - def belongs_to_counter_cache_before_destroy(association, reflection) + def belongs_to_counter_cache_before_destroy(reflection) foreign_key = reflection.foreign_key.to_sym unless destroyed_by_association && destroyed_by_association.foreign_key.to_sym == foreign_key - record = send association.name + record = send reflection.name if record && !self.destroyed? cache_column = reflection.counter_cache_column record.class.decrement_counter(cache_column, record.id) @@ -52,13 +48,13 @@ module ActiveRecord::Associations::Builder end end - def belongs_to_counter_cache_after_update(association, reflection) + def belongs_to_counter_cache_after_update(reflection) foreign_key = reflection.foreign_key cache_column = reflection.counter_cache_column if (@_after_create_counter_called ||= false) @_after_create_counter_called = false - elsif attribute_changed?(foreign_key) && !new_record? && association.constructable? + elsif attribute_changed?(foreign_key) && !new_record? && reflection.constructable? model = reflection.klass foreign_key_was = attribute_was foreign_key foreign_key = attribute foreign_key @@ -74,20 +70,19 @@ module ActiveRecord::Associations::Builder end end - def add_counter_cache_callbacks(model, reflection) + def self.add_counter_cache_callbacks(model, reflection) cache_column = reflection.counter_cache_column - association = self model.after_create lambda { |record| - record.belongs_to_counter_cache_after_create(association, reflection) + record.belongs_to_counter_cache_after_create(reflection) } model.before_destroy lambda { |record| - record.belongs_to_counter_cache_before_destroy(association, reflection) + record.belongs_to_counter_cache_before_destroy(reflection) } model.after_update lambda { |record| - record.belongs_to_counter_cache_after_update(association, reflection) + record.belongs_to_counter_cache_after_update(reflection) } klass = reflection.class_name.safe_constantize @@ -120,10 +115,10 @@ module ActiveRecord::Associations::Builder end end - def add_touch_callbacks(model, reflection) + def self.add_touch_callbacks(model, reflection) foreign_key = reflection.foreign_key - n = name - touch = options[:touch] + n = reflection.name + touch = reflection.options[:touch] callback = lambda { |record| BelongsTo.touch_record(record, foreign_key, n, touch) diff --git a/activerecord/lib/active_record/associations/builder/collection_association.rb b/activerecord/lib/active_record/associations/builder/collection_association.rb index 7bd0687c0b..15f9f9a65f 100644 --- a/activerecord/lib/active_record/associations/builder/collection_association.rb +++ b/activerecord/lib/active_record/associations/builder/collection_association.rb @@ -23,9 +23,13 @@ module ActiveRecord::Associations::Builder end end - def define_callbacks(model, reflection) + def self.define_callbacks(model, reflection) super - CALLBACKS.each { |callback_name| define_callback(model, callback_name) } + name = reflection.name + options = reflection.options + CALLBACKS.each { |callback_name| + define_callback(model, callback_name, name, options) + } end def define_extensions(model) @@ -35,7 +39,7 @@ module ActiveRecord::Associations::Builder end end - def define_callback(model, callback_name) + def self.define_callback(model, callback_name, name, options) full_callback_name = "#{callback_name}_for_#{name}" # TODO : why do i need method_defined? I think its because of the inheritance chain diff --git a/activerecord/lib/active_record/associations/builder/has_and_belongs_to_many.rb b/activerecord/lib/active_record/associations/builder/has_and_belongs_to_many.rb index f3bf406196..4b47824148 100644 --- a/activerecord/lib/active_record/associations/builder/has_and_belongs_to_many.rb +++ b/activerecord/lib/active_record/associations/builder/has_and_belongs_to_many.rb @@ -117,9 +117,9 @@ module ActiveRecord::Associations::Builder super + [:join_table, :association_foreign_key] end - def define_callbacks(model, reflection) + def self.define_callbacks(model, reflection) super - name = self.name + name = reflection.name model.send(:include, Module.new { class_eval <<-RUBY, __FILE__, __LINE__ + 1 def destroy_associations diff --git a/activerecord/lib/active_record/associations/builder/has_many.rb b/activerecord/lib/active_record/associations/builder/has_many.rb index a60cb4769a..7909b93622 100644 --- a/activerecord/lib/active_record/associations/builder/has_many.rb +++ b/activerecord/lib/active_record/associations/builder/has_many.rb @@ -8,7 +8,7 @@ module ActiveRecord::Associations::Builder super + [:primary_key, :dependent, :as, :through, :source, :source_type, :inverse_of, :counter_cache] end - def valid_dependent_options + def self.valid_dependent_options [:destroy, :delete_all, :nullify, :restrict_with_error, :restrict_with_exception] end end diff --git a/activerecord/lib/active_record/associations/builder/has_one.rb b/activerecord/lib/active_record/associations/builder/has_one.rb index 62d454ce55..f359efd496 100644 --- a/activerecord/lib/active_record/associations/builder/has_one.rb +++ b/activerecord/lib/active_record/associations/builder/has_one.rb @@ -10,18 +10,14 @@ module ActiveRecord::Associations::Builder valid end - def constructable? - !options[:through] - end - - def valid_dependent_options + def self.valid_dependent_options [:destroy, :delete, :nullify, :restrict_with_error, :restrict_with_exception] end private - def add_before_destroy_callbacks(model, name) - super unless options[:through] + def self.add_before_destroy_callbacks(model, reflection) + super unless reflection.options[:through] end end end diff --git a/activerecord/lib/active_record/associations/builder/singular_association.rb b/activerecord/lib/active_record/associations/builder/singular_association.rb index d97c0e9afd..10d568ebc0 100644 --- a/activerecord/lib/active_record/associations/builder/singular_association.rb +++ b/activerecord/lib/active_record/associations/builder/singular_association.rb @@ -6,13 +6,9 @@ module ActiveRecord::Associations::Builder super + [:remote, :dependent, :counter_cache, :primary_key, :inverse_of] end - def constructable? - true - end - - def define_accessors(model) + def define_accessors(model, reflection) super - define_constructors(model.generated_feature_methods) if constructable? + define_constructors(model.generated_feature_methods) if reflection.constructable? end # Defines the (build|create)_association methods for belongs_to or has_one association diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb index bdd00ee259..267aa28058 100644 --- a/activerecord/lib/active_record/persistence.rb +++ b/activerecord/lib/active_record/persistence.rb @@ -335,8 +335,18 @@ module ActiveRecord # Reloads the record from the database. # - # This method modifies the receiver in-place. Attributes are updated, and - # caches busted, in particular the associations cache. + # This method finds record by its primary key (which could be assigned manually) and + # modifies the receiver in-place: + # + # account = Account.new + # # => #<Account id: nil, email: nil> + # account.id = 1 + # account.reload + # # Account Load (1.2ms) SELECT "accounts".* FROM "accounts" WHERE "accounts"."id" = $1 LIMIT 1 [["id", 1]] + # # => #<Account id: 1, email: 'account@example.com'> + # + # Attributes are reloaded from the database, and caches busted, in + # particular the associations cache. # # If the record no longer exists in the database <tt>ActiveRecord::RecordNotFound</tt> # is raised. Otherwise, in addition to the in-place modification the method diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index f47282b7fd..263ba922da 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -200,6 +200,7 @@ module ActiveRecord @automatic_inverse_of = nil @type = options[:as] && "#{options[:as]}_type" @foreign_type = options[:foreign_type] || "#{name}_type" + @constructable = calculate_constructable(macro, options) end # Returns a new, unsaved instance of the associated class. +attributes+ will @@ -208,6 +209,10 @@ module ActiveRecord klass.new(attributes, &block) end + def constructable? # :nodoc: + @constructable + end + def table_name klass.table_name end @@ -379,6 +384,17 @@ module ActiveRecord end private + def calculate_constructable(macro, options) + case macro + when :belongs_to + !options[:polymorphic] + when :has_one + !options[:through] + else + true + end + end + # Attempts to find the inverse association name automatically. # If it cannot find a suitable inverse association name, it returns # nil. diff --git a/guides/CHANGELOG.md b/guides/CHANGELOG.md index afa695d445..38e407b198 100644 --- a/guides/CHANGELOG.md +++ b/guides/CHANGELOG.md @@ -2,4 +2,8 @@ *Sıtkı Bağdat* +* Added the Rails maintenance policy to the guides. + + *Matias Korhonen* + Please check [4-0-stable](https://github.com/rails/rails/blob/4-0-stable/guides/CHANGELOG.md) for previous changes. diff --git a/guides/source/documents.yaml b/guides/source/documents.yaml index 1b16f4e516..1bf9ff95e1 100644 --- a/guides/source/documents.yaml +++ b/guides/source/documents.yaml @@ -150,6 +150,13 @@ url: ruby_on_rails_guides_guidelines.html description: This guide documents the Ruby on Rails guides guidelines. - + name: Maintenance Policy + documents: + - + name: Maintenance Policy + url: maintenance_policy.html + description: What versions of Ruby on Rails are currently supported, and when to expect new versions. +- name: Release Notes documents: - diff --git a/guides/source/maintenance_policy.md b/guides/source/maintenance_policy.md new file mode 100644 index 0000000000..354b1121aa --- /dev/null +++ b/guides/source/maintenance_policy.md @@ -0,0 +1,59 @@ +Maintenance policy for Ruby on Rails +==================================== + +Since the most recent patch releases there has been some confusion about what +versions of Ruby on Rails are currently supported, and when people +can expect new versions. Our maintenance policy is as follows. + +Support of the Rails framework is divided into four groups: New features, bug +fixes, security issues, and severe security issues. They are handled as +follows, all versions in x.y.z format: + +New Features +------------ + +New Features are only added to the master branch and will not be made available +in point releases. + +Bug fixes +--------- + +Only the latest release series will receive bug fixes. When enough bugs are +fixed and its deemed worthy to release a new gem, this is the branch it happens +from. + +**Currently included series:** 4.0.z + +Security issues: +---------------- + +The current release series and the next most recent one will receive patches +and new versions in case of a security issue. + +These releases are created by taking the last released version, applying the +security patches, and releasing. Those patches are then applied to the end of +the x-y-stable branch. For example, a theoretical 1.2.3 security release would +be built from 1.2.2, and then added to the end of 1-2-stable. This means that +security releases are easy to upgrade to if you're running the latest version +of Rails. + +**Currently included series:** 4.0.z, 3.2.z + +Severe security issues: +----------------------- + +For severe security issues we will provide new versions as above, and also the +last major release series will receive patches and new versions. The +classification of the security issue is judged by the core team. + +**Currently included series:** 4.0.z, 3.2.z + +Unsupported Release Series +-------------------------- + +When a release series is no longer supported, it's your own responsibility to +deal with bugs and security issues. We may provide back-ports of the fixes and +publish them to git, however there will be no new versions released. If you are +not comfortable maintaining your own versions, you should upgrade to a +supported version. + diff --git a/rails.gemspec b/rails.gemspec index b426faf0e8..d1c199a97a 100644 --- a/rails.gemspec +++ b/rails.gemspec @@ -21,6 +21,7 @@ Gem::Specification.new do |s| s.add_dependency 'activesupport', version s.add_dependency 'actionpack', version s.add_dependency 'actionview', version + s.add_dependency 'activemodel', version s.add_dependency 'activerecord', version s.add_dependency 'actionmailer', version s.add_dependency 'railties', version |