diff options
Diffstat (limited to 'activerecord')
31 files changed, 133 insertions, 1320 deletions
diff --git a/activerecord/lib/active_record/associations/association.rb b/activerecord/lib/active_record/associations/association.rb index 9f47e7e631..495f0cde59 100644 --- a/activerecord/lib/active_record/associations/association.rb +++ b/activerecord/lib/active_record/associations/association.rb @@ -233,10 +233,10 @@ module ActiveRecord def stale_state end - def build_record(attributes, options) - reflection.build_association(attributes, options) do |record| + def build_record(attributes) + reflection.build_association(attributes) do |record| attributes = create_scope.except(*(record.changed - [reflection.foreign_key])) - record.assign_attributes(attributes, :without_protection => true) + record.assign_attributes(attributes) end end end diff --git a/activerecord/lib/active_record/associations/collection_association.rb b/activerecord/lib/active_record/associations/collection_association.rb index 424c1a5b79..fe3e5b00f7 100644 --- a/activerecord/lib/active_record/associations/collection_association.rb +++ b/activerecord/lib/active_record/associations/collection_association.rb @@ -95,22 +95,22 @@ module ActiveRecord first_or_last(:last, *args) end - def build(attributes = {}, options = {}, &block) + def build(attributes = {}, &block) if attributes.is_a?(Array) - attributes.collect { |attr| build(attr, options, &block) } + attributes.collect { |attr| build(attr, &block) } else - add_to_target(build_record(attributes, options)) do |record| + add_to_target(build_record(attributes)) do |record| yield(record) if block_given? end end end - def create(attributes = {}, options = {}, &block) - create_record(attributes, options, &block) + def create(attributes = {}, &block) + create_record(attributes, &block) end - def create!(attributes = {}, options = {}, &block) - create_record(attributes, options, true, &block) + def create!(attributes = {}, &block) + create_record(attributes, true, &block) end # Add +records+ to this association. Returns +self+ so method calls may @@ -425,16 +425,16 @@ module ActiveRecord persisted + memory end - def create_record(attributes, options, raise = false, &block) + def create_record(attributes, raise = false, &block) unless owner.persisted? raise ActiveRecord::RecordNotSaved, "You cannot call create unless the parent is saved" end if attributes.is_a?(Array) - attributes.collect { |attr| create_record(attr, options, raise, &block) } + attributes.collect { |attr| create_record(attr, raise, &block) } else transaction do - add_to_target(build_record(attributes, options)) do |record| + add_to_target(build_record(attributes)) do |record| yield(record) if block_given? insert_record(record, true, raise) end diff --git a/activerecord/lib/active_record/associations/collection_proxy.rb b/activerecord/lib/active_record/associations/collection_proxy.rb index 66132b7260..c113957faa 100644 --- a/activerecord/lib/active_record/associations/collection_proxy.rb +++ b/activerecord/lib/active_record/associations/collection_proxy.rb @@ -222,8 +222,8 @@ module ActiveRecord # # person.pets.size # => 5 # size of the collection # person.pets.count # => 0 # count from database - def build(attributes = {}, options = {}, &block) - @association.build(attributes, options, &block) + def build(attributes = {}, &block) + @association.build(attributes, &block) end ## @@ -253,8 +253,8 @@ module ActiveRecord # # #<Pet id: 2, name: "Spook", person_id: 1>, # # #<Pet id: 3, name: "Choo-Choo", person_id: 1> # # ] - def create(attributes = {}, options = {}, &block) - @association.create(attributes, options, &block) + def create(attributes = {}, &block) + @association.create(attributes, &block) end ## @@ -265,14 +265,13 @@ module ActiveRecord # end # # class Pet - # attr_accessible :name # validates :name, presence: true # end # # person.pets.create!(name: nil) # # => ActiveRecord::RecordInvalid: Validation failed: Name can't be blank - def create!(attributes = {}, options = {}, &block) - @association.create!(attributes, options, &block) + def create!(attributes = {}, &block) + @association.create!(attributes, &block) end ## diff --git a/activerecord/lib/active_record/associations/has_many_through_association.rb b/activerecord/lib/active_record/associations/has_many_through_association.rb index d8f14c896c..c7d8a84a7e 100644 --- a/activerecord/lib/active_record/associations/has_many_through_association.rb +++ b/activerecord/lib/active_record/associations/has_many_through_association.rb @@ -96,10 +96,10 @@ module ActiveRecord @through_records.delete(record.object_id) end - def build_record(attributes, options = {}) + def build_record(attributes) ensure_not_nested - record = super(attributes, options) + record = super(attributes) inverse = source_reflection.inverse_of if inverse diff --git a/activerecord/lib/active_record/associations/singular_association.rb b/activerecord/lib/active_record/associations/singular_association.rb index b84cb4922d..32f4557c28 100644 --- a/activerecord/lib/active_record/associations/singular_association.rb +++ b/activerecord/lib/active_record/associations/singular_association.rb @@ -17,16 +17,16 @@ module ActiveRecord replace(record) end - def create(attributes = {}, options = {}, &block) - create_record(attributes, options, &block) + def create(attributes = {}, &block) + create_record(attributes, &block) end - def create!(attributes = {}, options = {}, &block) - create_record(attributes, options, true, &block) + def create!(attributes = {}, &block) + create_record(attributes, true, &block) end - def build(attributes = {}, options = {}) - record = build_record(attributes, options) + def build(attributes = {}) + record = build_record(attributes) yield(record) if block_given? set_new_record(record) record @@ -51,8 +51,8 @@ module ActiveRecord replace(record) end - def create_record(attributes, options, raise_error = false) - record = build_record(attributes, options) + def create_record(attributes, raise_error = false) + record = build_record(attributes) yield(record) if block_given? saved = record.save set_new_record(record) diff --git a/activerecord/lib/active_record/attribute_assignment.rb b/activerecord/lib/active_record/attribute_assignment.rb index d9989274c8..ccc61ec5d3 100644 --- a/activerecord/lib/active_record/attribute_assignment.rb +++ b/activerecord/lib/active_record/attribute_assignment.rb @@ -1,98 +1,32 @@ module ActiveRecord - ActiveSupport.on_load(:active_record_config) do - mattr_accessor :whitelist_attributes, instance_accessor: false - mattr_accessor :mass_assignment_sanitizer, instance_accessor: false - end - module AttributeAssignment extend ActiveSupport::Concern - include ActiveModel::MassAssignmentSecurity - - included do - initialize_mass_assignment_sanitizer - end - - module ClassMethods - def inherited(child) # :nodoc: - child.send :initialize_mass_assignment_sanitizer if self == Base - super - end - - private - - # The primary key and inheritance column can never be set by mass-assignment for security reasons. - def attributes_protected_by_default - default = [ primary_key, inheritance_column ] - default << 'id' unless primary_key.eql? 'id' - default - end - - def initialize_mass_assignment_sanitizer - attr_accessible(nil) if Model.whitelist_attributes - self.mass_assignment_sanitizer = Model.mass_assignment_sanitizer if Model.mass_assignment_sanitizer - end - end + include ActiveModel::DeprecatedMassAssignmentSecurity + include ActiveModel::ForbiddenAttributesProtection # Allows you to set all the attributes at once by passing in a hash with keys # matching the attribute names (which again matches the column names). # - # If any attributes are protected by either +attr_protected+ or - # +attr_accessible+ then only settable attributes will be assigned. - # - # class User < ActiveRecord::Base - # attr_protected :is_admin - # end - # - # user = User.new - # user.attributes = { :username => 'Phusion', :is_admin => true } - # user.username # => "Phusion" - # user.is_admin? # => false + # If the passed hash responds to permitted? method and the return value + # of this method is false an ActiveModel::ForbiddenAttributesError exception + # is raised. def attributes=(new_attributes) return unless new_attributes.is_a?(Hash) assign_attributes(new_attributes) end - # Allows you to set all the attributes for a particular mass-assignment - # security role by passing in a hash of attributes with keys matching - # the attribute names (which again matches the column names) and the role - # name using the :as option. - # - # To bypass mass-assignment security you can use the :without_protection => true - # option. - # - # class User < ActiveRecord::Base - # attr_accessible :name - # attr_accessible :name, :is_admin, :as => :admin - # end - # - # user = User.new - # user.assign_attributes({ :name => 'Josh', :is_admin => true }) - # user.name # => "Josh" - # user.is_admin? # => false - # - # user = User.new - # user.assign_attributes({ :name => 'Josh', :is_admin => true }, :as => :admin) - # user.name # => "Josh" - # user.is_admin? # => true - # - # user = User.new - # user.assign_attributes({ :name => 'Josh', :is_admin => true }, :without_protection => true) - # user.name # => "Josh" - # user.is_admin? # => true - def assign_attributes(new_attributes, options = {}) + # Allows you to set all the attributes by passing in a hash of attributes with + # keys matching the attribute names (which again matches the column names) + def assign_attributes(new_attributes) return if new_attributes.blank? attributes = new_attributes.stringify_keys multi_parameter_attributes = [] nested_parameter_attributes = [] - previous_options = @mass_assignment_options - @mass_assignment_options = options - unless options[:without_protection] - attributes = sanitize_for_mass_assignment(attributes, mass_assignment_role) - end + attributes = sanitize_for_mass_assignment(attributes) attributes.each do |k, v| if k.include?("(") @@ -106,18 +40,6 @@ module ActiveRecord assign_nested_parameter_attributes(nested_parameter_attributes) unless nested_parameter_attributes.empty? assign_multiparameter_attributes(multi_parameter_attributes) unless multi_parameter_attributes.empty? - ensure - @mass_assignment_options = previous_options - end - - protected - - def mass_assignment_options - @mass_assignment_options ||= {} - end - - def mass_assignment_role - mass_assignment_options[:as] || :default end private diff --git a/activerecord/lib/active_record/attribute_methods/primary_key.rb b/activerecord/lib/active_record/attribute_methods/primary_key.rb index 7b7811a706..aa6704d5c9 100644 --- a/activerecord/lib/active_record/attribute_methods/primary_key.rb +++ b/activerecord/lib/active_record/attribute_methods/primary_key.rb @@ -18,7 +18,7 @@ module ActiveRecord # Sets the primary key value def id=(value) - write_attribute(self.class.primary_key, value) + write_attribute(self.class.primary_key, value) if self.class.primary_key end # Queries the primary key value @@ -53,8 +53,7 @@ module ActiveRecord end # Defines the primary key field -- can be overridden in subclasses. Overwriting will negate any effect of the - # primary_key_prefix_type setting, though. Since primary keys are usually protected from mass assignment, - # remember to let your database generate them or include the key in +attr_accessible+. + # primary_key_prefix_type setting, though. def primary_key @primary_key = reset_primary_key unless defined? @primary_key @primary_key diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb index 43ffca0227..8f798830d4 100644 --- a/activerecord/lib/active_record/core.rb +++ b/activerecord/lib/active_record/core.rb @@ -172,7 +172,7 @@ module ActiveRecord # # # Instantiates a single new object bypassing mass-assignment security # User.new({ :first_name => 'Jamie', :is_admin => true }, :without_protection => true) - def initialize(attributes = nil, options = {}) + def initialize(attributes = nil) defaults = self.class.column_defaults.dup defaults.each { |k, v| defaults[k] = v.dup if v.duplicable? } @@ -183,7 +183,7 @@ module ActiveRecord ensure_proper_type populate_with_current_scope_attributes - assign_attributes(attributes, options) if attributes + assign_attributes(attributes) if attributes yield self if block_given? run_callbacks :initialize unless _initialize_callbacks.empty? @@ -386,7 +386,7 @@ module ActiveRecord @destroyed = false @marked_for_destruction = false @new_record = true - @mass_assignment_options = nil + @txn = nil @_start_transaction_state = {} end end diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb index 3005dc042c..a33285b16f 100644 --- a/activerecord/lib/active_record/nested_attributes.rb +++ b/activerecord/lib/active_record/nested_attributes.rb @@ -194,18 +194,6 @@ module ActiveRecord # the parent model is saved. This happens inside the transaction initiated # by the parents save method. See ActiveRecord::AutosaveAssociation. # - # === Using with attr_accessible - # - # The use of <tt>attr_accessible</tt> can interfere with nested attributes - # if you're not careful. For example, if the <tt>Member</tt> model above - # was using <tt>attr_accessible</tt> like this: - # - # attr_accessible :name - # - # You would need to modify it to look like this: - # - # attr_accessible :name, :posts_attributes - # # === Validating the presence of a parent model # # If you want to validate that a child record is associated with a parent @@ -224,9 +212,7 @@ module ActiveRecord module ClassMethods REJECT_ALL_BLANK_PROC = proc { |attributes| attributes.all? { |key, value| key == '_destroy' || value.blank? } } - # Defines an attributes writer for the specified association(s). If you - # are using <tt>attr_protected</tt> or <tt>attr_accessible</tt>, then you - # will need to add the attribute writer to the allowed list. + # Defines an attributes writer for the specified association(s). # # Supported options: # [:allow_destroy] @@ -296,7 +282,7 @@ module ActiveRecord remove_method(:#{association_name}_attributes=) end def #{association_name}_attributes=(attributes) - assign_nested_attributes_for_#{type}_association(:#{association_name}, attributes, mass_assignment_options) + assign_nested_attributes_for_#{type}_association(:#{association_name}, attributes) end eoruby else @@ -340,15 +326,15 @@ module ActiveRecord if (options[:update_only] || !attributes['id'].blank?) && (record = send(association_name)) && (options[:update_only] || record.id.to_s == attributes['id'].to_s) - assign_to_or_mark_for_destruction(record, attributes, options[:allow_destroy], assignment_opts) unless call_reject_if(association_name, attributes) + assign_to_or_mark_for_destruction(record, attributes, options[:allow_destroy]) unless call_reject_if(association_name, attributes) - elsif attributes['id'].present? && !assignment_opts[:without_protection] + elsif attributes['id'].present? raise_nested_attributes_record_not_found(association_name, attributes['id']) elsif !reject_new_record?(association_name, attributes) method = "build_#{association_name}" if respond_to?(method) - send(method, attributes.except(*unassignable_keys(assignment_opts)), assignment_opts) + send(method, attributes.except(*UNASSIGNABLE_KEYS)) else raise ArgumentError, "Cannot build association `#{association_name}'. Are you trying to build a polymorphic one-to-one association?" end @@ -382,7 +368,7 @@ module ActiveRecord # { :name => 'John' }, # { :id => '2', :_destroy => true } # ]) - def assign_nested_attributes_for_collection_association(association_name, attributes_collection, assignment_opts = {}) + def assign_nested_attributes_for_collection_association(association_name, attributes_collection) options = self.nested_attributes_options[association_name] unless attributes_collection.is_a?(Hash) || attributes_collection.is_a?(Array) @@ -427,7 +413,7 @@ module ActiveRecord if attributes['id'].blank? unless reject_new_record?(association_name, attributes) - association.build(attributes.except(*unassignable_keys(assignment_opts)), assignment_opts) + association.build(attributes.except(*UNASSIGNABLE_KEYS)) end elsif existing_record = existing_records.detect { |record| record.id.to_s == attributes['id'].to_s } unless association.loaded? || call_reject_if(association_name, attributes) @@ -443,10 +429,8 @@ module ActiveRecord end if !call_reject_if(association_name, attributes) - assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy], assignment_opts) + assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy]) end - elsif assignment_opts[:without_protection] - association.build(attributes.except(*unassignable_keys(assignment_opts)), assignment_opts) else raise_nested_attributes_record_not_found(association_name, attributes['id']) end @@ -455,8 +439,8 @@ module ActiveRecord # Updates a record with the +attributes+ or marks it for destruction if # +allow_destroy+ is +true+ and has_destroy_flag? returns +true+. - def assign_to_or_mark_for_destruction(record, attributes, allow_destroy, assignment_opts) - record.assign_attributes(attributes.except(*unassignable_keys(assignment_opts)), assignment_opts) + def assign_to_or_mark_for_destruction(record, attributes, allow_destroy) + record.assign_attributes(attributes.except(*UNASSIGNABLE_KEYS)) record.mark_for_destruction if has_destroy_flag?(attributes) && allow_destroy end @@ -487,7 +471,7 @@ module ActiveRecord end def unassignable_keys(assignment_opts) - assignment_opts[:without_protection] ? UNASSIGNABLE_KEYS - %w[id] : UNASSIGNABLE_KEYS + UNASSIGNABLE_KEYS end end end diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb index 7bd65c180d..6f38262b86 100644 --- a/activerecord/lib/active_record/persistence.rb +++ b/activerecord/lib/active_record/persistence.rb @@ -35,11 +35,11 @@ module ActiveRecord # User.create([{ :first_name => 'Jamie' }, { :first_name => 'Jeremy' }]) do |u| # u.is_admin = false # end - def create(attributes = nil, options = {}, &block) + def create(attributes = nil, &block) if attributes.is_a?(Array) - attributes.collect { |attr| create(attr, options, &block) } + attributes.collect { |attr| create(attr, &block) } else - object = new(attributes, options, &block) + object = new(attributes, &block) object.save object end @@ -186,24 +186,24 @@ module ActiveRecord # # When updating model attributes, mass-assignment security protection is respected. # If no +:as+ option is supplied then the +:default+ role will be used. - # If you want to bypass the protection given by +attr_protected+ and - # +attr_accessible+ then you can do so using the +:without_protection+ option. - def update_attributes(attributes, options = {}) + # If you want to bypass the forbidden attributes protection then you can do so using + # the +:without_protection+ option. + def update_attributes(attributes) # The following transaction covers any possible database side-effects of the # attributes assignment. For example, setting the IDs of a child collection. with_transaction_returning_status do - assign_attributes(attributes, options) + assign_attributes(attributes) save end end # Updates its receiver just like +update_attributes+ but calls <tt>save!</tt> instead # of +save+, so an exception is raised if the record is invalid. - def update_attributes!(attributes, options = {}) + def update_attributes!(attributes) # The following transaction covers any possible database side-effects of the # attributes assignment. For example, setting the IDs of a child collection. with_transaction_returning_status do - assign_attributes(attributes, options) + assign_attributes(attributes) save! end end diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index d9c65fa170..f322b96f79 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -181,8 +181,8 @@ module ActiveRecord # Returns a new, unsaved instance of the associated class. +options+ will # be passed to the class's constructor. - def build_association(*options, &block) - klass.new(*options, &block) + def build_association(attributes, &block) + klass.new(attributes, &block) end def table_name diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 2d0457636e..ed80422336 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -151,22 +151,22 @@ module ActiveRecord # user.last_name = "O'Hara" # end # # => <User id: 2, first_name: 'Scarlett', last_name: 'Johansson'> - def first_or_create(attributes = nil, options = {}, &block) - first || create(attributes, options, &block) + def first_or_create(attributes = nil, &block) + first || create(attributes, &block) end # Like <tt>first_or_create</tt> but calls <tt>create!</tt> so an exception is raised if the created record is invalid. # # Expects arguments in the same format as <tt>Base.create!</tt>. - def first_or_create!(attributes = nil, options = {}, &block) - first || create!(attributes, options, &block) + def first_or_create!(attributes = nil, &block) + first || create!(attributes, &block) end # Like <tt>first_or_create</tt> but calls <tt>new</tt> instead of <tt>create</tt>. # # Expects arguments in the same format as <tt>Base.new</tt>. - def first_or_initialize(attributes = nil, options = {}, &block) - first || new(attributes, options, &block) + def first_or_initialize(attributes = nil, &block) + first || new(attributes, &block) end # Runs EXPLAIN on the query or queries triggered by this relation and diff --git a/activerecord/lib/active_record/schema_migration.rb b/activerecord/lib/active_record/schema_migration.rb index ca22154c84..9830abe7d8 100644 --- a/activerecord/lib/active_record/schema_migration.rb +++ b/activerecord/lib/active_record/schema_migration.rb @@ -4,7 +4,6 @@ require 'active_record/base' module ActiveRecord class SchemaMigration < ActiveRecord::Base - attr_accessible :version def self.table_name "#{Base.table_name_prefix}schema_migrations#{Base.table_name_suffix}" diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb index cef2bbd563..ed561bfb3c 100644 --- a/activerecord/lib/active_record/validations.rb +++ b/activerecord/lib/active_record/validations.rb @@ -32,11 +32,11 @@ module ActiveRecord module ClassMethods # Creates an object just like Base.create but calls <tt>save!</tt> instead of +save+ # so an exception is raised if the record is invalid. - def create!(attributes = nil, options = {}, &block) + def create!(attributes = nil, &block) if attributes.is_a?(Array) - attributes.collect { |attr| create!(attr, options, &block) } + attributes.collect { |attr| create!(attr, &block) } else - object = new(attributes, options) + object = new(attributes) yield(object) if block_given? object.save! object diff --git a/activerecord/lib/rails/generators/active_record/model/templates/model.rb b/activerecord/lib/rails/generators/active_record/model/templates/model.rb index 2cca17b94f..056f55470c 100644 --- a/activerecord/lib/rails/generators/active_record/model/templates/model.rb +++ b/activerecord/lib/rails/generators/active_record/model/templates/model.rb @@ -3,10 +3,5 @@ class <%= class_name %> < <%= parent_class_name.classify %> <% attributes.select {|attr| attr.reference? }.each do |attribute| -%> belongs_to :<%= attribute.name %><%= ', polymorphic: true' if attribute.polymorphic? %> <% end -%> -<% if !accessible_attributes.empty? -%> - attr_accessible <%= accessible_attributes.map {|a| ":#{a.name}" }.sort.join(', ') %> -<% else -%> - # attr_accessible :title, :body -<% end -%> end <% end -%> diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb index 4405f34355..4b56037a08 100644 --- a/activerecord/test/cases/associations/has_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_associations_test.rb @@ -188,28 +188,6 @@ class HasManyAssociationsTest < ActiveRecord::TestCase assert_equal invoice.id, line_item.invoice_id end - def test_association_conditions_bypass_attribute_protection - car = Car.create(:name => 'honda') - - bulb = car.frickinawesome_bulbs.new - assert_equal true, bulb.frickinawesome? - - bulb = car.frickinawesome_bulbs.new(:frickinawesome => false) - assert_equal true, bulb.frickinawesome? - - bulb = car.frickinawesome_bulbs.build - assert_equal true, bulb.frickinawesome? - - bulb = car.frickinawesome_bulbs.build(:frickinawesome => false) - assert_equal true, bulb.frickinawesome? - - bulb = car.frickinawesome_bulbs.create - assert_equal true, bulb.frickinawesome? - - bulb = car.frickinawesome_bulbs.create(:frickinawesome => false) - assert_equal true, bulb.frickinawesome? - end - # When creating objects on the association, we must not do it within a scope (even though it # would be convenient), because this would cause that scope to be applied to any callbacks etc. def test_build_and_create_should_not_happen_within_scope @@ -1580,19 +1558,6 @@ class HasManyAssociationsTest < ActiveRecord::TestCase assert_equal "RED!", car.bulbs.to_a.first.color end - def test_new_is_called_with_attributes_and_options - car = Car.create(:name => 'honda') - - bulb = car.bulbs.build - assert_equal Bulb, bulb.class - - bulb = car.bulbs.build(:bulb_type => :custom) - assert_equal Bulb, bulb.class - - bulb = car.bulbs.build({ :bulb_type => :custom }, :as => :admin) - assert_equal CustomBulb, bulb.class - end - def test_abstract_class_with_polymorphic_has_many post = SubStiPost.create! :title => "fooo", :body => "baa" tagging = Tagging.create! :taggable => post diff --git a/activerecord/test/cases/associations/has_many_through_associations_test.rb b/activerecord/test/cases/associations/has_many_through_associations_test.rb index c591fd8532..d4ceae6f80 100644 --- a/activerecord/test/cases/associations/has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb @@ -58,21 +58,6 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase assert post.reload.people(true).include?(person) end - def test_associate_existing_with_strict_mass_assignment_sanitizer - SecureReader.mass_assignment_sanitizer = :strict - - SecureReader.new - - post = posts(:thinking) - person = people(:david) - - assert_queries(1) do - post.secure_people << person - end - ensure - SecureReader.mass_assignment_sanitizer = :logger - end - def test_associate_existing_record_twice_should_add_to_target_twice post = posts(:thinking) person = people(:david) diff --git a/activerecord/test/cases/associations/has_one_associations_test.rb b/activerecord/test/cases/associations/has_one_associations_test.rb index 8bc633f2b5..2d3cb654df 100644 --- a/activerecord/test/cases/associations/has_one_associations_test.rb +++ b/activerecord/test/cases/associations/has_one_associations_test.rb @@ -446,38 +446,6 @@ class HasOneAssociationsTest < ActiveRecord::TestCase assert_equal pirate.id, ship.pirate_id end - def test_association_conditions_bypass_attribute_protection - car = Car.create(:name => 'honda') - - bulb = car.build_frickinawesome_bulb - assert_equal true, bulb.frickinawesome? - - bulb = car.build_frickinawesome_bulb(:frickinawesome => false) - assert_equal true, bulb.frickinawesome? - - bulb = car.create_frickinawesome_bulb - assert_equal true, bulb.frickinawesome? - - bulb = car.create_frickinawesome_bulb(:frickinawesome => false) - assert_equal true, bulb.frickinawesome? - end - - def test_new_is_called_with_attributes_and_options - car = Car.create(:name => 'honda') - - bulb = car.build_bulb - assert_equal Bulb, bulb.class - - bulb = car.build_bulb - assert_equal Bulb, bulb.class - - bulb = car.build_bulb(:bulb_type => :custom) - assert_equal Bulb, bulb.class - - bulb = car.build_bulb({ :bulb_type => :custom }, :as => :admin) - assert_equal CustomBulb, bulb.class - end - def test_build_with_block car = Car.create(:name => 'honda') diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb index b25d169038..fbfdd0f07a 100644 --- a/activerecord/test/cases/base_test.rb +++ b/activerecord/test/cases/base_test.rb @@ -55,10 +55,6 @@ class ReadonlyTitlePost < Post attr_readonly :title end -class ProtectedTitlePost < Post - attr_protected :title -end - class Weird < ActiveRecord::Base; end class Boolean < ActiveRecord::Base diff --git a/activerecord/test/cases/deprecated_dynamic_methods_test.rb b/activerecord/test/cases/deprecated_dynamic_methods_test.rb index 392f5f4cd5..dde36e7f72 100644 --- a/activerecord/test/cases/deprecated_dynamic_methods_test.rb +++ b/activerecord/test/cases/deprecated_dynamic_methods_test.rb @@ -199,23 +199,7 @@ class DeprecatedDynamicMethodsTest < ActiveRecord::TestCase assert !new_customer.persisted? end - def test_find_or_initialize_from_one_attribute_should_not_set_attribute_even_when_protected - c = Company.find_or_initialize_by_name({:name => "Fortune 1000", :rating => 1000}) - assert_equal "Fortune 1000", c.name - assert_not_equal 1000, c.rating - assert c.valid? - assert !c.persisted? - end - - def test_find_or_create_from_one_attribute_should_not_set_attribute_even_when_protected - c = Company.find_or_create_by_name({:name => "Fortune 1000", :rating => 1000}) - assert_equal "Fortune 1000", c.name - assert_not_equal 1000, c.rating - assert c.valid? - assert c.persisted? - end - - def test_find_or_initialize_from_one_attribute_should_set_attribute_even_when_protected + def test_find_or_initialize_from_one_attribute_should_set_attribute c = Company.find_or_initialize_by_name_and_rating("Fortune 1000", 1000) assert_equal "Fortune 1000", c.name assert_equal 1000, c.rating @@ -223,7 +207,7 @@ class DeprecatedDynamicMethodsTest < ActiveRecord::TestCase assert !c.persisted? end - def test_find_or_create_from_one_attribute_should_set_attribute_even_when_protected + def test_find_or_create_from_one_attribute_should_set_attribute c = Company.find_or_create_by_name_and_rating("Fortune 1000", 1000) assert_equal "Fortune 1000", c.name assert_equal 1000, c.rating @@ -231,7 +215,7 @@ class DeprecatedDynamicMethodsTest < ActiveRecord::TestCase assert c.persisted? end - def test_find_or_initialize_from_one_attribute_should_set_attribute_even_when_protected_and_also_set_the_hash + def test_find_or_initialize_from_one_attribute_should_set_attribute_even_when_set_the_hash c = Company.find_or_initialize_by_rating(1000, {:name => "Fortune 1000"}) assert_equal "Fortune 1000", c.name assert_equal 1000, c.rating @@ -239,7 +223,7 @@ class DeprecatedDynamicMethodsTest < ActiveRecord::TestCase assert !c.persisted? end - def test_find_or_create_from_one_attribute_should_set_attribute_even_when_protected_and_also_set_the_hash + def test_find_or_create_from_one_attribute_should_set_attribute_even_when_set_the_hash c = Company.find_or_create_by_rating(1000, {:name => "Fortune 1000"}) assert_equal "Fortune 1000", c.name assert_equal 1000, c.rating @@ -247,7 +231,7 @@ class DeprecatedDynamicMethodsTest < ActiveRecord::TestCase assert c.persisted? end - def test_find_or_initialize_should_set_protected_attributes_if_given_as_block + def test_find_or_initialize_should_set_attributes_if_given_as_block c = Company.find_or_initialize_by_name(:name => "Fortune 1000") { |f| f.rating = 1000 } assert_equal "Fortune 1000", c.name assert_equal 1000.to_f, c.rating.to_f @@ -255,7 +239,7 @@ class DeprecatedDynamicMethodsTest < ActiveRecord::TestCase assert !c.persisted? end - def test_find_or_create_should_set_protected_attributes_if_given_as_block + def test_find_or_create_should_set_attributes_if_given_as_block c = Company.find_or_create_by_name(:name => "Fortune 1000") { |f| f.rating = 1000 } assert_equal "Fortune 1000", c.name assert_equal 1000.to_f, c.rating.to_f diff --git a/activerecord/test/cases/dup_test.rb b/activerecord/test/cases/dup_test.rb index 9705a11387..71b2b16608 100644 --- a/activerecord/test/cases/dup_test.rb +++ b/activerecord/test/cases/dup_test.rb @@ -49,7 +49,7 @@ module ActiveRecord dbtopic = Topic.first topic = Topic.new - topic.attributes = dbtopic.attributes + topic.attributes = dbtopic.attributes.except("id") #duped has no timestamp values duped = dbtopic.dup diff --git a/activerecord/test/cases/forbidden_attributes_protection_test.rb b/activerecord/test/cases/forbidden_attributes_protection_test.rb new file mode 100644 index 0000000000..9a2172f41e --- /dev/null +++ b/activerecord/test/cases/forbidden_attributes_protection_test.rb @@ -0,0 +1,49 @@ +require 'cases/helper' +require 'active_support/core_ext/hash/indifferent_access' +require 'models/person' + +class ProtectedParams < ActiveSupport::HashWithIndifferentAccess + attr_accessor :permitted + alias :permitted? :permitted + + def initialize(attributes) + super(attributes) + @permitted = false + end + + def permit! + @permitted = true + self + end + + def dup + super.tap do |duplicate| + duplicate.instance_variable_set :@permitted, @permitted + end + end +end + +class ForbiddenAttributesProtectionTest < ActiveRecord::TestCase + def test_forbidden_attributes_cannot_be_used_for_mass_assignment + params = ProtectedParams.new(first_name: 'Guille', gender: 'm') + assert_raises(ActiveModel::ForbiddenAttributesError) do + Person.new(params) + end + end + + def test_permitted_attributes_can_be_used_for_mass_assignment + params = ProtectedParams.new(first_name: 'Guille', gender: 'm') + params.permit! + person = Person.new(params) + + assert_equal 'Guille', person.first_name + assert_equal 'm', person.gender + end + + def test_regular_hash_should_still_be_used_for_mass_assignment + person = Person.new(first_name: 'Guille', gender: 'm') + + assert_equal 'Guille', person.first_name + assert_equal 'm', person.gender + end +end diff --git a/activerecord/test/cases/mass_assignment_security_test.rb b/activerecord/test/cases/mass_assignment_security_test.rb deleted file mode 100644 index a36b2c2506..0000000000 --- a/activerecord/test/cases/mass_assignment_security_test.rb +++ /dev/null @@ -1,966 +0,0 @@ -require "cases/helper" -require 'models/company' -require 'models/subscriber' -require 'models/keyboard' -require 'models/task' -require 'models/person' - - -module MassAssignmentTestHelpers - def setup - # another AR test modifies the columns which causes issues with create calls - TightPerson.reset_column_information - LoosePerson.reset_column_information - end - - def attributes_hash - { - :id => 5, - :first_name => 'Josh', - :gender => 'm', - :comments => 'rides a sweet bike' - } - end - - def assert_default_attributes(person, create = false) - unless create - assert_nil person.id - else - assert !!person.id - end - assert_equal 'Josh', person.first_name - assert_equal 'm', person.gender - assert_nil person.comments - end - - def assert_admin_attributes(person, create = false) - unless create - assert_nil person.id - else - assert !!person.id - end - assert_equal 'Josh', person.first_name - assert_equal 'm', person.gender - assert_equal 'rides a sweet bike', person.comments - end - - def assert_all_attributes(person) - assert_equal 5, person.id - assert_equal 'Josh', person.first_name - assert_equal 'm', person.gender - assert_equal 'rides a sweet bike', person.comments - end - - def with_strict_sanitizer - ActiveRecord::Base.mass_assignment_sanitizer = :strict - yield - ensure - ActiveRecord::Base.mass_assignment_sanitizer = :logger - end -end - -module MassAssignmentRelationTestHelpers - def setup - super - @person = LoosePerson.create(attributes_hash) - end -end - - -class MassAssignmentSecurityTest < ActiveRecord::TestCase - include MassAssignmentTestHelpers - - def test_customized_primary_key_remains_protected - subscriber = Subscriber.new(:nick => 'webster123', :name => 'nice try') - assert_nil subscriber.id - - keyboard = Keyboard.new(:key_number => 9, :name => 'nice try') - assert_nil keyboard.id - end - - def test_customized_primary_key_remains_protected_when_referred_to_as_id - subscriber = Subscriber.new(:id => 'webster123', :name => 'nice try') - assert_nil subscriber.id - - keyboard = Keyboard.new(:id => 9, :name => 'nice try') - assert_nil keyboard.id - end - - def test_mass_assigning_invalid_attribute - firm = Firm.new - - assert_raise(ActiveRecord::UnknownAttributeError) do - firm.attributes = { "id" => 5, "type" => "Client", "i_dont_even_exist" => 20 } - end - end - - def test_mass_assigning_does_not_choke_on_nil - assert_nil Firm.new.assign_attributes(nil) - end - - def test_mass_assigning_does_not_choke_on_empty_hash - assert_nil Firm.new.assign_attributes({}) - end - - def test_assign_attributes_uses_default_role_when_no_role_is_provided - p = LoosePerson.new - p.assign_attributes(attributes_hash) - - assert_default_attributes(p) - end - - def test_assign_attributes_skips_mass_assignment_security_protection_when_without_protection_is_used - p = LoosePerson.new - p.assign_attributes(attributes_hash, :without_protection => true) - - assert_all_attributes(p) - end - - def test_assign_attributes_with_default_role_and_attr_protected_attributes - p = LoosePerson.new - p.assign_attributes(attributes_hash, :as => :default) - - assert_default_attributes(p) - end - - def test_assign_attributes_with_admin_role_and_attr_protected_attributes - p = LoosePerson.new - p.assign_attributes(attributes_hash, :as => :admin) - - assert_admin_attributes(p) - end - - def test_assign_attributes_with_default_role_and_attr_accessible_attributes - p = TightPerson.new - p.assign_attributes(attributes_hash, :as => :default) - - assert_default_attributes(p) - end - - def test_assign_attributes_with_admin_role_and_attr_accessible_attributes - p = TightPerson.new - p.assign_attributes(attributes_hash, :as => :admin) - - assert_admin_attributes(p) - end - - def test_new_with_attr_accessible_attributes - p = TightPerson.new(attributes_hash) - - assert_default_attributes(p) - end - - def test_new_with_attr_protected_attributes - p = LoosePerson.new(attributes_hash) - - assert_default_attributes(p) - end - - def test_create_with_attr_accessible_attributes - p = TightPerson.create(attributes_hash) - - assert_default_attributes(p, true) - end - - def test_create_with_attr_protected_attributes - p = LoosePerson.create(attributes_hash) - - assert_default_attributes(p, true) - end - - def test_new_with_admin_role_with_attr_accessible_attributes - p = TightPerson.new(attributes_hash, :as => :admin) - - assert_admin_attributes(p) - end - - def test_new_with_admin_role_with_attr_protected_attributes - p = LoosePerson.new(attributes_hash, :as => :admin) - - assert_admin_attributes(p) - end - - def test_create_with_admin_role_with_attr_accessible_attributes - p = TightPerson.create(attributes_hash, :as => :admin) - - assert_admin_attributes(p, true) - end - - def test_create_with_admin_role_with_attr_protected_attributes - p = LoosePerson.create(attributes_hash, :as => :admin) - - assert_admin_attributes(p, true) - end - - def test_create_with_bang_with_admin_role_with_attr_accessible_attributes - p = TightPerson.create!(attributes_hash, :as => :admin) - - assert_admin_attributes(p, true) - end - - def test_create_with_bang_with_admin_role_with_attr_protected_attributes - p = LoosePerson.create!(attributes_hash, :as => :admin) - - assert_admin_attributes(p, true) - end - - def test_new_with_without_protection_with_attr_accessible_attributes - p = TightPerson.new(attributes_hash, :without_protection => true) - - assert_all_attributes(p) - end - - def test_new_with_without_protection_with_attr_protected_attributes - p = LoosePerson.new(attributes_hash, :without_protection => true) - - assert_all_attributes(p) - end - - def test_create_with_without_protection_with_attr_accessible_attributes - p = TightPerson.create(attributes_hash, :without_protection => true) - - assert_all_attributes(p) - end - - def test_create_with_without_protection_with_attr_protected_attributes - p = LoosePerson.create(attributes_hash, :without_protection => true) - - assert_all_attributes(p) - end - - def test_create_with_bang_with_without_protection_with_attr_accessible_attributes - p = TightPerson.create!(attributes_hash, :without_protection => true) - - assert_all_attributes(p) - end - - def test_create_with_bang_with_without_protection_with_attr_protected_attributes - p = LoosePerson.create!(attributes_hash, :without_protection => true) - - assert_all_attributes(p) - end - - def test_protection_against_class_attribute_writers - [:logger, :configurations, :primary_key_prefix_type, :table_name_prefix, :table_name_suffix, :pluralize_table_names, - :default_timezone, :schema_format, :lock_optimistically, :timestamped_migrations, :default_scopes, - :connection_handler, :nested_attributes_options, :_attr_readonly, :attribute_types_cached_by_default, - :attribute_method_matchers, :time_zone_aware_attributes, :skip_time_zone_conversion_for_attributes].each do |method| - assert_respond_to Task, method - assert_respond_to Task, "#{method}=" - assert_respond_to Task.new, method - assert !Task.new.respond_to?("#{method}=") - end - end - - test "ActiveRecord::Model.whitelist_attributes works for models which include Model" do - begin - prev, ActiveRecord::Model.whitelist_attributes = ActiveRecord::Model.whitelist_attributes, true - - klass = Class.new { include ActiveRecord::Model } - assert_equal ActiveModel::MassAssignmentSecurity::WhiteList, klass.active_authorizers[:default].class - assert_equal [], klass.active_authorizers[:default].to_a - ensure - ActiveRecord::Model.whitelist_attributes = prev - end - end - - test "ActiveRecord::Model.whitelist_attributes works for models which inherit Base" do - begin - prev, ActiveRecord::Model.whitelist_attributes = ActiveRecord::Model.whitelist_attributes, true - - klass = Class.new(ActiveRecord::Base) - assert_equal ActiveModel::MassAssignmentSecurity::WhiteList, klass.active_authorizers[:default].class - assert_equal [], klass.active_authorizers[:default].to_a - - klass.attr_accessible 'foo' - assert_equal ['foo'], Class.new(klass).active_authorizers[:default].to_a - ensure - ActiveRecord::Model.whitelist_attributes = prev - end - end - - test "ActiveRecord::Model.mass_assignment_sanitizer works for models which include Model" do - begin - sanitizer = Object.new - prev, ActiveRecord::Model.mass_assignment_sanitizer = ActiveRecord::Model.mass_assignment_sanitizer, sanitizer - - klass = Class.new { include ActiveRecord::Model } - assert_equal sanitizer, klass._mass_assignment_sanitizer - - ActiveRecord::Model.mass_assignment_sanitizer = nil - klass = Class.new { include ActiveRecord::Model } - assert_not_nil klass._mass_assignment_sanitizer - ensure - ActiveRecord::Model.mass_assignment_sanitizer = prev - end - end - - test "ActiveRecord::Model.mass_assignment_sanitizer works for models which inherit Base" do - begin - sanitizer = Object.new - prev, ActiveRecord::Model.mass_assignment_sanitizer = ActiveRecord::Model.mass_assignment_sanitizer, sanitizer - - klass = Class.new(ActiveRecord::Base) - assert_equal sanitizer, klass._mass_assignment_sanitizer - - sanitizer2 = Object.new - klass.mass_assignment_sanitizer = sanitizer2 - assert_equal sanitizer2, Class.new(klass)._mass_assignment_sanitizer - ensure - ActiveRecord::Model.mass_assignment_sanitizer = prev - end - end -end - - -# This class should be deleted when we remove activerecord-deprecated_finders as a -# dependency. -class MassAssignmentSecurityDeprecatedFindersTest < ActiveRecord::TestCase - include MassAssignmentTestHelpers - - def setup - super - @deprecation_behavior = ActiveSupport::Deprecation.behavior - ActiveSupport::Deprecation.behavior = :silence - end - - def teardown - ActiveSupport::Deprecation.behavior = @deprecation_behavior - end - - def test_find_or_initialize_by_with_attr_accessible_attributes - p = TightPerson.find_or_initialize_by_first_name('Josh', attributes_hash) - - assert_default_attributes(p) - end - - def test_find_or_initialize_by_with_admin_role_with_attr_accessible_attributes - p = TightPerson.find_or_initialize_by_first_name('Josh', attributes_hash, :as => :admin) - - assert_admin_attributes(p) - end - - def test_find_or_initialize_by_with_attr_protected_attributes - p = LoosePerson.find_or_initialize_by_first_name('Josh', attributes_hash) - - assert_default_attributes(p) - end - - def test_find_or_initialize_by_with_admin_role_with_attr_protected_attributes - p = LoosePerson.find_or_initialize_by_first_name('Josh', attributes_hash, :as => :admin) - - assert_admin_attributes(p) - end - - def test_find_or_create_by_with_attr_accessible_attributes - p = TightPerson.find_or_create_by_first_name('Josh', attributes_hash) - - assert_default_attributes(p, true) - end - - def test_find_or_create_by_with_admin_role_with_attr_accessible_attributes - p = TightPerson.find_or_create_by_first_name('Josh', attributes_hash, :as => :admin) - - assert_admin_attributes(p, true) - end - - def test_find_or_create_by_with_attr_protected_attributes - p = LoosePerson.find_or_create_by_first_name('Josh', attributes_hash) - - assert_default_attributes(p, true) - end - - def test_find_or_create_by_with_admin_role_with_attr_protected_attributes - p = LoosePerson.find_or_create_by_first_name('Josh', attributes_hash, :as => :admin) - - assert_admin_attributes(p, true) - end - -end - - -class MassAssignmentSecurityHasOneRelationsTest < ActiveRecord::TestCase - include MassAssignmentTestHelpers - include MassAssignmentRelationTestHelpers - - # build - - def test_has_one_build_with_attr_protected_attributes - best_friend = @person.build_best_friend(attributes_hash) - assert_default_attributes(best_friend) - end - - def test_has_one_build_with_attr_accessible_attributes - best_friend = @person.build_best_friend(attributes_hash) - assert_default_attributes(best_friend) - end - - def test_has_one_build_with_admin_role_with_attr_protected_attributes - best_friend = @person.build_best_friend(attributes_hash, :as => :admin) - assert_admin_attributes(best_friend) - end - - def test_has_one_build_with_admin_role_with_attr_accessible_attributes - best_friend = @person.build_best_friend(attributes_hash, :as => :admin) - assert_admin_attributes(best_friend) - end - - def test_has_one_build_without_protection - best_friend = @person.build_best_friend(attributes_hash, :without_protection => true) - assert_all_attributes(best_friend) - end - - def test_has_one_build_with_strict_sanitizer - with_strict_sanitizer do - best_friend = @person.build_best_friend(attributes_hash.except(:id, :comments)) - assert_equal @person.id, best_friend.best_friend_id - end - end - - # create - - def test_has_one_create_with_attr_protected_attributes - best_friend = @person.create_best_friend(attributes_hash) - assert_default_attributes(best_friend, true) - end - - def test_has_one_create_with_attr_accessible_attributes - best_friend = @person.create_best_friend(attributes_hash) - assert_default_attributes(best_friend, true) - end - - def test_has_one_create_with_admin_role_with_attr_protected_attributes - best_friend = @person.create_best_friend(attributes_hash, :as => :admin) - assert_admin_attributes(best_friend, true) - end - - def test_has_one_create_with_admin_role_with_attr_accessible_attributes - best_friend = @person.create_best_friend(attributes_hash, :as => :admin) - assert_admin_attributes(best_friend, true) - end - - def test_has_one_create_without_protection - best_friend = @person.create_best_friend(attributes_hash, :without_protection => true) - assert_all_attributes(best_friend) - end - - def test_has_one_create_with_strict_sanitizer - with_strict_sanitizer do - best_friend = @person.create_best_friend(attributes_hash.except(:id, :comments)) - assert_equal @person.id, best_friend.best_friend_id - end - end - - # create! - - def test_has_one_create_with_bang_with_attr_protected_attributes - best_friend = @person.create_best_friend!(attributes_hash) - assert_default_attributes(best_friend, true) - end - - def test_has_one_create_with_bang_with_attr_accessible_attributes - best_friend = @person.create_best_friend!(attributes_hash) - assert_default_attributes(best_friend, true) - end - - def test_has_one_create_with_bang_with_admin_role_with_attr_protected_attributes - best_friend = @person.create_best_friend!(attributes_hash, :as => :admin) - assert_admin_attributes(best_friend, true) - end - - def test_has_one_create_with_bang_with_admin_role_with_attr_accessible_attributes - best_friend = @person.create_best_friend!(attributes_hash, :as => :admin) - assert_admin_attributes(best_friend, true) - end - - def test_has_one_create_with_bang_without_protection - best_friend = @person.create_best_friend!(attributes_hash, :without_protection => true) - assert_all_attributes(best_friend) - end - - def test_has_one_create_with_bang_with_strict_sanitizer - with_strict_sanitizer do - best_friend = @person.create_best_friend!(attributes_hash.except(:id, :comments)) - assert_equal @person.id, best_friend.best_friend_id - end - end - -end - - -class MassAssignmentSecurityBelongsToRelationsTest < ActiveRecord::TestCase - include MassAssignmentTestHelpers - include MassAssignmentRelationTestHelpers - - # build - - def test_belongs_to_build_with_attr_protected_attributes - best_friend = @person.build_best_friend_of(attributes_hash) - assert_default_attributes(best_friend) - end - - def test_belongs_to_build_with_attr_accessible_attributes - best_friend = @person.build_best_friend_of(attributes_hash) - assert_default_attributes(best_friend) - end - - def test_belongs_to_build_with_admin_role_with_attr_protected_attributes - best_friend = @person.build_best_friend_of(attributes_hash, :as => :admin) - assert_admin_attributes(best_friend) - end - - def test_belongs_to_build_with_admin_role_with_attr_accessible_attributes - best_friend = @person.build_best_friend_of(attributes_hash, :as => :admin) - assert_admin_attributes(best_friend) - end - - def test_belongs_to_build_without_protection - best_friend = @person.build_best_friend_of(attributes_hash, :without_protection => true) - assert_all_attributes(best_friend) - end - - # create - - def test_belongs_to_create_with_attr_protected_attributes - best_friend = @person.create_best_friend_of(attributes_hash) - assert_default_attributes(best_friend, true) - end - - def test_belongs_to_create_with_attr_accessible_attributes - best_friend = @person.create_best_friend_of(attributes_hash) - assert_default_attributes(best_friend, true) - end - - def test_belongs_to_create_with_admin_role_with_attr_protected_attributes - best_friend = @person.create_best_friend_of(attributes_hash, :as => :admin) - assert_admin_attributes(best_friend, true) - end - - def test_belongs_to_create_with_admin_role_with_attr_accessible_attributes - best_friend = @person.create_best_friend_of(attributes_hash, :as => :admin) - assert_admin_attributes(best_friend, true) - end - - def test_belongs_to_create_without_protection - best_friend = @person.create_best_friend_of(attributes_hash, :without_protection => true) - assert_all_attributes(best_friend) - end - - def test_belongs_to_create_with_strict_sanitizer - with_strict_sanitizer do - best_friend = @person.create_best_friend_of(attributes_hash.except(:id, :comments)) - assert_equal best_friend.id, @person.best_friend_of_id - end - end - - # create! - - def test_belongs_to_create_with_bang_with_attr_protected_attributes - best_friend = @person.create_best_friend!(attributes_hash) - assert_default_attributes(best_friend, true) - end - - def test_belongs_to_create_with_bang_with_attr_accessible_attributes - best_friend = @person.create_best_friend!(attributes_hash) - assert_default_attributes(best_friend, true) - end - - def test_belongs_to_create_with_bang_with_admin_role_with_attr_protected_attributes - best_friend = @person.create_best_friend!(attributes_hash, :as => :admin) - assert_admin_attributes(best_friend, true) - end - - def test_belongs_to_create_with_bang_with_admin_role_with_attr_accessible_attributes - best_friend = @person.create_best_friend!(attributes_hash, :as => :admin) - assert_admin_attributes(best_friend, true) - end - - def test_belongs_to_create_with_bang_without_protection - best_friend = @person.create_best_friend!(attributes_hash, :without_protection => true) - assert_all_attributes(best_friend) - end - - def test_belongs_to_create_with_bang_with_strict_sanitizer - with_strict_sanitizer do - best_friend = @person.create_best_friend_of!(attributes_hash.except(:id, :comments)) - assert_equal best_friend.id, @person.best_friend_of_id - end - end - -end - - -class MassAssignmentSecurityHasManyRelationsTest < ActiveRecord::TestCase - include MassAssignmentTestHelpers - include MassAssignmentRelationTestHelpers - - # build - - def test_has_many_build_with_attr_protected_attributes - best_friend = @person.best_friends.build(attributes_hash) - assert_default_attributes(best_friend) - end - - def test_has_many_build_with_attr_accessible_attributes - best_friend = @person.best_friends.build(attributes_hash) - assert_default_attributes(best_friend) - end - - def test_has_many_build_with_admin_role_with_attr_protected_attributes - best_friend = @person.best_friends.build(attributes_hash, :as => :admin) - assert_admin_attributes(best_friend) - end - - def test_has_many_build_with_admin_role_with_attr_accessible_attributes - best_friend = @person.best_friends.build(attributes_hash, :as => :admin) - assert_admin_attributes(best_friend) - end - - def test_has_many_build_without_protection - best_friend = @person.best_friends.build(attributes_hash, :without_protection => true) - assert_all_attributes(best_friend) - end - - def test_has_many_build_with_strict_sanitizer - with_strict_sanitizer do - best_friend = @person.best_friends.build(attributes_hash.except(:id, :comments)) - assert_equal @person.id, best_friend.best_friend_id - end - end - - # create - - def test_has_many_create_with_attr_protected_attributes - best_friend = @person.best_friends.create(attributes_hash) - assert_default_attributes(best_friend, true) - end - - def test_has_many_create_with_attr_accessible_attributes - best_friend = @person.best_friends.create(attributes_hash) - assert_default_attributes(best_friend, true) - end - - def test_has_many_create_with_admin_role_with_attr_protected_attributes - best_friend = @person.best_friends.create(attributes_hash, :as => :admin) - assert_admin_attributes(best_friend, true) - end - - def test_has_many_create_with_admin_role_with_attr_accessible_attributes - best_friend = @person.best_friends.create(attributes_hash, :as => :admin) - assert_admin_attributes(best_friend, true) - end - - def test_has_many_create_without_protection - best_friend = @person.best_friends.create(attributes_hash, :without_protection => true) - assert_all_attributes(best_friend) - end - - def test_has_many_create_with_strict_sanitizer - with_strict_sanitizer do - best_friend = @person.best_friends.create(attributes_hash.except(:id, :comments)) - assert_equal @person.id, best_friend.best_friend_id - end - end - - # create! - - def test_has_many_create_with_bang_with_attr_protected_attributes - best_friend = @person.best_friends.create!(attributes_hash) - assert_default_attributes(best_friend, true) - end - - def test_has_many_create_with_bang_with_attr_accessible_attributes - best_friend = @person.best_friends.create!(attributes_hash) - assert_default_attributes(best_friend, true) - end - - def test_has_many_create_with_bang_with_admin_role_with_attr_protected_attributes - best_friend = @person.best_friends.create!(attributes_hash, :as => :admin) - assert_admin_attributes(best_friend, true) - end - - def test_has_many_create_with_bang_with_admin_role_with_attr_accessible_attributes - best_friend = @person.best_friends.create!(attributes_hash, :as => :admin) - assert_admin_attributes(best_friend, true) - end - - def test_has_many_create_with_bang_without_protection - best_friend = @person.best_friends.create!(attributes_hash, :without_protection => true) - assert_all_attributes(best_friend) - end - - def test_has_many_create_with_bang_with_strict_sanitizer - with_strict_sanitizer do - best_friend = @person.best_friends.create!(attributes_hash.except(:id, :comments)) - assert_equal @person.id, best_friend.best_friend_id - end - end - -end - - -class MassAssignmentSecurityNestedAttributesTest < ActiveRecord::TestCase - include MassAssignmentTestHelpers - - def nested_attributes_hash(association, collection = false, except = [:id]) - if collection - { :first_name => 'David' }.merge(:"#{association}_attributes" => [attributes_hash.except(*except)]) - else - { :first_name => 'David' }.merge(:"#{association}_attributes" => attributes_hash.except(*except)) - end - end - - # build - - def test_has_one_new_with_attr_protected_attributes - person = LoosePerson.new(nested_attributes_hash(:best_friend)) - assert_default_attributes(person.best_friend) - end - - def test_has_one_new_with_attr_accessible_attributes - person = TightPerson.new(nested_attributes_hash(:best_friend)) - assert_default_attributes(person.best_friend) - end - - def test_has_one_new_with_admin_role_with_attr_protected_attributes - person = LoosePerson.new(nested_attributes_hash(:best_friend), :as => :admin) - assert_admin_attributes(person.best_friend) - end - - def test_has_one_new_with_admin_role_with_attr_accessible_attributes - person = TightPerson.new(nested_attributes_hash(:best_friend), :as => :admin) - assert_admin_attributes(person.best_friend) - end - - def test_has_one_new_without_protection - person = LoosePerson.new(nested_attributes_hash(:best_friend, false, nil), :without_protection => true) - assert_all_attributes(person.best_friend) - end - - def test_belongs_to_new_with_attr_protected_attributes - person = LoosePerson.new(nested_attributes_hash(:best_friend_of)) - assert_default_attributes(person.best_friend_of) - end - - def test_belongs_to_new_with_attr_accessible_attributes - person = TightPerson.new(nested_attributes_hash(:best_friend_of)) - assert_default_attributes(person.best_friend_of) - end - - def test_belongs_to_new_with_admin_role_with_attr_protected_attributes - person = LoosePerson.new(nested_attributes_hash(:best_friend_of), :as => :admin) - assert_admin_attributes(person.best_friend_of) - end - - def test_belongs_to_new_with_admin_role_with_attr_accessible_attributes - person = TightPerson.new(nested_attributes_hash(:best_friend_of), :as => :admin) - assert_admin_attributes(person.best_friend_of) - end - - def test_belongs_to_new_without_protection - person = LoosePerson.new(nested_attributes_hash(:best_friend_of, false, nil), :without_protection => true) - assert_all_attributes(person.best_friend_of) - end - - def test_has_many_new_with_attr_protected_attributes - person = LoosePerson.new(nested_attributes_hash(:best_friends, true)) - assert_default_attributes(person.best_friends.first) - end - - def test_has_many_new_with_attr_accessible_attributes - person = TightPerson.new(nested_attributes_hash(:best_friends, true)) - assert_default_attributes(person.best_friends.first) - end - - def test_has_many_new_with_admin_role_with_attr_protected_attributes - person = LoosePerson.new(nested_attributes_hash(:best_friends, true), :as => :admin) - assert_admin_attributes(person.best_friends.first) - end - - def test_has_many_new_with_admin_role_with_attr_accessible_attributes - person = TightPerson.new(nested_attributes_hash(:best_friends, true), :as => :admin) - assert_admin_attributes(person.best_friends.first) - end - - def test_has_many_new_without_protection - person = LoosePerson.new(nested_attributes_hash(:best_friends, true, nil), :without_protection => true) - assert_all_attributes(person.best_friends.first) - end - - # create - - def test_has_one_create_with_attr_protected_attributes - person = LoosePerson.create(nested_attributes_hash(:best_friend)) - assert_default_attributes(person.best_friend, true) - end - - def test_has_one_create_with_attr_accessible_attributes - person = TightPerson.create(nested_attributes_hash(:best_friend)) - assert_default_attributes(person.best_friend, true) - end - - def test_has_one_create_with_admin_role_with_attr_protected_attributes - person = LoosePerson.create(nested_attributes_hash(:best_friend), :as => :admin) - assert_admin_attributes(person.best_friend, true) - end - - def test_has_one_create_with_admin_role_with_attr_accessible_attributes - person = TightPerson.create(nested_attributes_hash(:best_friend), :as => :admin) - assert_admin_attributes(person.best_friend, true) - end - - def test_has_one_create_without_protection - person = LoosePerson.create(nested_attributes_hash(:best_friend, false, nil), :without_protection => true) - assert_all_attributes(person.best_friend) - end - - def test_belongs_to_create_with_attr_protected_attributes - person = LoosePerson.create(nested_attributes_hash(:best_friend_of)) - assert_default_attributes(person.best_friend_of, true) - end - - def test_belongs_to_create_with_attr_accessible_attributes - person = TightPerson.create(nested_attributes_hash(:best_friend_of)) - assert_default_attributes(person.best_friend_of, true) - end - - def test_belongs_to_create_with_admin_role_with_attr_protected_attributes - person = LoosePerson.create(nested_attributes_hash(:best_friend_of), :as => :admin) - assert_admin_attributes(person.best_friend_of, true) - end - - def test_belongs_to_create_with_admin_role_with_attr_accessible_attributes - person = TightPerson.create(nested_attributes_hash(:best_friend_of), :as => :admin) - assert_admin_attributes(person.best_friend_of, true) - end - - def test_belongs_to_create_without_protection - person = LoosePerson.create(nested_attributes_hash(:best_friend_of, false, nil), :without_protection => true) - assert_all_attributes(person.best_friend_of) - end - - def test_has_many_create_with_attr_protected_attributes - person = LoosePerson.create(nested_attributes_hash(:best_friends, true)) - assert_default_attributes(person.best_friends.first, true) - end - - def test_has_many_create_with_attr_accessible_attributes - person = TightPerson.create(nested_attributes_hash(:best_friends, true)) - assert_default_attributes(person.best_friends.first, true) - end - - def test_has_many_create_with_admin_role_with_attr_protected_attributes - person = LoosePerson.create(nested_attributes_hash(:best_friends, true), :as => :admin) - assert_admin_attributes(person.best_friends.first, true) - end - - def test_has_many_create_with_admin_role_with_attr_accessible_attributes - person = TightPerson.create(nested_attributes_hash(:best_friends, true), :as => :admin) - assert_admin_attributes(person.best_friends.first, true) - end - - def test_has_many_create_without_protection - person = LoosePerson.create(nested_attributes_hash(:best_friends, true, nil), :without_protection => true) - assert_all_attributes(person.best_friends.first) - end - - # create! - - def test_has_one_create_with_bang_with_attr_protected_attributes - person = LoosePerson.create!(nested_attributes_hash(:best_friend)) - assert_default_attributes(person.best_friend, true) - end - - def test_has_one_create_with_bang_with_attr_accessible_attributes - person = TightPerson.create!(nested_attributes_hash(:best_friend)) - assert_default_attributes(person.best_friend, true) - end - - def test_has_one_create_with_bang_with_admin_role_with_attr_protected_attributes - person = LoosePerson.create!(nested_attributes_hash(:best_friend), :as => :admin) - assert_admin_attributes(person.best_friend, true) - end - - def test_has_one_create_with_bang_with_admin_role_with_attr_accessible_attributes - person = TightPerson.create!(nested_attributes_hash(:best_friend), :as => :admin) - assert_admin_attributes(person.best_friend, true) - end - - def test_has_one_create_with_bang_without_protection - person = LoosePerson.create!(nested_attributes_hash(:best_friend, false, nil), :without_protection => true) - assert_all_attributes(person.best_friend) - end - - def test_belongs_to_create_with_bang_with_attr_protected_attributes - person = LoosePerson.create!(nested_attributes_hash(:best_friend_of)) - assert_default_attributes(person.best_friend_of, true) - end - - def test_belongs_to_create_with_bang_with_attr_accessible_attributes - person = TightPerson.create!(nested_attributes_hash(:best_friend_of)) - assert_default_attributes(person.best_friend_of, true) - end - - def test_belongs_to_create_with_bang_with_admin_role_with_attr_protected_attributes - person = LoosePerson.create!(nested_attributes_hash(:best_friend_of), :as => :admin) - assert_admin_attributes(person.best_friend_of, true) - end - - def test_belongs_to_create_with_bang_with_admin_role_with_attr_accessible_attributes - person = TightPerson.create!(nested_attributes_hash(:best_friend_of), :as => :admin) - assert_admin_attributes(person.best_friend_of, true) - end - - def test_belongs_to_create_with_bang_without_protection - person = LoosePerson.create!(nested_attributes_hash(:best_friend_of, false, nil), :without_protection => true) - assert_all_attributes(person.best_friend_of) - end - - def test_has_many_create_with_bang_with_attr_protected_attributes - person = LoosePerson.create!(nested_attributes_hash(:best_friends, true)) - assert_default_attributes(person.best_friends.first, true) - end - - def test_has_many_create_with_bang_with_attr_accessible_attributes - person = TightPerson.create!(nested_attributes_hash(:best_friends, true)) - assert_default_attributes(person.best_friends.first, true) - end - - def test_has_many_create_with_bang_with_admin_role_with_attr_protected_attributes - person = LoosePerson.create!(nested_attributes_hash(:best_friends, true), :as => :admin) - assert_admin_attributes(person.best_friends.first, true) - end - - def test_has_many_create_with_bang_with_admin_role_with_attr_accessible_attributes - person = TightPerson.create!(nested_attributes_hash(:best_friends, true), :as => :admin) - assert_admin_attributes(person.best_friends.first, true) - end - - def test_has_many_create_with_bang_without_protection - person = LoosePerson.create!(nested_attributes_hash(:best_friends, true, nil), :without_protection => true) - assert_all_attributes(person.best_friends.first) - end - - def test_mass_assignment_options_are_reset_after_exception - person = NestedPerson.create!({ :first_name => 'David', :gender => 'm' }, :as => :admin) - person.create_best_friend!({ :first_name => 'Jeremy', :gender => 'm' }, :as => :admin) - - attributes = { :best_friend_attributes => { :comments => 'rides a sweet bike' } } - assert_raises(RuntimeError) { person.assign_attributes(attributes, :as => :admin) } - assert_equal 'm', person.best_friend.gender - - person.best_friend_attributes = { :gender => 'f' } - assert_equal 'm', person.best_friend.gender - end - - def test_mass_assignment_options_are_nested_correctly - person = NestedPerson.create!({ :first_name => 'David', :gender => 'm' }, :as => :admin) - person.create_best_friend!({ :first_name => 'Jeremy', :gender => 'm' }, :as => :admin) - - attributes = { :best_friend_first_name => 'Josh', :best_friend_attributes => { :gender => 'f' } } - person.assign_attributes(attributes, :as => :admin) - assert_equal 'Josh', person.best_friend.first_name - assert_equal 'f', person.best_friend.gender - end - -end diff --git a/activerecord/test/cases/persistence_test.rb b/activerecord/test/cases/persistence_test.rb index 4ffa4836e0..b5f32a57b2 100644 --- a/activerecord/test/cases/persistence_test.rb +++ b/activerecord/test/cases/persistence_test.rb @@ -608,26 +608,6 @@ class PersistencesTest < ActiveRecord::TestCase assert_equal "The First Topic", topic.title end - def test_update_attributes_as_admin - person = TightPerson.create({ "first_name" => 'Joshua' }) - person.update_attributes({ "first_name" => 'Josh', "gender" => 'm', "comments" => 'from NZ' }, :as => :admin) - person.reload - - assert_equal 'Josh', person.first_name - assert_equal 'm', person.gender - assert_equal 'from NZ', person.comments - end - - def test_update_attributes_without_protection - person = TightPerson.create({ "first_name" => 'Joshua' }) - person.update_attributes({ "first_name" => 'Josh', "gender" => 'm', "comments" => 'from NZ' }, :without_protection => true) - person.reload - - assert_equal 'Josh', person.first_name - assert_equal 'm', person.gender - assert_equal 'from NZ', person.comments - end - def test_update_attributes! Reply.validates_presence_of(:title) reply = Reply.find(2) @@ -649,26 +629,6 @@ class PersistencesTest < ActiveRecord::TestCase Reply.reset_callbacks(:validate) end - def test_update_attributes_with_bang_as_admin - person = TightPerson.create({ "first_name" => 'Joshua' }) - person.update_attributes!({ "first_name" => 'Josh', "gender" => 'm', "comments" => 'from NZ' }, :as => :admin) - person.reload - - assert_equal 'Josh', person.first_name - assert_equal 'm', person.gender - assert_equal 'from NZ', person.comments - end - - def test_update_attributestes_with_bang_without_protection - person = TightPerson.create({ "first_name" => 'Joshua' }) - person.update_attributes!({ "first_name" => 'Josh', "gender" => 'm', "comments" => 'from NZ' }, :without_protection => true) - person.reload - - assert_equal 'Josh', person.first_name - assert_equal 'm', person.gender - assert_equal 'from NZ', person.comments - end - def test_destroyed_returns_boolean developer = Developer.first assert_equal false, developer.destroyed? diff --git a/activerecord/test/cases/validations_test.rb b/activerecord/test/cases/validations_test.rb index b11b330374..3f587d177b 100644 --- a/activerecord/test/cases/validations_test.rb +++ b/activerecord/test/cases/validations_test.rb @@ -7,12 +7,6 @@ require 'models/developer' require 'models/parrot' require 'models/company' -class ProtectedPerson < ActiveRecord::Base - self.table_name = 'people' - attr_accessor :addon - attr_protected :first_name -end - class ValidationsTest < ActiveRecord::TestCase fixtures :topics, :developers diff --git a/activerecord/test/models/bulb.rb b/activerecord/test/models/bulb.rb index 0dc2fdd8ae..e4c0278c0d 100644 --- a/activerecord/test/models/bulb.rb +++ b/activerecord/test/models/bulb.rb @@ -2,8 +2,6 @@ class Bulb < ActiveRecord::Base default_scope { where(:name => 'defaulty') } belongs_to :car - attr_protected :car_id, :frickinawesome - attr_reader :scope_after_initialize, :attributes_after_initialize after_initialize :record_scope_after_initialize @@ -20,12 +18,12 @@ class Bulb < ActiveRecord::Base self[:color] = color.upcase + "!" end - def self.new(attributes = {}, options = {}, &block) + def self.new(attributes = {}, &block) bulb_type = (attributes || {}).delete(:bulb_type) - if options && options[:as] == :admin && bulb_type.present? + if bulb_type.present? bulb_class = "#{bulb_type.to_s.camelize}Bulb".constantize - bulb_class.new(attributes, options, &block) + bulb_class.new(attributes, &block) else super end diff --git a/activerecord/test/models/company.rb b/activerecord/test/models/company.rb index 9bdce6e729..17b17724e8 100644 --- a/activerecord/test/models/company.rb +++ b/activerecord/test/models/company.rb @@ -3,7 +3,6 @@ class AbstractCompany < ActiveRecord::Base end class Company < AbstractCompany - attr_protected :rating self.sequence_name = :companies_nonstd_seq validates_presence_of :name diff --git a/activerecord/test/models/company_in_module.rb b/activerecord/test/models/company_in_module.rb index eb2aedc425..461bb0de09 100644 --- a/activerecord/test/models/company_in_module.rb +++ b/activerecord/test/models/company_in_module.rb @@ -3,7 +3,6 @@ require 'active_support/core_ext/object/with_options' module MyApplication module Business class Company < ActiveRecord::Base - attr_protected :rating end class Firm < Company diff --git a/activerecord/test/models/person.rb b/activerecord/test/models/person.rb index 6e6ff29f77..6ad0cf6987 100644 --- a/activerecord/test/models/person.rb +++ b/activerecord/test/models/person.rb @@ -59,9 +59,6 @@ class LoosePerson < ActiveRecord::Base self.table_name = 'people' self.abstract_class = true - attr_protected :comments, :best_friend_id, :best_friend_of_id - attr_protected :as => :admin - has_one :best_friend, :class_name => 'LoosePerson', :foreign_key => :best_friend_id belongs_to :best_friend_of, :class_name => 'LoosePerson', :foreign_key => :best_friend_of_id has_many :best_friends, :class_name => 'LoosePerson', :foreign_key => :best_friend_id @@ -74,11 +71,6 @@ class LooseDescendant < LoosePerson; end class TightPerson < ActiveRecord::Base self.table_name = 'people' - attr_accessible :first_name, :gender - attr_accessible :first_name, :gender, :comments, :as => :admin - attr_accessible :best_friend_attributes, :best_friend_of_attributes, :best_friends_attributes - attr_accessible :best_friend_attributes, :best_friend_of_attributes, :best_friends_attributes, :as => :admin - has_one :best_friend, :class_name => 'TightPerson', :foreign_key => :best_friend_id belongs_to :best_friend_of, :class_name => 'TightPerson', :foreign_key => :best_friend_of_id has_many :best_friends, :class_name => 'TightPerson', :foreign_key => :best_friend_id @@ -97,10 +89,6 @@ end class NestedPerson < ActiveRecord::Base self.table_name = 'people' - attr_accessible :first_name, :best_friend_first_name, :best_friend_attributes - attr_accessible :first_name, :gender, :comments, :as => :admin - attr_accessible :best_friend_attributes, :best_friend_first_name, :as => :admin - has_one :best_friend, :class_name => 'NestedPerson', :foreign_key => :best_friend_id accepts_nested_attributes_for :best_friend, :update_only => true diff --git a/activerecord/test/models/reader.rb b/activerecord/test/models/reader.rb index f5b6079bd2..f8fb9c573e 100644 --- a/activerecord/test/models/reader.rb +++ b/activerecord/test/models/reader.rb @@ -9,8 +9,6 @@ class SecureReader < ActiveRecord::Base belongs_to :secure_post, :class_name => "Post", :foreign_key => "post_id" belongs_to :secure_person, :inverse_of => :secure_readers, :class_name => "Person", :foreign_key => "person_id" - - attr_accessible nil end class LazyReader < ActiveRecord::Base diff --git a/activerecord/test/models/reply.rb b/activerecord/test/models/reply.rb index 53bc95e5f2..079e325aad 100644 --- a/activerecord/test/models/reply.rb +++ b/activerecord/test/models/reply.rb @@ -6,8 +6,6 @@ class Reply < Topic belongs_to :topic, :foreign_key => "parent_id", :counter_cache => true belongs_to :topic_with_primary_key, :class_name => "Topic", :primary_key => "title", :foreign_key => "parent_title", :counter_cache => "replies_count" has_many :replies, :class_name => "SillyReply", :dependent => :destroy, :foreign_key => "parent_id" - - attr_accessible :title, :author_name, :author_email_address, :written_on, :content, :last_read, :parent_title end class UniqueReply < Reply |