Redirect to SHOW action in another controller - ruby-on-rails

After creating a Person associated with a specific Account, how do I redirect back to the Account page?
The account_id is passed to the CREATE Person action via a URL parameter as follows:
http://localhost:3000/people/new?account_id=1
Here is the code:
<h2>Account:
<%= Account.find_by_id(params[:account_id]).organizations.
primary.first.name %>
</h2>
<%= form_for #person do |f| %>
<%= f.hidden_field :account_id, :value => params[:account_id] %><br />
<%= f.label :first_name %><br />
<%= f.text_field :first_name %><br />
<%= f.label :last_name %><br />
<%= f.text_field :last_name %><br />
<%= f.label :email1 %><br />
<%= f.text_field :email1 %><br />
<%= f.label :home_phone %><br />
<%= f.text_field :home_phone %><br />
<%= f.submit "Add person" %>
<% end %>
class PeopleController < ApplicationController
def new
#person = Person.new
end
def create
#person = Person.new(params[:person])
if #person.save
flash[:success] = "Person added successfully"
redirect_to account_path(params[:account_id])
else
render 'new'
end
end
end
When I submit the above form I get the following error message:
Routing Error
No route matches {:action=>"destroy", :controller=>"accounts"}
Why is the redirect_to routing to the DESTROY action? I want to redirect via the SHOW action. Any help will be greatly appreciated.

