Validations doesnt work with activemodel?

Hi,

I have a form with 2 attributes/fields. As im not storing them in a
database, i have used activemodel::validations for validations in my
model class.

In the views file i have 2 associated text fields (part of a form) with
a submit button. I have used validates_presence_of for the 2 attributes,
but i dont see an error even when i click the submit button with empty
fields.
How do i validate stuff in the form?

Well, there could be several things going on. So, lets go step by step.

  1. Open an irb console (if you are using rails, type “rails console”)
  2. Try to create a new model and call valid? on it. What does it return?

Play around in the console so you can learn if your model is validating
as
expected (better yet, write some tests). If it’s validating correctly, I
would then move to your controller and see that the code there is
behaving
as expected. Once you do that, make sure that view is somehow displaying
the errors.

If you need more help with any step, please provide relevant code, so
someone can better help you.

Hi,

Thanks for the suggestions. I have now included the code to display the
error messages. Here is the code for my MVC

model
class Record
include ActiveModel::Validations
validates: :ipaddress, :name, :presence => true
end

View

<%= form_for :Record, :url => {:action => 'submit'} do |f| %>
  <%= f.error_messages %>
  <div class="field">
    <%= f.label :ipaddress %><br />
    <%= f.text_field :ipaddress  %>
  </div>
  <div class="field">
    <%= f.label :name %><br />
    <%= f.text_field :name  %>
  </div>
  <div class="actions">
    <%= f.submit "Submit"%>
  </div>
<% end %>

Controller
Somehow this gets routed to action “create” instead of “submit” when the
submit button is called. Not sure why it is

def create -> same for def submit too

respond_to do |format|
if PARAM matches so and so
DEPENDING on params this gets routed to different page
else
format.html { redirect_to records_url}
format.json { head :no_content }
end
end

end

Should i write my controller differently to handle the errors?

validates*:* ← is only validates, without punctuation.

with colon you are creating a hash, not running the macro.

2012/6/26 cyber c. [email protected]

   <%= f.text_field :name  %>

def create → same for def submit too
end
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk?hl=en.


Fernando A.

I’m sorry, I dont know how it ended up in the post , but my code doesnt
have the extra colon.

Its actually this
model
class Record
include ActiveModel::Validations
validates :ipaddress, :name, :presence => true
end

Hi Walter,

Thanks for your comments.

def create -> same for def submit too

respond_to do |format|
if PARAM matches so and so
DEPENDING on params this gets routed to different page

at any point here do you instantiate a new instance of your model,
assign the params to it, and try to save it? Until you try to save, your
validations won’t fire.

I didn’t instantiate a new instance of my model. When i try to instantiate
@record = Record.new(params[:record])
fires an error "wrong number of arguments ( 1 for 0) "
I have removed the default new definition, as i thought i dont need
it(im not storing the info in a DB, but processing the form data)

else
  format.html { redirect_to records_url}
  format.json { head :no_content }

end
end

end

Should i write my controller differently to handle the errors?

You might want to look at a vanilla scaffold controller and see how it’s
done canonically before you reinvent the wheel. There are separate
create and update methods for a reason.

On Jun 26, 2012, at 4:23 PM, cyber c. wrote:

View

<%= form_for :Record, :url => {:action => ‘submit’} do |f| %>

Leave off the {:action} part here, I’ll explain why in a moment

   <%= f.submit "Submit"%>
 </div>

<% end %>

Controller
Somehow this gets routed to action “create” instead of “submit” when the
submit button is called. Not sure why it is

If your routes look like

resources :yourmodel

Then you are using REST URLs, and a POST from your form will always go
to #create, and a PUT (which you will automatically get from the
form_for if your resource has an id) will always go to #update. If you
want to use the submit method in place of create, you can probably do
that in your routes file, but why?

def create -> same for def submit too

respond_to do |format|
if PARAM matches so and so
DEPENDING on params this gets routed to different page

at any point here do you instantiate a new instance of your model,
assign the params to it, and try to save it? Until you try to save, your
validations won’t fire.

else
  format.html { redirect_to records_url}
  format.json { head :no_content }

end
end

end

Should i write my controller differently to handle the errors?

You might want to look at a vanilla scaffold controller and see how it’s
done canonically before you reinvent the wheel. There are separate
create and update methods for a reason.

Walter

On Jun 26, 2012, at 5:00 PM, cyber c. wrote:

at any point here do you instantiate a new instance of your model,
assign the params to it, and try to save it? Until you try to save, your
validations won’t fire.

I didn’t instantiate a new instance of my model. When i try to instantiate
@record = Record.new(params[:record])
fires an error "wrong number of arguments ( 1 for 0) "
I have removed the default new definition, as i thought i dont need
it(im not storing the info in a DB, but processing the form data)

What version of Rails? I see a Railscast here from 2010 that has that
very same code, and no error. But it also has an initialize method
hand-written into the model:

