diff options
Diffstat (limited to 'railties/guides/source')
-rw-r--r-- | railties/guides/source/3_2_release_notes.textile | 48 | ||||
-rw-r--r-- | railties/guides/source/active_record_querying.textile | 58 | ||||
-rw-r--r-- | railties/guides/source/active_record_validations_callbacks.textile | 33 | ||||
-rw-r--r-- | railties/guides/source/active_resource_basics.textile | 2 | ||||
-rw-r--r-- | railties/guides/source/association_basics.textile | 11 | ||||
-rw-r--r-- | railties/guides/source/contributing_to_ruby_on_rails.textile | 2 | ||||
-rw-r--r-- | railties/guides/source/form_helpers.textile | 2 | ||||
-rw-r--r-- | railties/guides/source/getting_started.textile | 4 | ||||
-rw-r--r-- | railties/guides/source/i18n.textile | 6 | ||||
-rw-r--r-- | railties/guides/source/migrations.textile | 30 | ||||
-rw-r--r-- | railties/guides/source/security.textile | 2 |
11 files changed, 150 insertions, 48 deletions
diff --git a/railties/guides/source/3_2_release_notes.textile b/railties/guides/source/3_2_release_notes.textile index 8b242df179..d669a7fdfa 100644 --- a/railties/guides/source/3_2_release_notes.textile +++ b/railties/guides/source/3_2_release_notes.textile @@ -27,6 +27,7 @@ h4. What to update in your apps ** <tt>rails = 3.2.0</tt> ** <tt>sass-rails ~> 3.2.3</tt> ** <tt>coffee-rails ~> 3.2.1</tt> +** <tt>uglifier >= 1.0.3</tt> * Rails 3.2 deprecates <tt>vendor/plugins</tt> and Rails 4.0 will remove them completely. You can start replacing these plugins by extracting them as gems and adding them in your Gemfile. If you choose not to make them gems, you can move them into, say, <tt>lib/my_plugin/*</tt> and add an appropriate initializer in <tt>config/initializers/my_plugin.rb</tt>. @@ -138,7 +139,7 @@ will create indexes for +title+ and +author+ with the latter being an unique ind * Remove old <tt>config.paths.app.controller</tt> API in favor of <tt>config.paths["app/controller"]</tt>. -h4. Deprecations +h4(#railties_deprecations). Deprecations * +Rails::Plugin+ is deprecated and will be removed in Rails 4.0. Instead of adding plugins to +vendor/plugins+ use gems or bundler with path or git dependencies. @@ -204,7 +205,7 @@ We now no longer write out HTTP_COOKIE and the cookie jar is persistent between * Assets should use the request protocol by default or default to relative if no request is available. -h5. Deprecations +h5(#actioncontroller_deprecations). Deprecations * Deprecated implied layout lookup in controllers whose parent had a explicit layout set: @@ -225,8 +226,6 @@ In the example above, Posts controller will no longer automatically look up for * Deprecated <tt>method_missing</tt> in favour of +action_missing+ for missing actions. -* Deprecated <tt>ActionController#performed?</tt> in favour of checking for the presence of <tt>response_body</tt>. - * Deprecated <tt>ActionController#rescue_action</tt>, <tt>ActionController#initialize_template_class</tt> and <tt>ActionController#assign_shortcuts</tt>. h4. Action Dispatch @@ -239,7 +238,7 @@ h4. Action Dispatch * Allow rescue responses to be configured through a railtie as in <tt>config.action_dispatch.rescue_responses</tt>. -h5. Deprecations +h5(#actiondispatch_deprecations). Deprecations * Deprecated the ability to set a default charset at the controller level, use the new <tt>config.action_dispatch.default_charset</tt> instead. @@ -286,7 +285,7 @@ end * Added +font_path+ helper method that computes the path to a font asset in <tt>public/fonts</tt>. -h5. Deprecations +h5(#actionview_deprecations). Deprecations * Passing formats or handlers to render :template and friends like <tt>render :template => "foo.html.erb"</tt> is deprecated. Instead, you can provide :handlers and :formats directly as an options: <tt> render :template => "foo", :formats => [:html, :js], :handlers => :erb</tt>. @@ -296,7 +295,9 @@ h4. Sprockets h3. Active Record -* Boolean columns with 'on' and 'ON' values are type casted to true. +* Boolean columns with 'on' and 'ON' values are type cast to true. + +* When the +timestamps+ method creates the +created_at+ and +updated_at+ columns, it makes them non-nullable by default. * Implemented <tt>ActiveRecord::Relation#explain</tt>. @@ -371,7 +372,34 @@ has_many :clients, :class_name => :Client # Note that the symbol need to be capi User.where(:first_name => "Scarlett").first_or_create!(:last_name => "Johansson") </ruby> -h4. Deprecations +* Added a <tt>with_lock</tt> method to Active Record objects, which starts a transaction, locks the object (pessimistically) and yields to the block. The method takes one (optional) parameter and passes it to +lock!+. + +This makes it possible to write the following: + +<ruby> +class Order < ActiveRecord::Base + def cancel! + transaction do + lock! + # ... cancelling logic + end + end +end +</ruby> + +as: + +<ruby> +class Order < ActiveRecord::Base + def cancel! + with_lock do + # ... cancelling logic + end + end +end +</ruby> + +h4(#activerecord_deprecations). Deprecations * Automatic closure of connections in threads is deprecated. For example the following code is deprecated: @@ -419,7 +447,7 @@ h3. Active Model * Provide mass_assignment_sanitizer as an easy API to replace the sanitizer behavior. Also support both :logger (default) and :strict sanitizer behavior. -h4. Deprecations +h4(#activemodel_deprecations). Deprecations * Deprecated <tt>define_attr_method</tt> in <tt>ActiveModel::AttributeMethods</tt> because this only existed to support methods like +set_table_name+ in Active Record, which are themselves being deprecated. @@ -479,7 +507,7 @@ Event.where(:created_at => Time.now.all_day) * Removed <tt>ActiveSupport::SecureRandom</tt> in favor of <tt>SecureRandom</tt> from the standard library. -h4. Deprecations +h4(#activesupport_deprecations). Deprecations * +ActiveSupport::Base64+ is deprecated in favor of <tt>::Base64</tt>. diff --git a/railties/guides/source/active_record_querying.textile b/railties/guides/source/active_record_querying.textile index beada85ce3..21bbc64255 100644 --- a/railties/guides/source/active_record_querying.textile +++ b/railties/guides/source/active_record_querying.textile @@ -404,6 +404,8 @@ Or ordering by multiple fields: <ruby> Client.order("orders_count ASC, created_at DESC") +# OR +Client.order("orders_count ASC", "created_at DESC") </ruby> h3. Selecting Specific Fields @@ -606,9 +608,33 @@ SELECT * FROM clients WHERE orders_count > 10 ORDER BY clients.id DESC This method accepts *no* arguments. +h3. Null Relation + +The +none+ method returns a chainable relation with no records. Any subsequent conditions chained to the returned relation will continue generating empty relations. This is useful in scenarios where you need a chainable response to a method or a scope that could return zero results. + +<ruby> +Post.none # returns an empty Relation and fires no queries. +</ruby> + +<ruby> +# The visible_posts method below is expected to return a Relation. +@posts = current_user.visible_posts.where(:name => params[:name]) + +def visible_posts + case role + when 'Country Manager' + Post.where(:country => country) + when 'Reviewer' + Post.published + when 'Bad User' + Post.none # => returning [] or nil breaks the caller code in this case + end +end +</ruby> + h3. Readonly Objects -Active Record provides +readonly+ method on a relation to explicitly disallow modification or deletion of any of the returned object. Any attempt to alter or destroy a readonly record will not succeed, raising an +ActiveRecord::ReadOnlyRecord+ exception. +Active Record provides +readonly+ method on a relation to explicitly disallow modification of any of the returned objects. Any attempt to alter a readonly record will not succeed, raising an +ActiveRecord::ReadOnlyRecord+ exception. <ruby> client = Client.readonly.first @@ -648,15 +674,13 @@ c2.save # Raises an ActiveRecord::StaleObjectError 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. -NOTE: 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, +ActiveRecord::Base+ provides a class method called +set_locking_column+: +To override the name of the +lock_version+ column, +ActiveRecord::Base+ provides a class attribute called +locking_column+: <ruby> class Client < ActiveRecord::Base - set_locking_column :lock_client_column + self.locking_column = :lock_client_column end </ruby> @@ -692,6 +716,17 @@ Item.transaction do end </ruby> +If you already have an instance of your model, you can start a transaction and acquire the lock in one go using the following code: + +<ruby> +item = Item.first +item.with_lock do + # This block is called within a transaction, + # item is already locked. + item.increment!(:views) +end +</ruby> + h3. Joining Tables Active Record provides a finder method called +joins+ for specifying +JOIN+ clauses on the resulting SQL. There are multiple ways to use the +joins+ method. @@ -954,7 +989,7 @@ If you're working with dates or times within scopes, due to how they are evaluat <ruby> class Post < ActiveRecord::Base - scope :last_week, lambda { where("created_at < ?", Time.zone.now ) } + scope :created_before_now, lambda { where("created_at < ?", Time.zone.now ) } end </ruby> @@ -966,21 +1001,21 @@ When a +lambda+ is used for a +scope+, it can take arguments: <ruby> class Post < ActiveRecord::Base - scope :1_week_before, lambda { |time| where("created_at < ?", time) } + scope :created_before, lambda { |time| where("created_at < ?", time) } end </ruby> This may then be called using this: <ruby> -Post.1_week_before(Time.zone.now) +Post.created_before(Time.zone.now) </ruby> However, this is just duplicating the functionality that would be provided to you by a class method. <ruby> class Post < ActiveRecord::Base - def self.1_week_before(time) + def self.created_before(time) where("created_at < ?", time) end end @@ -989,7 +1024,7 @@ end Using a class method is the preferred way to accept arguments for scopes. These methods will still be accessible on the association objects: <ruby> -category.posts.1_week_before(time) +category.posts.created_before(time) </ruby> h4. Working with scopes @@ -1389,6 +1424,9 @@ A threshold of +nil+ disables automatic EXPLAINs. The default threshold in development mode is 0.5 seconds, and +nil+ in test and production modes. +INFO. Automatic EXPLAIN gets disabled if Active Record has no logger, regardless +of the value of the threshold. + h5. Disabling Automatic EXPLAIN Automatic EXPLAIN can be selectively silenced with +ActiveRecord::Base.silence_auto_explain+: diff --git a/railties/guides/source/active_record_validations_callbacks.textile b/railties/guides/source/active_record_validations_callbacks.textile index a27c292a4c..15d24f9ac1 100644 --- a/railties/guides/source/active_record_validations_callbacks.textile +++ b/railties/guides/source/active_record_validations_callbacks.textile @@ -614,7 +614,7 @@ As shown in the example, you can also combine standard validations with your own h4. Custom Methods -You can also create methods that verify the state of your models and add messages to the +errors+ collection when they are invalid. You must then register these methods by using one or more of the +validate+, +validate_on_create+ or +validate_on_update+ class methods, passing in the symbols for the validation methods' names. +You can also create methods that verify the state of your models and add messages to the +errors+ collection when they are invalid. You must then register these methods by using the +validate+ class method, passing in the symbols for the validation methods' names. You can pass more than one symbol for each class method and the respective validations will be run in the same order as they were registered. @@ -637,12 +637,24 @@ class Invoice < ActiveRecord::Base end </ruby> +By default such validations will run every time you call +valid?+. It is also possible to control when to run these custom validations by giving an +:on+ option to the +validate+ method, with either: +:create+ or +:update+. + +<ruby> +class Invoice < ActiveRecord::Base + validate :active_customer, :on => :create + + def active_customer + errors.add(:customer_id, "is not active") unless customer.active? + end +end +</ruby> + You can even create your own validation helpers and reuse them in several different models. For example, an application that manages surveys may find it useful to express that a certain field corresponds to a set of choices: <ruby> ActiveRecord::Base.class_eval do def self.validates_as_choice(attr_name, n, options={}) - validates attr_name, :inclusion => { {:in => 1..n}.merge(options) } + validates attr_name, :inclusion => { { :in => 1..n }.merge!(options) } end end </ruby> @@ -659,7 +671,7 @@ h3. Working with Validation Errors In addition to the +valid?+ and +invalid?+ methods covered earlier, Rails provides a number of methods for working with the +errors+ collection and inquiring about the validity of objects. -The following is a list of the most commonly used methods. Please refer to the +ActiveRecord::Errors+ documentation for a list of all the available methods. +The following is a list of the most commonly used methods. Please refer to the +ActiveModel::Errors+ documentation for a list of all the available methods. h4(#working_with_validation_errors-errors). +errors+ @@ -889,13 +901,8 @@ Below is a simple example where we change the Rails behavior to always display t <ruby> ActionView::Base.field_error_proc = Proc.new do |html_tag, instance| - if instance.error_message.kind_of?(Array) - %(#{html_tag}<span class="validation-error"> - #{instance.error_message.join(',')}</span>).html_safe - else - %(#{html_tag}<span class="validation-error"> - #{instance.error_message}</span>).html_safe - end + errors = Array(instance.error_message).join(',') + %(#{html_tag}<span class="validation-error"> #{errors}</span>).html_safe end </ruby> @@ -949,6 +956,7 @@ h4. Creating an Object * +before_validation+ * +after_validation+ * +before_save+ +* +around_save+ * +before_create+ * +around_create+ * +after_create+ @@ -959,6 +967,7 @@ h4. Updating an Object * +before_validation+ * +after_validation+ * +before_save+ +* +around_save+ * +before_update+ * +around_update+ * +after_update+ @@ -967,8 +976,8 @@ h4. Updating an Object h4. Destroying an Object * +before_destroy+ -* +after_destroy+ * +around_destroy+ +* +after_destroy+ WARNING. +after_save+ runs both on create and update, but always _after_ the more specific callbacks +after_create+ and +after_update+, no matter the order in which the macro calls were executed. @@ -1013,7 +1022,7 @@ The following methods trigger callbacks: * +increment!+ * +save+ * +save!+ -* +save(false)+ +* +save(:validate => false)+ * +toggle!+ * +update+ * +update_attribute+ diff --git a/railties/guides/source/active_resource_basics.textile b/railties/guides/source/active_resource_basics.textile index 851aac1a3f..37abb8a640 100644 --- a/railties/guides/source/active_resource_basics.textile +++ b/railties/guides/source/active_resource_basics.textile @@ -71,7 +71,7 @@ person.destroy h3. Validations -Module to support validation and errors with Active Resource objects. The module overrides Base#save to rescue ActiveResource::ResourceInvalid exceptions and parse the errors returned in the web service response. The module also adds an errors collection that mimics the interface of the errors provided by ActiveRecord::Errors. +Module to support validation and errors with Active Resource objects. The module overrides Base#save to rescue ActiveResource::ResourceInvalid exceptions and parse the errors returned in the web service response. The module also adds an errors collection that mimics the interface of the errors provided by ActiveModel::Errors. h4. Validating client side resources by overriding validation methods in base class diff --git a/railties/guides/source/association_basics.textile b/railties/guides/source/association_basics.textile index 451653655f..a55ed38d1b 100644 --- a/railties/guides/source/association_basics.textile +++ b/railties/guides/source/association_basics.textile @@ -1120,7 +1120,7 @@ h6(#has_many-collection-find). <tt><em>collection</em>.find(...)</tt> The <tt><em>collection</em>.find</tt> method finds objects within the collection. It uses the same syntax and options as +ActiveRecord::Base.find+. <ruby> -@open_orders = @customer.orders.where(:open => 1) +@open_orders = @customer.orders.find(1) </ruby> h6(#has_many-collection-where). <tt><em>collection</em>.where(...)</tt> @@ -1242,7 +1242,7 @@ h6(#has_many-counter_sql). +:counter_sql+ Normally Rails automatically generates the proper SQL to count the association members. With the +:counter_sql+ option, you can specify a complete SQL statement to count them yourself. -NOTE: If you specify +:finder_sql+ but not +:counter_sql+, then the counter SQL will be generated by substituting +SELECT COUNT(*) FROM+ for the +SELECT ... FROM+ clause of your +:finder_sql+ statement. +NOTE: If you specify +:finder_sql+ but not +:counter_sql+, then the counter SQL will be generated by substituting the +SELECT ... FROM+ clause of your +:finder_sql+ statement by +SELECT COUNT(*) FROM+. h6(#has_many-dependent). +:dependent+ @@ -1545,12 +1545,9 @@ h6(#has_and_belongs_to_many-collection-find). <tt><em>collection</em>.find(...)< The <tt><em>collection</em>.find</tt> method finds objects within the collection. It uses the same syntax and options as +ActiveRecord::Base.find+. It also adds the additional condition that the object must be in the collection. <ruby> -@new_assemblies = @part.assemblies.all( - :conditions => ["created_at > ?", 2.days.ago]) +@assembly = @part.assemblies.find(1) </ruby> -NOTE: Beginning with Rails 3, supplying options to the +ActiveRecord::Base.find+ method is discouraged. Use <tt><em>collection</em>.where</tt> instead when you need to pass conditions. - h6(#has_and_belongs_to_many-collection-where). <tt><em>collection</em>.where(...)</tt> The <tt><em>collection</em>.where</tt> method finds objects within the collection based on the conditions supplied but the objects are loaded lazily meaning that the database is queried only when the object(s) are accessed. It also adds the additional condition that the object must be in the collection. @@ -1669,7 +1666,7 @@ h6(#has_and_belongs_to_many-counter_sql). +:counter_sql+ Normally Rails automatically generates the proper SQL to count the association members. With the +:counter_sql+ option, you can specify a complete SQL statement to count them yourself. -NOTE: If you specify +:finder_sql+ but not +:counter_sql+, then the counter SQL will be generated by substituting +SELECT COUNT(*) FROM+ for the +SELECT ... FROM+ clause of your +:finder_sql+ statement. +NOTE: If you specify +:finder_sql+ but not +:counter_sql+, then the counter SQL will be generated by substituting the +SELECT ... FROM+ clause of your +:finder_sql+ statement by +SELECT COUNT(*) FROM+. h6(#has_and_belongs_to_many-delete_sql). +:delete_sql+ diff --git a/railties/guides/source/contributing_to_ruby_on_rails.textile b/railties/guides/source/contributing_to_ruby_on_rails.textile index e082fd2941..aac5e13978 100644 --- a/railties/guides/source/contributing_to_ruby_on_rails.textile +++ b/railties/guides/source/contributing_to_ruby_on_rails.textile @@ -309,7 +309,7 @@ Rails follows a simple set of coding style conventions. * Two spaces, no tabs. * No trailing whitespace. Blank lines should not have any space. -* Indent after private/protected. +* Outdent private/protected from method definitions. Same indentation as the class/module. * Prefer +&&+/+||+ over +and+/+or+. * Prefer class << self block over self.method for class methods. * +MyClass.my_method(my_arg)+ not +my_method( my_arg )+ or +my_method my_arg+. diff --git a/railties/guides/source/form_helpers.textile b/railties/guides/source/form_helpers.textile index 1681629620..9758b639cf 100644 --- a/railties/guides/source/form_helpers.textile +++ b/railties/guides/source/form_helpers.textile @@ -754,7 +754,7 @@ produces exactly the same output as the previous example. h3. Forms to external resources -If you need to post some data to an external resource it is still great to build your from using rails form helpers. But sometimes you need to set an +authenticity_token+ for this resource. You can do it by passing an +:authenticity_token => 'your_external_token'+ parameter to the +form_tag+ options: +If you need to post some data to an external resource it is still great to build your form using rails form helpers. But sometimes you need to set an +authenticity_token+ for this resource. You can do it by passing an +:authenticity_token => 'your_external_token'+ parameter to the +form_tag+ options: <erb> <%= form_tag 'http://farfar.away/form', :authenticity_token => 'external_token') do %> diff --git a/railties/guides/source/getting_started.textile b/railties/guides/source/getting_started.textile index c77bc93cfb..bed14ef6a8 100644 --- a/railties/guides/source/getting_started.textile +++ b/railties/guides/source/getting_started.textile @@ -853,7 +853,7 @@ below: </erb> Now when you refresh the +/posts+ page, you'll see a gray background to the -page. This same gray background will be used throughout all the views for posts. +page. This same gray background will be used throughout all the views. h4. Creating New Posts @@ -1668,7 +1668,7 @@ right in the form where you create the post. First, create a new model to hold the tags: <shell> -$ rails generate model tag name:string post:references +$ rails generate model Tag name:string post:references </shell> Again, run the migration to create the database table: diff --git a/railties/guides/source/i18n.textile b/railties/guides/source/i18n.textile index 16ad35f345..25201888e7 100644 --- a/railties/guides/source/i18n.textile +++ b/railties/guides/source/i18n.textile @@ -819,13 +819,13 @@ h5. Action View Helper Methods * The +number_to_currency+, +number_with_precision+, +number_to_percentage+, +number_with_delimiter+, and +number_to_human_size+ helpers use the number format settings located in the "number":https://github.com/rails/rails/blob/master/actionpack/lib/action_view/locale/en.yml#L2 scope. -h5. Active Record Methods +h5. Active Model Methods * +model_name.human+ and +human_attribute_name+ use translations for model names and attribute names if available in the "activerecord.models":https://github.com/rails/rails/blob/master/activerecord/lib/active_record/locale/en.yml#L29 scope. They also support translations for inherited class names (e.g. for use with STI) as explained above in "Error message scopes". -* +ActiveRecord::Errors#generate_message+ (which is used by Active Record validations but may also be used manually) uses +model_name.human+ and +human_attribute_name+ (see above). It also translates the error message and supports translations for inherited class names as explained above in "Error message scopes". +* +ActiveModel::Errors#generate_message+ (which is used by Active Model validations but may also be used manually) uses +model_name.human+ and +human_attribute_name+ (see above). It also translates the error message and supports translations for inherited class names as explained above in "Error message scopes". -* +ActiveRecord::Errors#full_messages+ prepends the attribute name to the error message using a separator that will be looked up from "activerecord.errors.format.separator":https://github.com/rails/rails/blob/master/actionpack/lib/action_view/locale/en.yml#L91 (and which defaults to +' '+). +* +ActiveModel::Errors#full_messages+ prepends the attribute name to the error message using a separator that will be looked up from "errors.format":https://github.com/rails/rails/blob/master/activemodel/lib/active_model/locale/en.yml#L4 (and which defaults to +"%{attribute} %{message}"+). h5. Active Support Methods diff --git a/railties/guides/source/migrations.textile b/railties/guides/source/migrations.textile index 66160f8b26..c11f8e221b 100644 --- a/railties/guides/source/migrations.textile +++ b/railties/guides/source/migrations.textile @@ -114,6 +114,7 @@ database independent way (you'll read about them in detail later): * +change_column+ * +change_table+ * +create_table+ +* +create_join_table+ * +drop_table+ * +remove_column+ * +remove_index+ @@ -384,6 +385,35 @@ end will append +ENGINE=BLACKHOLE+ to the SQL statement used to create the table (when using MySQL, the default is +ENGINE=InnoDB+). +h4. Creating a Join Table + +Migration method +create_join_table+ creates a HABTM join table. A typical use +would be + +<ruby> +create_join_table :products, :categories +</ruby> + +which creates a +categories_products+ table with two columns called +category_id+ and +product_id+. +These columns have the option +:null+ set to +false+ by default. + +You can pass the option +:table_name+ with you want to customize the table name. For example, + +<ruby> +create_join_table :products, :categories, :table_name => :categorization +</ruby> + +will create a +categorization+ table. + +By default, +create_join_table+ will create two columns with no options, but you can specify these +options using the +:column_options+ option. For example, + +<ruby> +create_join_table :products, :categories, :column_options => {:null => true} +</ruby> + +will create the +product_id+ and +category_id+ with the +:null+ option as +true+. + h4. Changing Tables A close cousin of +create_table+ is +change_table+, used for changing existing diff --git a/railties/guides/source/security.textile b/railties/guides/source/security.textile index c2ef7bf9b5..b1a09c0c05 100644 --- a/railties/guides/source/security.textile +++ b/railties/guides/source/security.textile @@ -385,7 +385,7 @@ params[:user] # => {:name => “ow3ned”, :admin => true} So if you create a new user using mass-assignment, it may be too easy to become an administrator. -Note that this vulnerability is not restricted to database columns. Any setter method, unless explicitly protected, is accessible via the <tt>attributes=</tt> method. In fact, this vulnerability is extended even further with the introduction of nested mass assignment (and nested object forms) in Rails 2.3+. The +accepts_nested_attributes_for+ declaration provides us the ability to extend mass assignment to model associations (+has_many+, +has_one+, +has_and_belongs_to_many+). For example: +Note that this vulnerability is not restricted to database columns. Any setter method, unless explicitly protected, is accessible via the <tt>attributes=</tt> method. In fact, this vulnerability is extended even further with the introduction of nested mass assignment (and nested object forms) in Rails 2.3<plus>. The +accepts_nested_attributes_for+ declaration provides us the ability to extend mass assignment to model associations (+has_many+, +has_one+, +has_and_belongs_to_many+). For example: <ruby> class Person < ActiveRecord::Base |