Reputation: 18855
I'm relatively new to Ruby on Rails and I feel like I am doing something wrong here. I'm setting up a payment model and can't figure out how to do the accessible attributes stuff.
My cash_transaction model has:
attr_accessible :billing_address_line_one, :billing_address_line_2, :billing_city, :billing_country, :billing_post_code, :payee_first_name, :payee_last_name, :card_expiry, :card_type
attr_accessor :card_number, :card_verification
Ok, so I want to submit the form and validate and maybe save to a database in future if the payment goes through.
If I leave :card_number, :card_verification
in the attr_accessible
, Rails gives the error:
*unknown attribute card_number*
Which is fair enough because I don't want to save that in my DB.
When I try:
@cash_transaction = current_user.cash_transactions.build(params[:cash_transaction])
I get a mass assignment security error when those parameters are not in attr_accessible
.
I have got around both errors with:
@cash_transaction = current_user.cash_transactions.build(params[:cash_transaction].except(:card_number, :card_verification))
@cash_transaction.card_number = params[:cash_transaction][:card_number]
@cash_transaction.card_verification = params[:cash_transaction][:card_verification]
But that's just the same as building with those parameters included in the hash anyway so I'm cheating it?
What do?
Upvotes: 1
Views: 1616
Reputation: 10142
Rails is quite careful against several kinds of injections. And this can be confusing.
attr_accessible
is a Rails thing, similar to the Ruby Module method attr_accessor
, yet different. attr_accessible
does allow access to the specified arguments, much in the same way as attr_accessor
(the object gets "getters" and "setters"). attr_accessible
does also more work to protect against injections.
When a parameter dictionary is passed to create an object, each parameter is checked against the whitelist defined by attr_accessible
. If the parameter belongs to the list, it gets assigned and persisted. If not, the mass-assignment security error is raised to prevent any unwanted assignment---a potential security hole. attr_accessor
does not do all that, as it does not make sense in plain Ruby.
Now card_number
and card_verification
should not be persisted according to your specifications. They belong to the logic related to cash transaction only, so choosing instance attributes seems a good choice at this point. As plain attributes of CashTransaction instances, they need be treated as such, with plain Ruby access methods. The short answer to all that is @gylaz'.
Wordy feedbacks above. For concrete examples, the ActiveModel's code and related comments are very informative.
Upvotes: 2