How to render an action plus GET parameter? - ruby-on-rails

In my Rails 4 application I have this controller:
class ProfilesController < ApplicationController
SECTIONS = %w(time currency letterhead)
def edit
section = Profile::SECTIONS.include?(params[:section]) ? params[:section] : Profile::SECTIONS[0]
session[:section] = section
end
def update
if #profile.update_attributes(profile_params)
flash[:success] = "Profile updated."
redirect_to edit_profile_path(:section => session[:section])
else
render :edit
end
end
end
In the view, each user's profile record is spread across three different tabs using GET parameters.
E.g. when the user is in the "time" tab and successfully saves it, s/he is redirected to that same tab. Nice!
But unfortunately, when the save is unsuccessful (and Rails' validation kicks in), that doesn't work.
I tried adding a parameter to render but to no avail.
Can anybody tell me what's the best way to do this?
Thanks for any help.

I think you're checking params[:section] in the view and you're using its value to determine which tab to show. So the easiest solution is to just set params[:section] in the else part.
if #profile.update_attributes(profile_params)
flash[:success] = "Profile updated."
redirect_to edit_profile_path(:section => session[:section])
else
params[:section] = session[:section]
render :edit
end
Another easier way is to just use session[:section] in the view so you don't have to pass it in between requests.

render :edit, :locals => {:params1 => "value"}
Use locals to pass paramters in render

Related

Keep model with errors when redirecting to edit

When there was an error on updating my model, I was rendering :edit, but this was stripping the /edit from my url because #update is the same as #show with a different request method. To solve this I tried following the advice given here, but this caused me to get an ActionDispatch::Cookies::CookieOverflow error when I try to submit an invalid form. How should I correctly re render the edit page, while keeping both the /edit url and the flash messages? Is it possible to check for validity and show the errors without making a call to update?
Original code:
def edit
end
def update
respond_to do |format|
format.html do
if #model.update(model_params)
redirect_to home_base_url_or_default(model_url(#model)), notice: "Successfully updated."
else
render :edit
end
end
end
end
Failing code:
def edit
if flash[:model]
#model = flash[:model]
end
end
def update
respond_to do |format|
format.html do
if #model.update(model_params)
redirect_to home_base_url_or_default(model_url(#model)), notice: "Successfully updated."
else
flash[:model] = #model
redirect_to :action => :edit
end
end
end
end
Rather than doing a redirect, in this case the problem was solved by doing a render, then controlling the view by setting an instance var in the controller saying if it is the edit page or not. Also by using the update class in the CSS. However, this still has the the url for the show page, but at least the layout is correct.
One way to do it would be to allow the edit action to accept the POST method as well. Use request.method to check whether it is a POST or GET, then perform your render or redirect accordingly.

How do I define a custom URL for a form confirmation page?

I am creating a basic product landing page with Rails in which users can enter their email address to be notified when the product launches. (Yes, there are services/gems etc that could do this for me, but I am new to programming and want to build it myself to learn rails.)
On successful submit of the form, I would like to redirect to a custom '/thanks' page in which I thank users for their interest in the product (and also encourage them to complete a short survey.)
Currently, successful submits are displayed at "/invites/:id/" eg "invites/3" which I do not want since it exposes the number of invites that have been submitted. I would like to instead redirect all successful submits to a "/thanks" page.
I have attempted to research "rails custom URLs" but have not been able to find anything that works. The closest I was able to find was this Stackoverflow post on how to redirect with custom routes but did not fully understand the solution being recommended. I have also tried reading the Rails Guide on Routes but am new to this and did not see anything that I understood to allow for creating a custom URL.
I have placed my thanks message which I would like displayed on successful form submit in "views/invites/show.html.haml"
My Routes file
resources :invites
root :to => 'invites#new'
I tried inserting in routes.rb:
post "/:thanks" => "invites#show", :as => :thanks
But I don't know if this would work or how I would tell the controller to redirect to :thanks
My controller (basically vanilla rails, only relevant actions included here):
def show
#invite = Invite.find(params[:id])
show_path = "/thanks"
respond_to do |format|
format.html # show.html.erb
format.json { render json: #invite }
end
end
# GET /invites/new
# GET /invites/new.json
def new
#invite = Invite.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #invite }
end
end
# POST /invites
# POST /invites.json
def create
#invite = Invite.new(params[:invite])
respond_to do |format|
if #invite.save
format.html { redirect_to #invite }
#format.js { render :action => 'create_success' }
format.json { render json: #invite, status: :created, location: #invite }
else
format.html { render action: "new" }
#format.js { render :action => 'create_fail' }
format.json { render json: #invite.errors, status: :unprocessable_entity }
end
end
end
It would seem as if creating a standard URL for displaying a confirmation would be relatively straightforward. Any advice on how to achieve this would be appreciated.
I guess you want to redirect after your create action, which is executed when the form is submitted.
Just add redirect_to in the following way:
def create
#invite = Invite.new(params[:invite])
if #invite.save
...
redirect_to '/thanks'
else
...
redirect_to new_invite_path # if you want to return to the form submission page on error
end
end
I omitted some of the code for brevity.
In your routes add:
get '/thanks', to: "invites#thanks"
Add the thanks action to your invites controller:
def thanks
# something here if needed
end
And create a thanks.html.erb page in app/views/invites.
I would do get "/thanks" => "invites#thanks" in routes.rb and then add this in your controller:
def thanks
end
Then add a file app/views/invites/thanks.html.erb with your thank-you content.
You could create a route like this:
resources :invites do
collection do
get 'thanks'
end
end
This will also create a path helper called thanks_invites_path.
It will be at the invites/thanks path, but if you want it to be on/thanks, you could just do as Jason mentioned:
get "/thanks" => "invites#thanks", :as => :thanks
The as part will generate a helper to access that page: thanks_path.
You would need a extra action in the controller called thanks, and put whatever info you need inside, and also you will need a additional view called thanks.html.erb
Since you want everybody to go to that page after a successful submit, in your create action you would have:
format.html { redirect_to thanks_invites_path} (or thanks_path), what ever you choose, when you name the route you can check it with rake routes if it's okay, and whatever rake routes says, just add _path at the end.

Controller not calling the View in Rails , is Sample

1 - My controller is this , but this not call the view whit this name is login.html.erb, im not understand beacause what happen this , is to show the form of the login.
class FinancesController < ApplicationController
# GET /finances
# GET /finances.json
def login
#user = User.find_by_name(params[:user])
if #user
session[:user_id] = #user.id
redirect_to :action => 'index'
else
redirect_to login_url
end
end
def index
#finances = Finance.all(:order => "created_at")
respond_to do |format|
format.html # index.html.erb
format.json { render json: #finances }
end
end
2 - Someone can talk to me to use the authenticate method to validate a sample login whit user and password forms some, can show to me how use this method , the find_by_name_and_password dont works.
I thanks by the answers, many.
Routes.rb
Controle::Application.routes.draw do
match 'login' => 'finances#login'
resources :finances
end
check for the #user object.
because, as of your code it will redirect to your login method if #user is not available.
To render login.html.erb from login method, there is no need for any manual redirections.

instance var was not kept across the method

Here is code in customers controller:
def edit
#customer = Customer.find(params[:id])
#return_to = params[:return_to]
end
def update
#customer = Customer.find(params[:id])
if #customer.update_attributes(params[:customer], :as => :roles_new_update)
redirect_to #return_to, :notice => 'Customer was updated successfaully!'
else
render 'edit', :notice => 'Customer was not updated!'
end
end
It is verified that there is value in #return_to in method edit. However there is an error saying: Cannot redirect to nil! for
redirect_to #return_to, :notice => 'Customer was updated successfaully!'
in method update.
Any thoughts about the error? Thanks.
It's because when you are on the edit action, that is one request to show the form. Then when you submit the form, that is a second request calling the update action. Any states set in an action are confined to that action alone. There's a few ways to use data across multiple actions:
The database (So save it in a model)
The session hash
Pass it in the view to go into your form.
Because it's a redirect/return to value, i would suggestion using a session variable such as:
session[:return_to] = params[:return_to]
In your edit action, then just refer to that value in your update:
session[:return_to]
I don't understand; edit doesn't call update, so there'd be no intrinsic reason for #return_to to still exist.
Are you aware that controllers are created per-request?

Can't find View template in Rails?

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...

Resources