I have a simple User model with a singular nested Profile resource so in my routes.rb I have:
resources :users do
resource :profile, :only => [:edit, :update, :show]
end
This generates the expected routes:
edit_user_profile GET /users/:user_id/profile/edit(.:format) {:action=>"edit", :controller=>"profiles"}
user_profile GET /users/:user_id/profile(.:format) {:action=>"show", :controller=>"profiles"}
user_profile PUT /users/:user_id/profile(.:format) {:action=>"update", :controller=>"profiles"}
I've created a simple controller update method that updates the model and then redirects upon successful update:
def update
#profile = Profile.find_by_user_id(params[:user_id])
#user = User.find_by_id(params[:user_id])
respond_to do |format|
if #profile.update_attributes(params[:profile])
format.html { redirect_to( user_profile_path(#user, #profile), :notice => 'Profile was successfully updated.') }
else
# ...
end
end
end
The problem is that once the form is submitted, the form redirects to mydomain.com/users/4/profile.22 where 22 happens to be the id of the profile. Clearly this confuses the controllers since the routing interprets the '22' as the format.
My question is, how do I get this to redirect to mydomain.com/users/4/profile instead? I've tried the following variations on the redirect_to statement to no effect, they all result in the same incorrect url:
redirect_to( user_profile_path(#user), ... )
redirect_to( user_profile_path(#user, #profile), ... )
redirect_to([#user, #profile], ... )
redirect_to( #profile, ... )
What's more, using 'user_profile_path(#user)' elsewhere produces the correct url.
Any ideas? Oh, and I'm using Rails 3.0.0 and Ruby 1.9.2 if that helps.
After looking around, it appears that the form generating the update had an incorrect url. If anyone is seeing this issue, it's because I had my form set up as:
form_for [#user, #profile] do |f| ...
This caused the form action to have the incorrect url (of the offending form above). Instead, I used
form_for #profile, :url => user_profile_path(#user) do |f| ...
and everything seemed to work.
You should redirect to user_profile_path(#user) since as your routes says it is:
/users/:user_id/profile(.:format)
If you look at it closely, then you will see, that there is only :user_id parameter needed, thou it is only #user in a path.
/users/:user_id/profile/:id(.:format)
It would be correct if you had resource*s* :profiles in your routes.rb, then as well you could use your path as in your example.
user_profile_path(#user) should be correct. You're sure that one is returning mydomain.com/users/4/profile.22?
Related
I have a model called 'users' that I changed to 'people' in the url.
Routes.rb
resources :users, :path => "people"
Everything works fine except when creating a new user I get a routing error and it redirects to '/users', instead of creating the user and going to '/people/:id'.
No route matches [POST] "/users"
If I take
:path => "people"
out of the routes it works fine.
The form looks like:
<%= simple_form_for(#user) do |f| %>
and here is the controlller:
def create
#user = User.create(user_params)
if #user.save
redirect_to #user
else
redirect_to root_path
end
end
What is happening is in your route file, you are changing what the users route is routing to with your path: 'people' call.
However, since rails sees that the model you're creating is called User, it assumes that it should post that to /users.
While, I'm not completely familiar with simple_form, this works with normal rails:
<%= form_for #user, url: users_path do |f| %>
Notice the url: users_path option, what this does is explicitly link the form to the user path, aka /testers.
--Cheers
I need a page for changing Profile of current user, it's weird if the url is /user/:id, so I map it to /settings
get "/settings", to: "users#edit", as: "settings_user"
But when I submit the form I got this error:
Routing Error
No route matches [PATCH] "/settings"
The weird part is if I press back and re-submit the form, it will submit just fine.
If I go to another page then back to the form, it will get error on first try but works fine on second try onward.
My controller:
class UsersController < ApplicationController
...
def edit
#user = current_user #this is the cache of currently logged in user
end
def update
#user = User.find(params[:id])
if #user.update(user_params)
redirect_to settings_user_path, notice: "Profile has been saved"
end
end
private
def user_params
params.require(:user).permit(:id, :name, :email, :bio)
end
end
My view:
<%= form_for #user do |f| %>
...
<% end %>
Note:
Other page that are using the default route like my Product page works fine, so it's not the Rails config problem.
Devise
I guess you're using devise (by how you're using current_user) - so you may wish to look at Devise' custom routing paths. Although this won't provide a routing structure for your user object, it may come in handy some time:
#config/routes.rb
devise_for :users, path: "auth", path_names: { sign_in: 'login', sign_out: 'logout', password: 'secret', confirmation: 'verification', unlock: 'unblock', registration: 'register', sign_up: 'cmon_let_me_in' }
--
Routes
If you want to manage your user object, you'll be best using the resources route definition:
#config/routes.rb
resources :users, only: [], path: "" do
collection do
get :settings, action: :edit
match :settings, action :update, via: [:patch, :put]
end
end
The problem you have is your form is thinking it should send your update request to /settings too:
No route matches [PATCH] "/settings"
The way around this is to either provide a route for patch (as demonstrated above), OR define the url parameter of the form:
<%= form_for #user, url: your_update_path do |f| %>
--
Hope this helps?
This issue only occur on Chrome 37 Beta. I reverted back to Chrome 36 Release and everything works fine.
I guess I won't use the beta version for daily use ever again.
My rails app is adding a dot/period "." into the route when trying to browse to a devise gem user's profile.
routes.rb:
devise_for :users, :controllers => { :registrations => "registrations" }
(Basically using routes to allow for some custom functions - it should be still using the default devise routing paths.
Rake routes output:
user_registration POST /users(.:format) registrations#create
new_user_registration GET /users/sign_up(.:format) registrations#new
edit_user_registration GET /users/edit(.:format) registrations#edit
Link in view:
<%= link_to 'Edit', edit_user_registration_path(user) %>
Where user is defined in a .each loop.
Outputted Link in URL looks like:
http://localhost:3000/users/edit.2
My goal is to have a link to edit any user's profile (permissions controlled outside these items of course).
I "think" my problem is the routes.rb and not specifying the path correctly there. I think it should be something that would have a rake routes that includes an :id parameter.
Thanks for the help!
That's normal routes's devise, registrations#edit is for edit current signed-in user, If you want to CRUD interface for users (I think you want to editing a user), you can add another controller (e.g users_controller.rb) and make some action , example for controller :
def edit
#user = User.find(params[:id])
end
def update
if params[:user][:password].blank?
params[:user].delete(:password)
params[:user].delete(:password_confirmation)
end
#user = User.find(params[:id])
respond_to do |format|
if #user.update_attributes(params[:user])
format.html { redirect_to some_path, notice: 'Updated.' }
format.json { head :no_content }
else
format.html {
flash[:alert] = "Something wrong"
render :action => :edituser
}
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
On your routes.rb you can following like this
scope '/user' do
match '/edit/:id' => 'users#edit', :as => :edit_user
put '/update/:id' => 'users#update', :as => :update_user
end
And links on each section looks like :
<%= link_to 'Edit', edit_user_path(user) %>
references :
How To: Manage users through a CRUD interface
CRUD Devise Example
I think Devise's edit_user_registration_path uses current_user internally, so you shouldn't need the (user) in your link_to
I have this controller
def usersedit
#user = User.find_by id: params[:id]
end
def usersupdate
#user = User.find_by id: params[:id]
if #user.update(post_params)
redirect_to action: :users
else
render 'usersedit'
end
end
And this form in the view in usersedit.html.erb
<%= form_for :user, url: {action: "usersupdate"}, method: :patch do |f| %>
but when I submit the form this error appears
No route matches [PATCH] "/admin/usersupdate"
My routes code is:
Prefix Verb URI Pattern Controller#Action
root GET / pages#home
admin_index GET /admin/index(.:format) admin#index
admin_grades GET /admin/grades(.:format) admin#grades
pages_home GET /pages/home(.:format) pages#home
pages_register GET /pages/register(.:format) pages#register
pages_create POST /pages/create(.:format) pages#create
pages_login GET /pages/login(.:format) pages#login
pages_logging POST /pages/logging(.:format) pages#logging
pages_logout GET /pages/logout(.:format) pages#logout
GET /activate/:user/:hash(.:format) pages#activate
remember POST /remember(.:format) pages#remember
reactivation POST /reactivation(.:format) pages#reactivation
admin_documents GET /admin/documents(.:format) admin#documents
admin_users GET /admin/users(.:format) admin#users
GET /admin/usersedit/:id(.:format) admin#usersedit
admin_usersupdate POST /admin/usersupdate(.:format) admin#usersupdate
Help please.
change the method in the form method: :post
your header of form
form_for :user, url: {action: "usersupdate"}, :method => :POST do |f|
I had the same problem, you'll need to update your routes.rb file correctly.
I'm guessing the line in your routes file where you've defined this path starts with "post", try changing that to "patch".
Inside of config/routes.rb
change:
post "admin/usersupdate" => "admin#usersupdate", :as => "admin/usersupdate"
to:
patch "admin/usersupdate" => "admin#usersupdate", :as => "admin/usersupdate"
Everything works swimmingly for me after I made this change.
You defined the route with POST, but you use PATCH in the form.
I am a .NET developer moving to Ruby on Rails. I have been programming in ASP.NET MVC and now trying to apply the same concepts to Rails. I created index action and now when I say home/index it automatically redirects me the "show" action which does not exists. My routes.rb file has this particular line:
resources :home
home is the home_controller.
What am I doing wrong?
class HomeController < ApplicationController
def show
end
# show all the articles
def index
#articles = Array.new[Article.new,Article.new,Article.new]
respond_to do |format|
format.html
format.xml { render :xml => #articles }
end
end
def new
#article = Article.new
respond_to do |format|
format.html
format.xml { render :xml => #article }
end
end
def create
#article = Article.new(params[:post]);
if #article.save
format.html { redirect_to(#post,
:notice => 'Post was successfully created.') }
end
end
def confirm
end
end
You can run "rake routes" to check out what rails thinks about your routes and which urls will be dispatched to which controllers.
In your case, I get:
home_index GET /home(.:format) {:action=>"index", :controller=>"home"}
home_index POST /home(.:format) {:action=>"create", :controller=>"home"}
new_home GET /home/new(.:format) {:action=>"new", :controller=>"home"}
edit_home GET /home/:id/edit(.:format) {:action=>"edit", :controller=>"home"}
home GET /home/:id(.:format) {:action=>"show", :controller=>"home"}
home PUT /home/:id(.:format) {:action=>"update", :controller=>"home"}
home DELETE /home/:id(.:format) {:action=>"destroy", :controller=>"home"}
So to get to the index action, you need to go to "/home". If you go to "/home/index", it will think "index" is the ID of the resource, thus dispatching to the show action.
However, in Rails, it's custom to use plural names for controllers, and naming them after the resource they represent (this is usually a model, but it doesn't have to be). So in your case the name of the controller should be "ArticlesController" and your routes.rb should contain "resources :articles". Rails is very anal about plural and singular names.
The big advantage of using the plural name of the resource you're accessing, is that you can now use short notations, like "redirect_to #article", "form_for #article do |f|", etc.
So, resources in Rails are supposed to be telling about what you want your actually getting. This helps maintenance too, since other developers have to guess less. If you find yourself needing more than one ArticlesController, consider using namespaces, or try to figure out if one of those controllers are actually another resource (even though they store their data in the same database table).
More information about the routers can be found in the Rails Guide: http://guides.rubyonrails.org/routing.html