Topic: Validate without saving?

Is there a way to check for data validation without saving it to the database?

My situation is that I have a controller that saves data from a form to multiple tables (e.g., first text field to first table, second text field to second table).

If the save to the first table fails validation (e.g., blank input), I return a flash notice with the error.

But I'd like the flash notice to also include any errors that may be associated with the data for the second table (e.g., if second text field is also blank).

Right now my solution is to do a save and then a destroy for the data from the second text field so that any errors will be generated. But that seems like an unnecessary db action.

I found a run_validations! method on the Rails api, but it's not well documented and I just get a protected method error.

Any ideas?

Thanks

Re: Validate without saving?

Your model have a method valid? which will tell you if the record is valid. After that, errors attribute will be populated.

Re: Validate without saving?

flaggy's answer using the valid? method on ActiveRecord class is at first glance a good solution BUT not in your case.
you ABSOLUTELY SHOULD be using database transactions

http://api.rubyonrails.org/classes/Acti … thods.html

Using transactions will not only deal with validations but absolutely anything else that could go wrong

What you want and what you need are too often not the same thing!
When your head is hurting from trying to solve a problem, stop standing on it. When you are the right way up you will see the problem differently and you just might find the solution.
(Quote by me 15th July 2009)

Re: Validate without saving?

Thanks for the help. I actually tried the valid? method too, but it didn't work.

I'll look into using a transaction block as you suggested James.

Thanks again.

Last edited by Brian71 (2012-04-25 15:09:32)

Re: Validate without saving?

jamesw,

I did as you recommended and changed my controller to use transaction. Everything works as expected, except that the form errors are not returning and being displayed as before. How can I revise it so that the validation error text gets returned?

Here is my current controller code:

  def create
    begin
      Widget.transaction do
        @color = current_user.colors.new(params[:color])
        @color.save!
        @shape = current_user.shapes.new(params[:shape])
        @shape.save!
        @widget = current_user.widgets.new(shape_id: @shape.id, color_id: @color.id)
        @widget.save!
      end
    rescue ActiveRecord::RecordInvalid => invalid
      flash[:notice] = "Must enter color and shape." # this gets returned right now; I'd rather return the actual error text
      redirect_to new_widget_path
    end
    
    if !@widget.nil?
      flash[:success] = "New widget has been created."
      redirect_to widgets_path
    end
  end

Re: Validate without saving?

I would move the transaction handling into the model then use the add to base error handling with your own custom error messages then let the form do it's stuff in the normal way
something like
in your controller instead of  @widget.save create yourself a new method

@widget.save_widget(@color, @shape)

then have the save_widget method handle the transaction and adding of errors

I have to say that the code you have shown smacks of needing a multi model form with accepts nested attributes which would handle all this for you.

What you want and what you need are too often not the same thing!
When your head is hurting from trying to solve a problem, stop standing on it. When you are the right way up you will see the problem differently and you just might find the solution.
(Quote by me 15th July 2009)

Re: Validate without saving?

jamesw wrote:

I have to say that the code you have shown smacks of needing a multi model form with accepts nested attributes which would handle all this for you.

I looked into this, and concluded that it would not work in this situation. What's happening in the form is that the user is entering a color and a shape, and the new color and shape are entered into respective tables. A new widget is also created in a widget table as you see in the controller. Each color and shape has many widgets (the user can use each color/shape for other widgets). Thus, I cannot put accepts_nested_attributes_for :color, :shape in the widget model because of the many-to-one relationships.

Also, further investigation, I found that I can change my flash to something like flash[:notice] = @object.errors.full_messages. However, I found out that the transaction block seems to be stopping at the first failed save!, rather than attempting all of them. As a result, if there is a validation error for shape and color, the shape validation error never gets generated, so I'm back to the same problem I had before that led me to do the save and destroy to get all errors.

So it seems at this point that my options are to either revert back to the save/destroy to generate any further errors, or to just generate my own kind of general error message...

Re: Validate without saving?

There are solutions to both your issues, depends what way you wish to go with it but I would definitely suggest a multi model form with accepts nested attributes. It certainly is possible to set this up on a belongs to or a has many, or even a has_one if you so desire it, which is totally logical when you understand that accepts nested attributes is all about taking a params hash and dealing with attributes that are nested inside it's own params element.

What you want and what you need are too often not the same thing!
When your head is hurting from trying to solve a problem, stop standing on it. When you are the right way up you will see the problem differently and you just might find the solution.
(Quote by me 15th July 2009)

Re: Validate without saving?

Okay, well then clearly I need to take a second look at accepts_nested_attributes. The only examples I saw in the api were for one-to-many and one-to-one relationships, so I concluded that accepts_nested_attributes was limited to those situations, and wouldn't work in a many-to-many situation like I have between shapes and colors.

Re: Validate without saving?

Let me know if you get stuck with this this

What you want and what you need are too often not the same thing!
When your head is hurting from trying to solve a problem, stop standing on it. When you are the right way up you will see the problem differently and you just might find the solution.
(Quote by me 15th July 2009)

Re: Validate without saving?

Thanks. Fortunately I have a working form. Just looking to do some refactoring. For now I have bigger issues to address, but I'll return to this at some point.