Pergunta

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?

Foi útil?

Solução

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top