Question

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?

Était-ce utile?

La solution

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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top