Permalink
Browse files

Merge pull request #357 from joshk/assign_attributes.

Assign protected attributes with create/new and control the role.
  • Loading branch information...
dhh committed May 1, 2011
2 parents 32ef3cc + 86d7ed3 commit a8861c8f5b57ea653e1518325a686fd97995aef4
@@ -93,20 +93,20 @@ def last(*args)
first_or_last(:last, *args)
end
- def build(attributes = {}, &block)
- build_or_create(attributes, :build, &block)
+ def build(attributes = {}, options = {}, &block)
+ build_or_create(:build, attributes, options, &block)
end
- def create(attributes = {}, &block)
+ def create(attributes = {}, options = {}, &block)
unless owner.persisted?
raise ActiveRecord::RecordNotSaved, "You cannot call create unless the parent is saved"
end
- build_or_create(attributes, :create, &block)
+ build_or_create(:create, attributes, options, &block)
end
- def create!(attrs = {}, &block)
- record = create(attrs, &block)
+ def create!(attrs = {}, options = {}, &block)
+ record = create(attrs, options, &block)
Array.wrap(record).each(&:save!)
record
end
@@ -403,9 +403,9 @@ def merge_target_lists(loaded, existing)
end + existing
end
- def build_or_create(attributes, method)
+ def build_or_create(method, attributes, options)
records = Array.wrap(attributes).map do |attrs|
- record = build_record(attrs)
+ record = build_record(attrs, options)
add_to_target(record) do
yield(record) if block_given?
@@ -421,8 +421,8 @@ def insert_record(record, validate = true)
raise NotImplementedError
end
- def build_record(attributes)
- reflection.build_association(scoped.scope_for_create.merge(attributes))
+ def build_record(attributes, options)
+ reflection.build_association(scoped.scope_for_create.merge(attributes), options)
end
def delete_or_destroy(records, method)
@@ -60,10 +60,10 @@ def through_record(record)
through_record
end
- def build_record(attributes)
+ def build_record(attributes, options = {})
ensure_not_nested
- record = super(attributes)
+ record = super(attributes, options)
inverse = source_reflection.inverse_of
if inverse
@@ -17,16 +17,16 @@ def writer(record)
replace(record)
end
- def create(attributes = {})
- new_record(:create, attributes)
+ def create(attributes = {}, options = {})
+ new_record(:create, attributes, options)
end
- def create!(attributes = {})
- build(attributes).tap { |record| record.save! }
+ def create!(attributes = {}, options = {})
+ build(attributes, options).tap { |record| record.save! }
end
- def build(attributes = {})
- new_record(:build, attributes)
+ def build(attributes = {}, options = {})
+ new_record(:build, attributes, options)
end
private
@@ -44,9 +44,9 @@ def set_new_record(record)
replace(record)
end
- def new_record(method, attributes)
+ def new_record(method, attributes, options)
attributes = scoped.scope_for_create.merge(attributes || {})
- record = reflection.send("#{method}_association", attributes)
+ record = reflection.send("#{method}_association", attributes, options)
set_new_record(record)
record
end
@@ -475,10 +475,19 @@ def find_by_sql(sql, binds = [])
# The +attributes+ parameter can be either be a Hash or an Array of Hashes. These Hashes describe the
# attributes on the objects that are to be created.
#
+ # +create+ respects mass-assignment security and accepts either +:as+ or +:without_protection+ options
+ # in the +options+ parameter.
+ #
# ==== Examples
# # Create a single new object
# User.create(:first_name => 'Jamie')
#
+ # # Create a single new object using the :admin mass-assignment security scope
+ # User.create({ :first_name => 'Jamie', :is_admin => true }, :as => :admin)
+ #
+ # # Create a single new object bypassing mass-assignment security
+ # User.create({ :first_name => 'Jamie', :is_admin => true }, :without_protection => true)
+ #
# # Create an Array of new objects
# User.create([{ :first_name => 'Jamie' }, { :first_name => 'Jeremy' }])
#
@@ -491,11 +500,11 @@ def find_by_sql(sql, binds = [])
# User.create([{ :first_name => 'Jamie' }, { :first_name => 'Jeremy' }]) do |u|
# u.is_admin = false
# end
- def create(attributes = nil, &block)
+ def create(attributes = nil, options = {}, &block)
if attributes.is_a?(Array)
- attributes.collect { |attr| create(attr, &block) }
+ attributes.collect { |attr| create(attr, options, &block) }
else
- object = new(attributes)
+ object = new(attributes, options)
yield(object) if block_given?
object.save
object
@@ -1465,7 +1474,20 @@ def encode_quoted_value(value) #:nodoc:
# attributes but not yet saved (pass a hash with key names matching the associated table column names).
# In both instances, valid attribute keys are determined by the column names of the associated table --
# hence you can't have attributes that aren't part of the table columns.
- def initialize(attributes = nil)
+ #
+ # +initialize+ respects mass-assignment security and accepts either +:as+ or +:without_protection+ options
+ # in the +options+ parameter.
+ #
+ # ==== Examples
+ # # Instantiates a single new object
+ # User.new(:first_name => 'Jamie')
+ #
+ # # Instantiates a single new object using the :admin mass-assignment security scope
+ # User.new({ :first_name => 'Jamie', :is_admin => true }, :as => :admin)
+ #
+ # # 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 = {})
@attributes = attributes_from_column_definition
@association_cache = {}
@aggregation_cache = {}
@@ -1481,7 +1503,8 @@ def initialize(attributes = nil)
set_serialized_attributes
populate_with_current_scope_attributes
- self.attributes = attributes unless attributes.nil?
+
+ assign_attributes(attributes, options) if attributes
result = yield self if block_given?
run_callbacks :initialize
Oops, something went wrong.

2 comments on commit a8861c8

@smartinez87

This comment has been minimized.

Show comment Hide comment
@smartinez87

smartinez87 May 2, 2011

Contributor

Please remember to update the guides when needed.
I added some docs here https://github.com/lifo/docrails/commit/9fa080e703362876b5afe9a7627bf3ffb6fa131e, feel free to complete them.

Cheers

Contributor

smartinez87 replied May 2, 2011

Please remember to update the guides when needed.
I added some docs here https://github.com/lifo/docrails/commit/9fa080e703362876b5afe9a7627bf3ffb6fa131e, feel free to complete them.

Cheers

@joshk

This comment has been minimized.

Show comment Hide comment
@joshk

joshk May 2, 2011

Contributor

Thank for updating the guides, I was going to do this via the docrails repo today or tomorrow as it was midnight when I finished the work.

Cheers

Contributor

joshk replied May 2, 2011

Thank for updating the guides, I was going to do this via the docrails repo today or tomorrow as it was midnight when I finished the work.

Cheers

Please sign in to comment.