I'm using Rails 2.3.4/Ruby 1.9.1 for my application. In the view I have this to show error messages:
<%= content_tag('div', flash[:notice], :class => 'flash notice') if flash[:notice] %>
it works fine if I assign it manually from the controller such as:
flash[:notice] = "User Name can only contain letters, number - or _"
But for the automatic validation in the model such as:
validates_uniqueness_of :user_name
the error messages don't show! although the form doesn't submit which what should happen but I don't see the error messages.
Any ideas?
Thanks,
Tam
Unless this has changed very recently in rails, flash[:notice] is never populated by model validations. To display errors from a validation in the view, you would use the error_messages_for method.
Related
I want to have a form that anyone can fill out, but must be logged in to submit it - if not, put the process on hold until they do.
My thought process is if someone comes across the form, it checks if they are logged in, if not the user can still fill it out, but instead prompted to log in or sign up as opposed to "Submit". If they click on either link (log in/sign up) I want it to save the form data, most likely to the session, have them log in/sign up, and then have the computer check to see if there is a saved form, and if so display a confirmation like screen, where the newly registered user can accept it.
I've posted come code below that I thought would work, but it isn't - and I was thinking that knowing rails, theres probably some convention out the to do this much faster and easier!
And I don't believe the way that I am passing the form data around is correct, so if anyone can correct me there that would be great!
View
<%= form_for :comment, :url => {:action => 'create'} %>
form fields here
<% if current_user %>
<%= f.submit "Submit" %>
<% else %>
<%= link_to "Log In", save_to_session_and_log_in_path(:comment => :comment) %> or
<%= link_to "Sign Up", save_to_session_and_sign_up_path(:comment => :comment) %>
<% end %>
Controller
def save_to_session_and_log_in_path
session[:temp_comment] = Comment.new(params[:comment])
redirect_to log_in_path
end
def save_to_session_and_sign_up_path
session[:temp_comment] = Comment.new(params[:comment])
redirect_to sign_up_path
end
User* Controller
def create
#Normal create action, under the redirect:
if session[:temp_comment]
redirect_to confirm_comment
else
redirect_to users_home_page
end
end
The error I am receiving is:
ActiveRecord::RecordNotFound in CommentsController#show
Couldn't find Comment with id=save_to_session_and_log_in
Rails.root: scrubbed
Application Trace | Framework Trace | Full Trace
app/controllers/comments_controller.rb:87:in `show'
Request
Parameters:
{"comment"=>"comment"
"id"=>"save_to_session_and_log_in"}
I've tried tweaking it every which way but it still keeps getting me here so I am unable to test if any of my code is working
What are your CommentsController#create and #show action? About your error, could you paste the rake routes result for the save_to_session_and_log_in_path and the save_to_session_and_sign_up_path methods? Since you don't have an id at that moment, you should set them as collection routes.
--
The way I'd do it, though, is submitting the form to different controllers that will handle each scenario. That way, your CommentsController will be for logged in users and you can have a TemporaryCommentsController that will take care of comments made by guests.
--
Also, depending on the comment's field, I don't know if it's a great idea to store them in the session. You could probably store a tmp_comment_id in the session and recover that from the DB. Also, delete all records with a cron-job. (This is a problem only when "the comment is big and 'hard' to serialize" though).
My error messages are not showing automatically, so I decided to use flash as a workaround. This is what I'm doing
Controller:
flash[:notice] = #post.errors.full_messages
View:
<%= flash[:notice] %>
Then, I get this ugly error message on my view.
["Content can't be blank", "Content is too short (minimum is 10 characters)"]
But at least, the user successfully gets the error message. Now I need to customize the error message and make it look a little bit more pretty. I guess I could parse each error sentence into some local variables and show them (is there a more sophisticated way?). However, I don't know how to customize the error message. For example, "Content can't be blank" should be changed to "You left the content blank". Where can I fix this?
What happens is that when #post contains some validation errors doing #post.errors.full_messages returns an array of errors that happened during validation.
To display them nicely you might want to do something like
<%- flash[:notice].each do |error| %>
<%= error %>
<% end %>
EDIT
Whoops I misread the question.
These errors are validation errors in your model where you have the validations like
validates you can pass custom messages like so
validates :content, :presence => { :message => "You left the content blank" }
Update: check this link out for the options you have
http://apidock.com/rails/ActiveModel/Validations/ClassMethods/validates
I have a simple user registration page in my rails app that has two fields: name and email. I have client side validation on each text field and server side for the submit button (This is the recommended way right?)
My problem is that I don't know how to repopulate the two fields with the previous values if they submitted it with a mistake. I have tried a few days such as:
format.html { redirect_to :back, :notice => 'Uh Oh! Something went wrong!', :name => #user.name } <-- create action
and
if(params.has_key?(:name))
#user.name = params[:name]
end <-- new action
Any help appreciated!
Yes this is the recommended way to put validation on both client and server side.
Regarding retaining the fields is concerned on redirect the # variables use to be get destroyed only flash persist up to one redirect.
Either u can pass your validations message in flash which is bad way the good one is to render the form page (good to be make form as seperate partial) and the # object will be automaticaly map the relevant fields like name, email.
Hope this will help you.
thanks
Add this in your form: <%= f.error_messages %> and don't redirect because you will lose the posted data.
You could do something like this in your action:
if #posted_object.save
redirect_to ...
else
render 'your view'
end
It turns out that flash can do what I wanted, but I was using it incorrectly.
I had to use:
flash[:name] = "name"
before the redirect instead of redirect_to :back, :name => "name"
and in the html
<% if flash[:name] %> instead of <% if params[:name] %> or <% name %>
I'm making good progress with my first Rails app (using Rails 3). The MVC interaction is all going fine, but I'm having difficulty with a form that doesn't relate directly to a model.
I'm using form_tag, and in the case of success, everything behaves fine. However, the handling of errors is somewhat unfriendly. The actual error message is stored in the flash and displayed fine by layouts/application.html, but I'd really like it if the form could remember the contents that the user had just filled in. But it doesn't: all the fields reset to their default values.
I love the way that forms for RESTful actions on objects automatically remember their submitted values, and get highlighted in red if there are errors. I'm fine without the red highlight, but I'd really like it if I could make the form's fields keep the submitted values.
Can anyone advise how to do this?
Excerpts from the relevant files:
views/cardsets/import.html.erb:
<%= form_tag :action => :import_data, :id => #cardset do %>
...
<%= text_field_tag "separator", "", :maxlength => 1 %>
...
<%= text_field_tag "formatting_line" %>
...etc (more fields)
controllers/cardsets_controller.rb:
# POST /cardsets/1/import_data
def import_data
success, message = #cardset.import_data(params, current_user)
if success
redirect_to(#cardset, :notice => message)
else
flash.now[:error] = message
render :import
end
end
The second arg to text_field_tag is the value to fill in the field with. Try something like this:
<%= text_field_tag "separator", params[:separator], :maxlength => 1 %>
If your field has a default, you will want to set it from the "show" action for the form:
# GET
def show_form
params[:key] = 'default'
end
# POST
def validate_form_and_act
# Don't set it here to reuse what the user passed.
end
or directly on the template (less good because uses an || every time and adds more controller data to view):
<%= text_field_tag 'name', params[:key] || 'default' %>
I have two forms in one view updating the User Profile. One Form is to Update my name etc. and one is to change my password.
Profile Form:
- form_for #user, :url => account_path do |f|
= f.error_messages
...form fields here...
Password Form:
- form_for #user, :url => account_path do |pf|
= pf.error_messages
...password fields here...
As you can see they both point to the same update action in the users controller. If I type in a invalid password both error_messages show me the same error message.
How can I output separate error messages per form?
You need to use error_message_on to output the error message for one specific attribute. Keep in mind, that its output is not very meaningful by itself, as it lacks the attribute name and the header message that error_messages/error_messages_for include by default. You can use :prepend_text and :append_text to customize the messages (look at the API docs for more info).
Note that for the password part, all you have to do is call error_message_on :password, but for the rest of the form fields, you have to call error_message_on once for every attribute, apart from :password. You could write your own helper to avoid that.