def initialize(attributes = {})
attributes.each do |name, value|
send(“#{name}=”, value)
end
end

You might need something like that to “persist” the data long enough for
your controller to do something with it.

Walter

On Jun 26, 2012, at 5:45 PM, cyber c. wrote:

include ActiveModel::Validations
def persisted?
<%= f.text_field :ipaddress %>
Controller
else
format.html { redirect_to records_url}
format.json { head :no_content }
end
end

end

I dont see any errors but i see a refreshed page of records_url

Then I would try writing just one validation, and see if you can make
that work. And by the way, look, that colon at the end of validates has
crept back in there. Is that a paste from your model, or your previous
e-mail?

Try using

validates_presence_of :ipaddress

and see what happens.

I’ve never tried using ActiveModel before, so I’m guessing here.

Walter

Hi,

I’m using rails 3.2.4.

I had referred to the activemodel episode from the rail casts and yes i
included the initialize and persisted methods as specified. Still i dont
see errors when i click the submit button with empty values

model
class Record
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
attr_accessor :ipaddress, :name
validates: :ipaddress, :name, :presence => true
def initialize(attributes = {})
attributes.each do |name, value|
send("#{name}=", value)
end
end

def persisted?
return false
end
end

View

<%= form_for :Record  do |f| %>
  <%= f.error_messages %>
  <div class="field">
    <%= f.label :ipaddress %><br />
    <%= f.text_field :ipaddress  %>
  </div>
  <div class="field">
    <%= f.label :name %><br />
    <%= f.text_field :name  %>
  </div>
  <div class="actions">
    <%= f.submit "Submit"%>
  </div>
<% end %>

Controller

def new
@record = Record.new
end

def create
@record = Record.new(params[:record])
respond_to do |format|
if @record.valid?
DEPENDING on params this gets routed to different page
else
format.html { redirect_to records_url}
format.json { head :no_content }
end
end

end

I dont see any errors but i see a refreshed page of records_url

On Jun 26, 2012, at 5:59 PM, cyber c. wrote:

Hi Walter,

Yah the “:” came from copy pasting my earlier comment.
The result is the same(no errors) with one attribute or using
validates_presense_of(tried with other validate* options too). I was
wondering if that problem was to do with the view?
Anyother way of displaying the errors?

Try running this in console, and see if you have any errors there. And
in your view, are you using some variant of this:

<% flash.each do |name, msg| %>
<%= content_tag :div, msg, :id => "flash_#{name}" %>
<% end %>

Walter

Hi Walter,

The validate* methods works fine on the console. The function
object.valid? returns false if any of the validate method fails. For
that case object.valid? returns false even in the controller function,
but when i redirect to the same url, it doesn’t show any errors from the
code

<%= f.error_messages %>

In my view im not using any sort of this code

<% flash.each do |name, msg| %>
<%= content_tag :div, msg, :id => “flash_#{name}” %>
<% end %>

Do i need it?

Hi Walter,

Yah the “:” came from copy pasting my earlier comment.
The result is the same(no errors) with one attribute or using
validates_presense_of(tried with other validate* options too). I was
wondering if that problem was to do with the view?
Anyother way of displaying the errors?

Hi Walter,

Thanks for the detailed explanation. I am redirecting to different pages
in both the cases(valid and not valid case). Now that i am rendering a
new page incase of a validate failure and i see the errors. Thank you
very much :slight_smile:

On Jun 26, 2012, at 6:23 PM, cyber c. wrote:

Hi Walter,

The validate* methods works fine on the console. The function
object.valid? returns false if any of the validate method fails. For
that case object.valid? returns false even in the controller function,
but when i redirect to the same url, it doesn’t show any errors from the
code

The errors are set in the event loop of reading the form submission and
showing the results, but when you redirect, you start a new loop, and so
unless you disrupt the cycle you seem to have set for yourself, you’re
never going to see those errors, because the errors – and I suspect the
object – does not exist in the context of the page you redirected to.

In a normal scaffold controller, you will see this pattern:

def new
@my_model = MyModel.new(params[:my_model])
end

def create
@my_model = MyModel.new(params[:my_model])
if @my_model.save
redirect_to some_route(@my_model), :notice => ‘Yay!’
else
render :action => ‘new’
end
end

If both sides of your test for save are redirects, then you have to set
the :warn or :error flash to your errors, because they will not persist
after the redirect. Especially because you’re using Active Model, but
particularly because you’re in a #create method – each time that runs,
the model instance is created fresh from the supplied parameters, and it
forgets all about the botched save.

It’s what I use, it may be out of date, since I am using Rails 3.0 for
this app that I copied it from. I believe that some of this was
streamlined in 3.2. But I am also sure that you have to use /some/ sort
of code to indicate where you want your errors to appear on your
application layout file.

Walter