Validating non-model forms - a predicament


#1

Hey folks,
I have encountered what’s beginning to look like a classic problem with
Rails: validating non-model forms. Under what circumstances do you need
to use non-model components in a model-backed form? I need to for credit
card processing: I want to save information like the customer’s phone
number but I don’t want to save their credit card number for security
reasons. Apparently, this situation also comes up when setting up basic
search forms for your website as well
(http://railscasts.com/episodes/37-simple-search-form); unfortunately,
Ryan didn’t address it.

Essentially we’re looking at this situation in the checkout view:

<% form_for(@checkout, :url => “/checkout”) do |f| %>
<%= f.text_field :first_name %>
<%= f.text_field :last_name %>
<%= text_field(:cc, :card) %>
<%= text_field(:cc, :expiration_date) %>
<% end %>

But when the model is saved, the :card and :expiration_date fields are
not validated because they’re not part of the model (they are accessed
using params[:cc][:card] and params[:cc][:expiration_date]).

All this code works - I just need to validate my credit card stuff! How
do I do this? I know I’m not the first guy to run into this problem.

Thank you for any suggestions!


#2

Patrick L. wrote:

But when the model is saved, the :card and :expiration_date fields are
not validated because they’re not part of the model (they are accessed
using params[:cc][:card] and params[:cc][:expiration_date]).
Add them as attributes to the model and then create validation rules as
normal -

attr_accessible :expiration_date

validates_presence_of :expiration_date


#3

Patrick L. wrote:

Hey folks,
I have encountered what’s beginning to look like a classic problem with
Rails: validating non-model forms. Under what circumstances do you need
to use non-model components in a model-backed form? I need to for credit
card processing: I want to save information like the customer’s phone
number but I don’t want to save their credit card number for security
reasons.

Add attr_accessor :cc_number to your model, then validate it.

Then call .save(false) when saving the model object internally, to
bypass all
your validations.

Everything will work as if you had a column with that name, except
find_by_cc_number, or loading the number (natch).

Also f.text_field will work, so Card.new(params[:card]) will work.


Phlip


#4

Andrew P. wrote:

Patrick L. wrote:

But when the model is saved, the :card and :expiration_date fields are
not validated because they’re not part of the model (they are accessed
using params[:cc][:card] and params[:cc][:expiration_date]).
Add them as attributes to the model and then create validation rules as
normal -

attr_accessible :expiration_date

validates_presence_of :expiration_date

Thank you both. I implemented Andrew’s solution, and it seems to work.
Thing is, it doesn’t wrap the expiration_date input field in the error
div (in other words, it doesn’t turn red).

How should I fix this?


#5

I second this.

I have a User model where a user signs up and enters basic
information, and then later enters more information to access advanced
features.

If I put validates_presence_of in the model for the fields in the
second form, Rails won’t let me create the user in the first form
without those fields.

How can I get around this?

On Jan 2, 3:08 pm, “Patrick L.” removed_email_address@domain.invalid