I have built a dashboard of sorts with multiple forms from different models in the same view. My goal is to have all of the error messages from each form render on the dashboard. The dashboard is part of the PagesController and the forms belong to other controllers.
All of the forms currently work great. However, when errors occur they render in other views not the dashboard. When I attempt to "render" the errors on the dashboard page I get errors that the other form's models are missing.
Example of "render" that renders outside of the dashboard view.
class NotesController < ApplicationController
def create
#note = Note.new(params[:note])
if #note.save
flash[:notice] = "Note Created!"
redirect_to dashboard_path
else
flash[:alert] = "Note failed"
render :action => "new"
end
end
end
The example I would like to work, which renders the errors inside the dashboard view.
class NotesController < ApplicationController
def create
#note = Note.new(params[:note])
if #note.save
flash[:notice] = "Note Created!"
redirect_to dashboard_path
else
flash[:alert] = "Note failed"
render 'pages/home'
end
end
end
To reiterate, I am trying to make it so all errors will show up on the dashboard page with out breaking the site. Let me know if you would like more information.
You can accomplished this by just setting errors to an instance variable that all the forms use:
class NotesController < ApplicationController
def create
#note = Note.new(params[:note])
if #note.save
flash[:notice] = "Note Created!"
redirect_to dashboard_path
else
#errors = #note.errors
load_home
render 'pages/home'
end
end
private
def load_home
#instances = Model.all
#instance_1 = Model.find(1)
end
end
All your controllers would set #errors = #model.errors then in your view you just have something like this instead of relying on f.error_messages or whatever you have in your form:
(in haml)
- unless #errors.nil?
#errorExplanation
%h2 Please correct these errors
%ul
- for e in #errors
%li= e[1]
Related
Hey all so in my code I am just redirecting back to the index of all the topics and theoretically I would like to redirect back to the page.
this is my controller for this page, right now I am just using topics_path as a stand in.
class LikesController < ApplicationController
def index
end
def create
#bookmark = Bookmark.find(params[:bookmark_id])
like = current_user.likes.build(bookmark: #bookmark)
if like.save
flash[:notice] = "Successfully liked bookmark."
else
flash.now[:alert] = 'Error in liking bookmark. Please try again.'
end
redirect_to topics_path
end
def destroy
#bookmark = Bookmark.find(params[:bookmark_id])
like = current_user.likes.find(params[:id])
# Get the bookmark from the params
# Find the current user's like with the ID in the params
if like.destroy
flash[:notice] = "Successfully unliked bookmark."
else
flash.now[:alert] = 'Error in unliking bookmark. Please try again.'
end
redirect_to topics_path
end
end
this is the line from rake routes that I was to redirect_to
bookmarks_show GET /bookmarks/show(.:format) bookmarks#show
If you wish to redirect back to a specific topic's page... then you'll need to pass the topic_id through as a param so you can use it in the redirection.
Add it into the form/link you're using eg:
(note: totally making this up, obviously your code will be different)
<% form_for #like do |f| %>
<%= f.hidden_field :topic_id, #topic.id %>
Then in your create action, you just redirect using that eg:
def create
#bookmark = Bookmark.find(params[:bookmark_id])
like = current_user.likes.build(bookmark: #bookmark)
if like.save
flash[:notice] = "Successfully liked bookmark."
else
flash.now[:alert] = 'Error in liking bookmark. Please try again.'
end
redirect_to topic_path(:id => params[:topic_id])
end
Note: if you want to use some other page (eg the bookmark page) then use that instead... this is a "general howto" not a "use this code exactly as you see it here" :)
I've been trying to fix this for a while but haven't gotten anywhere yet. Would appreciate if someone could let me know how how this can be done, or if there is any way i can use the render method to do this instead (currently preserves errors but redirects to wrong path as mentioned below...)
I have a custom route for form which I am trying to redirect back when there are validation errors:
get "clubs/sign_up/:plan_id", to: "clubs#new", as: :new_membership
below is what I have so far in my controller along along with some comments regarding other steps I have tried
clubs_controller.rb
def create
#membership = Membership.new(membership_params)
if #membership.save
redirect_to root_path
else
flash[:error] = "Please check form errors:"
redirect_to new_membership_path(session[:membership_plan_id]) #errors lost
# render action: 'new', plan_id: 'silver' # <<<Preserves errors but breaks path, renders: localhost:3000/clubs instead of .../clubs/sign_up/:plan_id
# session[:membership_errors] = #membership.errors #<<< Doesn't wotk either, getting a cookie overflow error when trying to pass errors to #new
return
end
end
def new
session[:membership_plan_id] = params[:plan_id]
#membership = Membership.new
end
Assuming plan_I'd is part of your model..
Change your render line to:
render :new
Change the rest to:
def new
session[:membership_plan_id] = params[:plan_id]
#membership = Membership.new plan_id: params[:plan_id]
end
def create
#membership = Membership.new(membership_params)
if #membership.save
redirect_to root_path
else
flash[:error] = #membership.errors.full_messages.to_sentence
render :new
end
end
And add a hidden field for plan_id in your form. The reason render goes wrong is that it does not have the param available, trying to add it to the render operation does not work hence your issue
You need to render instead of redirecting. Use the ||= operator to help here.. It's all just ruby, so something like
(..snip..)
else
flash[:error] = "Problem with form"
new
end
end
def new
session[:membership_plan_id] = params[:plan_id]
#membership ||= Membership.new
render 'new'
end
The problem in brief: I'm working on a rails 4 app (4.1.8) and I'm trying to get flash[:notice] and flash[:alert] to show up under a form.
Two controllers: landingpage_controller and contacts_controller. The landingpage_controller serves a static landingpage through its show action and the contacts_controller has new and create actions, to store the contacts in a db table.
On the static landingpage, a modal with id="contact-modal" contains a partial with a simple_form_for #contact (see below). Upon submittal of the form, a db-entry is not created if the fields are not all filled out and a db-entry is created if the fields are filled out. However, no flash messages are displayed.
Wanted output:
Ideally the partial would re-load without leaving/closing the modal, with either: a success message and an empty form or a alert message and the form as it was upon submittal. How do I do this?
The controller: app/controllers/contacts_controller.rb
class ContactsController < ApplicationController
def new
#contact = Contact.new
render layout: "contact"
end
def create
#contact = Contact.new
respond_to do |format|
if #contact.save
flash[:notice] = "Success"
format.js
else
flash[:alert] = "Error"
format.js
end
end
end
private
def contact_params
params.require(:contact).permit(:email, :structure, :message_content)
end
end
The form: app/views/contacts/_new.html.haml
= simple_form_for #contact, html: { id: "contact-form"} do |c|
= c.input :email
= c.input :structure
= c.input :message_content
= c.button :submit
.messages-container
= if flash[:notice]
%p
= flash[:notice]
= if flash[:alert]
%p
= flash[:alert]
Routes:
resources :contacts, only: [:new, :create]
I'm aware that a partial reload probably involves AJAX. I've read several StackOverflow questions on this but have not been able to figure it out. See here, here and these two blog-posts: jetthoughts, ericlondon.
Your help is very much appreciated
There are several problems in your code:
views, that start with underscore are called partials and are not full actions, but just parts of reusable view code (you don't redirect to them, instead you use render since you usually don't want a full page reload.
1.1 Rename your _new.html.haml to _form.html.haml
2.1 Create a new view new.html.erb(I guess you have that already, otherwise your new action might not work properly) with content = render 'form'
From what I understand you don't want the modal to close, just to render a form after successful submission or if there is an error.
In that case:
1.create a create.js.erb file in your views/contacts folder
create.js.erb
$("#your_modal_id").html("<%= j( render 'form') %>")
2. change your create action
def create
#contact = Contact.new(contact_params)
respond_to do |format|
if #contact.save
flash[:notice] = "Success"
format.js
else
flash[:alert] = "Error"
format.js
end
end
end
to your form add remote: true
WARNING: This will leave your form filled in even if it is successful.
More about this topic see:
http://guides.rubyonrails.org/v4.1.8/working_with_javascript_in_rails.html#form-for
Hope it helps, and I hope I didn't forget anything
I have been trying to get to grips with jQuery and been following a railscast on adding an Ajax add review form, which works fine but I would now like to add into it the ability for a review to belong to a user as well as a venue.
Reviews controller
def create
#review = Review.create!(params[:review])
#review.venue = #venue
if #review.save
flash[:notice] = 'Thank you for reviewing this venue!'
respond_to do |format|
format.html { redirect_to venue_path(#venue) }
format.js
end
else
render :action => :new
end
end
views\reviews\create.js.erb
$("#new_review").before('<div id="flash_notice"><%= escape_javascript(flash.delete(:notice)) %></div>');
$("#reviews_count").html("<%= pluralize(#review.venue.reviews.count, 'Review') %>");
$("#reviews").append("<%= escape_javascript(render(:partial => #review)) %>");
$("#new_review")[0].reset();
I have tried changing the controller to:
def create
#review = #current_user.reviews.create!(params[:review])
#review.venue = #venue
if #review.save
flash[:notice] = 'Thank you for reviewing this venue!'
respond_to do |format|
format.html { redirect_to venue_path(#venue) }
format.js
end
else
render :action => :new
end
end
but it just wont submit, with no errors.
I think I have the models set correctly with belongs_to and has_many, I think this is a controller issue I'll add other code bits if needed.
Development log
NoMethodError (undefined method `reviews' for nil:NilClass):
app/controllers/reviews_controller.rb:14:in `create'
Thanks for any help!
It appears that your error is residing with #current_user. According to your development log, #current_user is nil when you call #current_user.reviews on it. I would say track down where this #current_user instance variable is being set and find out why it is nil. Now, what kind of authentication are you using? Most authentication plugins, especially those used by Ryan Bates of the Railscasts you mentioned, use a local variable, say just current_user, as the means to access the currently signed in user. I know I do in all my code.
So, rewrite the line as
#review = current_user.reviews.create!(params[:review])
and see if that works. If it doesn't, change it back and then track down where this #current_user is being set. Chances are good it is being set in a before_filter :method_name at the beginning of your controller.
Calling create! (with exclamation mark) will throw an exception and thus abort your create action if saving fails. Check your log/development.log for these exceptions.
Use build instead of create and lose the exclamation mark.
def create
#review = #current_user.reviews.build(params[:review])
#review.venue = #venue
if #review.save
flash[:notice] = 'Thank you for reviewing this venue!'
respond_to do |format|
format.html { redirect_to venue_path(#venue) }
format.js
end
else
render :action => :new
end
end
This is my users_controller.rb code:
...
def edit
#user = #current_user
end
def update
#user = #current_user # makes our views "cleaner" and more consistent
if #user.update_attributes(params[:user])
flash[:notice] = "Account settings updated."
redirect_back_or_default account_url
else
render :action => 'edit'
end
end
...
I have the following views/users:
new.html.erb
password.html.erb
profile.html.erb
show.html.erb
Everytime I try to update my user account settings, the following pops up:
ActionView::MissingTemplate (Missing template users/edit.erb in view path app/views:vendor/plugins/admin_data/app/views):
app/controllers/users_controller.rb:46:in `update'
It's not the fault of admin_data is you are curious. It's the controller. What have I done wrong? Thanks.
First, if you want the update action to return to :show, you should change
render :action => 'edit'
to
render :action => 'show'
otherwise, it will of course look for edit.html.erb or edit.erb
Second, if you use 'show' for letting the user edit his/her information, why do you actually have the :edit action in your controller? If you don't use it, you should probably remove the following:
def edit
#user = #current_user
end
unless you tell the edit method to render something else or redirect to some where, the default is that it will look for a template of edit.erb...