params[:account_id] exists in the form, but when you pass it to create you're sending it along in the person hash, so you'd access it via params[:person][:account_id]
params[:account_id] is nil, hence the bad route. To be honest, I'm not sure why, but resource_path(nil) ends up routing to destroy instead of show. In either case, it's a broken route without an id parameter.
# so you *could* change it to:
redirect_to account_path(params[:person][:account_id])
# or simpler:
redirect_to account_path(#person.account_id)
# but what you probably *should* change it to is:
redirect_to #person.account
Rails will inherently understand this last option, ascertaining the path from the class of the record, and getting the id from #to_param

I would not be pass this through using a hidden_field. Instead, use nested resources:
resources :account do
resources :people
end
Then have an account object for the form:
<%= form_for [#account, #person] do |f| %>
...
<% end %>
This #account object should be set up in the action that renders the form with a line like this:
#acccount = Account.find(params[:account_id])
Then when the form is submitted you'll have params[:account_id] in that action without the ugly hidden_field hack to get it there.
Yippee!

Related

When I try to load my create.html.erb page, I get this error "param is missing or the value is empty"

I got this error on loading the page and I would guess that it has somethinng to do with my create method in the controller
My controller looks like this
class StoryController < ApplicationController
def index
#story = Story.all
end
def new
#story = Story.new
end
def create
#story = Story.new(story_params)
if #story.save
flash[:notice] = "Story created successfully"
flash[:color]= "valid"
else
flash[:notice] = "Story is invalid, man"
flash[:color]= "invalid"
end
end
def show
#story = Story.find(params[:id])
end
private
def story_params
params.require(:story).permit(:story_title, :story_body)
end
end
My create.html.erb looks like
<%= form_for #story ,url: story_path do |f| %>
<%= label :story, :title %><br />
<%= text_field :story, :story_title %>
<%= label :story, :body %><br />
<%= text_field :story, :story_body %>
<%= submit_tag 'Create story' %>
<% end %>
My create.html.erb didnt look like this before, I changed it to that after I read some questions about how form_for would work instead of form_tag for the story_params.
But either way, I still get the error anyways and I would like to know why and if there is a fix for it.
very first, you don't need to specify a path if you are using form_for and if you don't want to submit a form on the custom route.
If you are using new object then it will submit form on create method and for existing object it will submit form on update method.
So your form will be,
<%= form_for #story do |f| %>
<%= f.label :title %><br />
<%= f.text_field :story_title %>
<%= f.label :body %><br />
<%= f.text_field :story_body %>
<%= submit_tag 'Create story' %>
<% end %>
And this form needs to be in new.html.erb file.
This form will submit your form to create action with post method and from there you need to do render or redirection depending upon condition. So your controller will be,
class StoryController < ApplicationController
def index
#story = Story.all
end
def new
#story = Story.new
end
def create
#story = Story.new(story_params)
if #story.save
flash[:notice] = "Story created successfully"
flash[:color]= "valid"
redirect_to story_path(#story)
else
flash[:notice] = "Story is invalid, man"
flash[:color]= "invalid"
render :new
end
end
def show
#story = Story.find(params[:id])
end
private
def story_params
params.require(:story).permit(:story_title, :story_body)
end
end
If you do rake routes in the termial, you can see all methods with its expected methods
Also according to rails conventions, if you have story model then you can directly create :title & :body attributes instead of :story_title and :story_body
The create method is a POST... so when he enters story/create he's already expecting those values... that's why he says he can't find the params... i didn't look at the code deeply but it seems fine. Just change the name of the view to new.html.erb. New is the setup for create.
In new you setup the values and then invoke create where the controller actually creates the story.
Just change the name of the view to new.html.erb and change it to this
<%= form_for #story do |f| %>
<%= f.label :title %><br />
<%= f.text_field :story_title %>
<%= f.label :body %><br />
<%= f.text_field :story_body %>
<%= submit_tag 'Create story' %>
<% end %>
as the other user said. you need to say that those inputs belong to form |f| the text_field belongs to f, f.text_field
And of course you access that view through stories/new
Try this make changes in the create.html.erb
<%= form_for #story ,url: story_path do |f| %>
<%= f.label :title %><br />
<%= f.text_field :story_title %>
<%= f.label :body %><br />
<%= f.text_field :story_body %>
<%= submit_tag 'Create story' %>
<% end %>
Are you sure your attributes for the Story object are named story_title and story_body ?
If not, your story_params should be like this :
def story_params
params.require(:story).permit(:title, :body)
end
And also, apply #koshlendra suggestion, he's right.
I suggest you to generate a scaffolding for a fake resource to see how it's supposed to work :
rails g scaffold Fake title:string body:text
Then look at the generated controller and views to understand fully how it works.

Routes in ruby with rails, html forms not working

I am new to ruby with rails,I generated a new Controller named users by using command:
rails generate controller users register index login
After that I opened register.html.erb and wrote following code:
<h1>Register New User</h1>
<p>
<%= form_for :user do |f| %>
<%= f.label:USERID %><%= f.text_field:userid %><br />
<%= f.label:PASSWORD %><%= f.text_field:password %><br />
<%= f.label:EMAIL %><%= f.text_field:email %><br />
<br />
<%= f.submit %>
<% end %>
</p>
Then in users_controller.rb I wrote following code in register:
class UsersController < ApplicationController
def index
end
def show
end
def login
end
def register
print "test"
end
def user_params
params.require(:user).permit(:userid,:password,:email)
end
end
And test is not being printed and get and post methods of the form are not working at all.
And params.require(:user).permit(:userid,:password,:email) is not working as well. I get error that :user is empty.
I get error that :user is empty.
form_for(path/to/your/controller/action) is a helper method to create HTML form elements with the url path to the POST or GET request. The helper knows if it should be a new record or an update record based on what you are asking to do in your controller action. So, basically, it's looking for the #user in the corresponding controller action when you write form_for #user in your view. As you don't have it currently, hence you ar getting this error.
See this for more information.
To solve your current problem, you have to define the #user in the controller's register action:
def register
#user = User.new(user_params)
end
Then, in your register.html.erb file's form, you can use that #user:
<h1>Register New User</h1>
<p>
<%= form_for #user do |f| %>
<%= f.label :USERID %>
<%= f.text_field :userid %><br />
<%= f.label :PASSWORD %>
<%= f.text_field :password %><br />
<%= f.label :EMAIL %>
<%= f.text_field :email %><br />
<br />
<%= f.submit %>
<% end %>
</p>

update record outside of namespaced admin [rails]

I have a named spaced admin in my app, where you can CRUD a client, this works great.
Outside of the admin within the app the #current_user has the opportunity to edit the client's address.
I am not sure how to access this and persist the new update to the database. this is what I have so far
products_controller.rb (where the partial is rendering from)
class ProductsController < ActionController::Base
layout "application"
def index
#products = Product.all
end
def show
#products = Product.all
#current_user = Client.find_by(id: session[:client])
end
end
_overlay_checkout.html.erb (this populates a form with the clients address from the db, and if its not updated they can change it.)
<%= simple_form_for([:admin, #current_user], :url => edit_admin_client_path) do |f| %>
<%= f.text_field :address %><br />
<%= f.text_field :address_line_2 %><br />
<%= f.select(:state, options_for_select(us_states, "CA")) %> <br />
<%= f.text_field :zipcode %><br />
<%= f.text_field :city %><br />
<%= f.submit %>
<% end %>
im unsure how I can update this record, ... without being in the admin section of the app, .. any help would be greatly appreciated.
One thing I've done in situations like this is to specify #submit_url as an instance variable in my controller action.
class ProductsController < ApplicationController
def show
#submit_url = client_path(#client)
end
end
You can can pass this variable to your form_for call like so:
<%= simple_form_for([:admin, #current_user], :url => #submit_path) do |f| %>
<%= f.text_field :address %><br />
<%= f.text_field :address_line_2 %><br />
<%= f.select(:state, options_for_select(us_states, "CA")) %> <br />
<%= f.text_field :zipcode %><br />
<%= f.text_field :city %><br />
<%= f.submit %>
<% end %>
If the #submit_url is not nil then the form action will be set to the value of the #submit_url otherwise it will get set to the resource based route that you specified. This means that in Admin Controller will not need to be changed at all. Just the alternate controller (in this case products_controller) where you want the submission of the form to go someplace other than the auto generated resourceful route.

Routing Error - No route matches [POST] for new

I'm getting an error with routes and I can't find where is the problem, I'm creating a simple CRUD and get this trouble with the create method.
Error
No route matches [POST] "/usuarios/new"
Controller
def new
#usuario = Usuarios.new
end
def create
#usuario = Usuarios.new(params[:usuario])
if #usuario.save
redirect_to usuario_path, :notice => "Cadastrado realizado com sucesso!"
else
render "new"
end
end
new.html.erb
<h1>Add new user</h1>
<%= form_for (:usuario) do |f| %>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<p>
<%= f.label :idade %><br />
<%= f.text_field :idade %>
</p>
<p>
<%= f.label :email %><br />
<%= f.text_field :email %>
</p>
<p>
<%= f.submit "send" %>
</p>
<% end %>
As Flexoid has pointed out, you probably haven't add the new method in the controller.
So, put this
def new
#usuario = Usuario.new
end
EDIT
You have to pay more attention.
Take a look:
def new
#usuario = Usuario.new # not Usuarios.new, that's wrong.
end
def create
#usuario = Usuario.new(params[:usuario]) # not usuarios, first letter should be capital
if #usuario.save
redirect_to usuarios_path, :notice => "Cadastrado realizado com sucesso!" # usuario_path requires an id parameter like `usuario_path(#usuario)` or you could redirect to the `index` with `usuarios_path`
else
render "new"
end
end
Change
<%= form_for (:usuario) do |f| %>
to
<%= form_for (#usuario) do |f| %>
Seems like you forgot about configuring of the Rails Router.
Try to add this to your config/routes.rb file:
resources :usuarios
For the reference you can read rails guide Rails Routing from the Outside In.

Rails 3 - params on create action not assigning values to model

I am having an issue that, when form values are posted to a create action, the values are not being assigned to the new model.
For example -
I have a partial form, _form.html.erb in views/groups/:
<%= form_for #group, :html => { :multipart => true } do |f| %>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<p>
<%= f.label :website %><br />
<%= f.text_field :website %>
</p>
<p>
<%= f.label :description %><br />
<%= f.text_area :description %>
</p>
<p>
<%= f.label :image %><br />
<%= f.file_field :image %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
This is rendered in views/groups/new.html.erb:
<h1>Group#new</h1>
<%= render :partial => "form" %>
My new action looks like this:
def new
#group = Group.new
end
And my create action looks like this:
def create
#raise params.inspect
#group = Group.new(params[:group])
#raise #group.inspect
if #group.save
flash[:message] = "Group Created!"
redirect_to groups_path
else
flash[:message] = "Sorry, there are errors in the form"
render :new
end
end
If I raise params.inspect, I get this:
{"utf8"=>"✓", "authenticity_token"=>"cVW7BgMKFU1z3QlyCOGq5y2t7IcKcsatVsXDDE1069g=", "group"=>{"name"=>"testname", "website"=>"testweb", "description"=>"testdesc"}, "commit"=>"Create Group", "action"=>"cr
... which appears to have my :group hash values just fine.
If I try to assign it then inspect that:
#group = Group.new(params[:group])
raise #group.inspect
I get:
#<Group id: nil, name: nil, description: nil, website: nil, image: nil, created_at: nil, updated_at: nil>
What am I missing here? I have 2 other controllers structured very similarly, but I'm not sure what I did wrong here -
Thanks!
It's also worth a check see if mass assignment is set properly. Do you have any attr_accessible :name... in the Group model?
If so, check if #group.name = params[:group][:name] would set the name value. Usually if this works it means the field is not be able to mass assigned via = hash.
Note that params[:group] depends on the hash being #with_indifferent_access. Every once in a while I run across something like this that should be with_indifferent_access, but isn't due to a plugin manipulating the params or some such. Worth a check (i.e. try params['group']).

Resources