Trouble on setting the ':controller' parameter for a 'link_to' statement - ruby-on-rails

I am using Ruby on Rails 3.0.9 and I would like to know why I get the error described below and how can I solve that.
In my /views/articles/categories/_content.html.erb file I have:
...
<%= link_to("New article", {:controller => content[:article_controller], :action => 'new'}) %>
...
If I set the content[:article_controller] to (both setting true and false for the :only_path option)
1. content[:article_controller] = 'articles'
2. content[:article_controller] = '/articles'
3. content[:article_controller] = '/articles/'
4. content[:article_controller] = '/'
4. content[:article_controller] = ''
I get respectively the following errors (note :controller values):
1. `ActionView::Template::Error (No route matches {:controller=>"articles/categories/articles", :action=>"new"})`
2. `ActionView::Template::Error (No route matches {:controller=>"articles//articles", :action=>"new"})`
3. `ActionView::Template::Error (No route matches {:controller=>"articles/", :action=>"new"})`
4. `ActionView::Template::Error (No route matches {:controller=>"articles//", :action=>"new"})`
4. `ActionView::Template::Error (No route matches {:controller=>"articles/categories/", :action=>"new"})`
Is it a Ruby on Rails bug or is it my fault? What is the problem and how can I solve that making the link_to properly work?
However I can solve that problem by using:
<%= link_to("New article", {:controller => '../', :action => 'new'}) %>
But why it works with '.../' but not in other ways?
I noticed that some time the controller path for which I try to set the content[:article_contr8oller] seems to relying on the "base" current controller path that is handling the view file (the controller file is app/controllers/articles/categories/concerns_controller.rb - read below for more information)... why it happens?
It also happens using url_for:
url_for(:controller => 'articles', :action => 'new')
Running the rake routes command I get the following:
articles_categories GET /articles/categories(.:format) {:action=>"index", :controller=>"articles/categories"}
POST /articles/categories(.:format) {:action=>"create", :controller=>"articles/categories"}
new_articles_category GET /articles/categories/new(.:format) {:action=>"new", :controller=>"articles/categories"}
edit_articles_category GET /articles/categories/:id/edit(.:format) {:action=>"edit", :controller=>"articles/categories"}
articles_category GET /articles/categories/:id(.:format) {:action=>"show", :controller=>"articles/categories"}
PUT /articles/categories/:id(.:format) {:action=>"update", :controller=>"articles/categories"}
DELETE /articles/categories/:id(.:format) {:action=>"destroy", :controller=>"articles/categories"}
articles GET /articles(.:format) {:action=>"index", :controller=>"articles"}
POST /articles(.:format) {:action=>"create", :controller=>"articles"}
new_article GET /articles/new(.:format) {:action=>"new", :controller=>"articles"}
edit_article GET /articles/:id/edit(.:format) {:action=>"edit", :controller=>"articles"}
article GET /articles/:id(.:format) {:action=>"show", :controller=>"articles"}
PUT /articles/:id(.:format) {:action=>"update", :controller=>"articles"}
DELETE /articles/:id(.:format) {:action=>"destroy", :controller=>"articles"}
P.S.: If you need more information, let me know and I will update the question as well.
UPDATE I
In my route file I have:
namespace :articles do articles :categories end
scope :path => 'articles/categories/:id', :controller => 'articles/categories/concerns' do
...
end
resources :articles
UPDATE II
In my view /views/articles/categories/_content.html.erb files I have:
<div class="links">
<%= link_to("New article", {:controller => content[:article_controller], :action => 'new'}) %>
</div>
In my Articles::Categories::ConcernsController (that is, in the app/controllers/articles/categories/concerns_controller.rb file) I have:
def show
#articles_category = Articles::Category.find(params[:id])
respond_to do |format|
format.html {
render :partial => '/views/articles/categories/_content.html.erb',
:locals => {
:content => {
:article_controller => '/articles'
}
}
format.js {
...
end
end
end

Did you try using symbols? I think they are more "direct".
<%= link_to("New article", {:controller => content[:article_controller].to_sym, :action => :new}) %>
Did you try using a relativ path?
<%= link_to("New article", {:controller => "../#{content[:article_controller]}", :action => 'new'}) %>

Why aren't you using link_to 'New article', new_article_path? Why use the old, tired url_for ... when you can use the named path/url helper (new_article_url).

Related

'show' route matched instead 'new'

rails 3.1
rake routes for admin/sections_contoller
trigger_admin_section GET /admin/sections/:id/trigger(.:format) {:action=>"trigger", :controller=>"admin/sections"}
admin_sections GET /admin/sections(.:format) {:action=>"index", :controller=>"admin/sections"}
POST /admin/sections(.:format) {:action=>"create", :controller=>"admin/sections"}
new_admin_section GET /admin/sections/new(.:format) {:action=>"new", :controller=>"admin/sections"}
edit_admin_section GET /admin/sections/:id/edit(.:format) {:action=>"edit", :controller=>"admin/sections"}
admin_section GET /admin/sections/:id(.:format) {:action=>"show", :controller=>"admin/sections"}
PUT /admin/sections/:id(.:format) {:action=>"update", :controller=>"admin/sections"}
DELETE /admin/sections/:id(.:format) {:action=>"destroy", :controller=>"admin/sections"}
routes.rb
namespace :admin do
resources :sections do
resources :items
resources :parameters
get :trigger, :on => :member
end
...
end
view
<%= link_to "Add a section", new_admin_section_path, :class=>'add-btn' %>
generated link
http://localhost:3000/admin/sections/new
result
No route matches {:action=>"show", :controller=>"admin/sections",
:id=>#<Section id: nil, ..., meta_description: nil}
strange bug or my mistake. other controllers has similar routes and all works fine.
for ex.:
<%= link_to 'Add a group', new_admin_group_path, :class=>'add-btn' %>
works GREAT!
please, help or i'll kill myself someday
upd1 same problem on heroku with this app.
upd2 join github issue: https://github.com/rails/rails/issues/4704
i found the answer.
once i put this string in view 'admin/section/_form'
<%= link_to 'delete', admin_section_path(#section), :method => :delete, :confirm => "Sure?" %>
i used this form for creating and editing. so combination of new object and deleting link for it caused the bug.
i used debugger for analysis.
Look at your "create" method in sections_controller.
I guess your section is correctly created but it redirect to "show" action. And "show" view may not exist.
Have you checked your database ? Is the section saved ?

custom route no routes match

During cucumber tests, I get the following error:
No route matches "/companies/29/update_owner"
I am not sure what I am doing wrong, but im sure its something stupid.
I have the following routes:
company_update_owner POST /companies/:company_id/update_owner(.:format) {:controller=>"companies", :action=>"update_owner"}
company_set_owner /companies/:company_id/set_owner(.:format) {:controller=>"companies", :action=>"set_owner"}
companies GET /companies(.:format) {:action=>"index", :controller=>"companies"}
POST /companies(.:format) {:action=>"create", :controller=>"companies"}
new_company GET /companies/new(.:format) {:action=>"new", :controller=>"companies"}
edit_company GET /companies/:id/edit(.:format) {:action=>"edit", :controller=>"companies"}
company GET /companies/:id(.:format) {:action=>"show", :controller=>"companies"}
PUT /companies/:id(.:format) {:action=>"update", :controller=>"companies"}
DELETE /companies/:id(.:format) {:action=>"destroy", :controller=>"companies"}
I have tried:
company_update_owner_path(:company_id => #company.id)
and
company_update_owner_path(#company)
update:
= form_for #company, :url => company_update_owner_path(:company_id => #company.id), :method => :put do |f|
Any help would be greatly appreciated.
Here is the code in routes.rb:
resources :companies do
match '/update_owner' => 'companies#update_owner', :as => :update_owner, :via => :post
match '/set_owner' => 'companies#set_owner', :as => :set_owner
end
you need to remove the ":method=>:put"
Your route is declared as a POST but you're doing a PUT in the form. Fix either the route or the form and you'll nail it.
Would leave this as a comment, but the fromatting gets jacked.
If you're not aware, you can also define those routes slightly differently, too:
resources :companies do
member do
post "update_owner"
get "set_owner"
end
end

What is wrong with my routes?

root :to => "index#home"
#public tattoo viewing and submissions
match "/submit" => "index#new", :via => :get
match "/tattoo" => "index#create", :via => :post
match "/tattoo/:id" => "index#show", :via => :get
match "/tagged" => "index#tagged", :via => :get
match "/tattoo/:id" => "index#destroy", :via => :delete
match "/tattoos" => "index#index", :via => :get
members section and its nested images
resources :members, :except => [:new, :create] do
resources :tattoos
end
Thats whats in my routes.rb file. They produce:
root /(.:format) {:controller=>"index", :action=>"home"}
submit GET /submit(.:format) {:controller=>"index", :action=>"new"}
tattoo POST /tattoo(.:format) {:controller=>"index", :action=>"create"}
GET /tattoo/:id(.:format) {:controller=>"index", :action=>"show"}
tagged GET /tagged(.:format) {:controller=>"index", :action=>"tagged"}
DELETE /tattoo/:id(.:format) {:controller=>"index", :action=>"destroy"}
tattoos GET /tattoos(.:format) {:controller=>"index", :action=>"index"}
members GET /members(.:format) {:action=>"index", :controller=>"members"}
edit_member GET /members/:id/edit(.:format) {:action=>"edit", :controller=>"members"}
member GET /members/:id(.:format) {:action=>"show", :controller=>"members"}
PUT /members/:id(.:format) {:action=>"update", :controller=>"members"}
DELETE /members/:id(.:format) {:action=>"destroy", :controller=>"members"}
But i have a problem. For some reason, when I try to go to mysite.com/submit
I used to get this error
No route matches {:controller=>"images"}
on
<%= form_for #tattoo, :html =>{:multipart => true} do |f| %>
but that has magically changed to:
undefined method `images_path'
on the same line.
when my controller has this:
indexcontroller
def new
#tattoo = Image.new
end
def create
#tattoo = Image.new(params[:image])
if #tattoo.save
flash[:success] = "Tattoo sent in for approval!"
redirect_to(images_path)
else
render :action => "new"
end
end
And then this link_to:
<%= link_to "Manage tattoos", member_tattoos_path() %>
give me this error:
No route matches {:controller=>"tattoos"}
I thought I was beginning to understand routes and had a decent grasp but I dont get whats going on!
You need to pass in a member object to edit_member_path.
<%= link_to "Edit profile", edit_member_path(#member) %>
edit_member_path should know the id of the member you want to edit. Please try
<%= link_to "Edit profile", edit_member_path(#member) %>
For No route matches {:controller=>"images"}; since the action image is not defined in your route, please try to stop and restart the server and check if there is any plugin like Paperclip in place.

Rails & Devise: Two-step confirmation route error

I'm trying to make a two-step confirmation like heroku using Devise.
My routes:
devise_for :user, :controllers => {:confirmations => "confirmations", :registrations => "registrations" }
put "confirm_account", :to => "confirmations#confirm_account"
Here's my alternate confirmation controller:
class ConfirmationsController < Devise::ConfirmationsController
def show
#account = User.find_by_confirmation_token(params[:confirmation_token])
if !#account.present?
render_with_scope :new
end
end
def confirm_account
#account = User.find(params[:account][:confirmation_token])
if #account.update_attributes(params[:account]) and #account.password_match?
#account = User.confirm_by_token(#account.confirmation_token)
set_flash_message :notice, :confirmed
sign_in_and_redirect("user", #account)
else
render :action => "show"
end
end
end
Here's my show.html.erb:
<%= form_for(resource, :as => resource_name, :url => confirm_account_path(resource_name)) do |f| %>
<%= f.label :email %>
<%= #account.email %>
<%= f.hidden_field :confirmation_token %>
<%= f.label :password %>
<%= f.password_field :password %>
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation %>
<%= f.submit 'Confirm Account' %>
<%= link_to 'Home', root_url %>
<%= render :partial => 'devise/shared/links' %>
<% end %>
When I click confirm after filling out the password (after clicking confirm in the confirmation email). I'm routed to /confirm_account.user That's pretty weird, right? What's going on to cause this problem?
Edit
rake routes returns:
new_user_session GET /user/sign_in(.:format) {:action=>"new", :controller=>"devise/sessions"}
user_session POST /user/sign_in(.:format) {:action=>"create", :controller=>"devise/sessions"}
destroy_user_session GET /user/sign_out(.:format) {:action=>"destroy", :controller=>"devise/sessions"}
user_password POST /user/password(.:format) {:action=>"create", :controller=>"devise/passwords"}
new_user_password GET /user/password/new(.:format) {:action=>"new", :controller=>"devise/passwords"}
edit_user_password GET /user/password/edit(.:format) {:action=>"edit", :controller=>"devise/passwords"}
PUT /user/password(.:format) {:action=>"update", :controller=>"devise/passwords"}
cancel_user_registration GET /user/cancel(.:format) {:action=>"cancel", :controller=>"registrations"}
user_registration POST /user(.:format) {:action=>"create", :controller=>"registrations"}
new_user_registration GET /user/sign_up(.:format) {:action=>"new", :controller=>"registrations"}
edit_user_registration GET /user/edit(.:format) {:action=>"edit", :controller=>"registrations"}
PUT /user(.:format) {:action=>"update", :controller=>"registrations"}
DELETE /user(.:format) {:action=>"destroy", :controller=>"registrations"}
user_confirmation POST /user/confirmation(.:format) {:action=>"create", :controller=>"confirmations"}
new_user_confirmation GET /user/confirmation/new(.:format) {:action=>"new", :controller=>"confirmations"}
GET /user/confirmation(.:format) {:action=>"show", :controller=>"confirmations"}
user_unlock POST /user/unlock(.:format) {:action=>"create", :controller=>"devise/unlocks"}
new_user_unlock GET /user/unlock/new(.:format) {:action=>"new", :controller=>"devise/unlocks"}
GET /user/unlock(.:format) {:action=>"show", :controller=>"devise/unlocks"}
confirm_account PUT /confirm_account(.:format) {:action=>"confirm_account", :controller=>"confirmations"}
editreject_admin GET /admin/:id/editreject(.:format) {:action=>"editreject", :controller=>"admin"}
reject_admin GET /admin/:id/reject(.:format) {:action=>"reject", :controller=>"admin"}
accept_admin GET /admin/:id/accept(.:format) {:action=>"accept", :controller=>"admin"}
entries_admin_index GET /admin/entries(.:format) {:action=>"entries", :controller=>"admin"}
preferences_admin_index GET /admin/preferences(.:format) {:action=>"preferences", :controller=>"admin"}
admin_index GET /admin(.:format) {:action=>"index", :controller=>"admin"}
about_entries GET /entries/about(.:format) {:action=>"about", :controller=>"entries"}
all_entries GET /entries/all(.:format) {:action=>"all", :controller=>"entries"}
myentries_entries GET /entries/myentries(.:format) {:action=>"myentries", :controller=>"entries"}
rate_entry GET /entries/:id/rate(.:format) {:action=>"rate", :controller=>"entries"}
submit_entry PUT /entries/:id/submit(.:format) {:action=>"submit", :controller=>"entries"}
entry_comments POST /entries/:entry_id/comments(.:format) {:action=>"create", :controller=>"comments"}
entry_comment DELETE /entries/:entry_id/comments/:id(.:format) {:action=>"destroy", :controller=>"comments"}
entries GET /entries(.:format) {:action=>"index", :controller=>"entries"}
POST /entries(.:format) {:action=>"create", :controller=>"entries"}
new_entry GET /entries/new(.:format) {:action=>"new", :controller=>"entries"}
edit_entry GET /entries/:id/edit(.:format) {:action=>"edit", :controller=>"entries"}
entry GET /entries/:id(.:format) {:action=>"show", :controller=>"entries"}
PUT /entries/:id(.:format) {:action=>"update", :controller=>"entries"}
DELETE /entries/:id(.:format) {:action=>"destroy", :controller=>"entries"}
/auth/:service/callback(.:format) {:controller=>"services", :action=>"create"}
services GET /services(.:format) {:action=>"index", :controller=>"services"}
POST /services(.:format) {:action=>"create", :controller=>"services"}
root /(.:format) {:controller=>"entries", :action=>"index"}
offline /offline(.:format) {:controller=>"application", :action=>"offline"}
Edit 3
In changing
devise_for :user, :controllers => {:confirmations => "confirmations", :registrations => "registrations" } do
match "/confirm_account", :to => "confirmations#confirm_account"
end
I'm receiving :
You have a nil object when you didn't
expect it! You might have expected an
instance of Array. The error occurred
while evaluating nil.[]
{"utf8"=>"✓",
"authenticity_token"=>"dsG/e8Tw2Oi6zEDb07R/L0yDOKFEFlse+IgLbfz3Lo0=",
"user"=>{"confirmation_token"=>"",
"password"=>"[FILTERED]",
"password_confirmation"=>"[FILTERED]"},
"commit"=>"Confirm Account"}
There's definitely a token in the url, though...This is actually going somewhere, though!
It looks to me like confirm_account_path doesn't exist?
If you didn't set up your routes manually, you can go ahead and set that in the config/routes.rb file, to confirmations#confirm_account.
Or, if you set Devise to use your ConfirmationsController, using new_user_confirmation_path may work too (and may not). Type rake routes in the console to see available routes. They should lead to the ConfirmationsController and the confirm_account action.
EDIT: Try editing your routes file as follows.
devise_for :user, :controllers => {:confirmations => "confirmations", :registrations => "registrations" } do
match "/confirm_account" => "confirmations#confirm_account"
end
I think the slash is important before confirm_account because it is now inside the devise_for block (which is identical to devise_scope). Otherwise it may go to users/confirm_account.
EDIT2: Use params[:user][:confirmation_token], not params[:account][:confirmation_token] in the controller. But currently it looks like the confirmation token is blank.

Rails 3 Form For Custom Action

I'm having trouble routing a form to a custom action in Rails 3. Here are my routes:
resources :photos do
resources :comments
collection do
get 'update_states'
end
member do
put 'upload'
end
end
Here's the form_for:
form_for #photo, :remote => true, :url => { :action => upload_photo_path(#photo) }, :html => { :multipart => :true, :method => 'put' } do |f|
And here's the error message:
No route matches {:action=>"/photos/42/upload", :controller=>"photos"}
... this is especially frustrating because "photos/:id/upload" is exactly the correct action for this form.
What am I missing?
EDITS - Here are the original Photo-related routes:
photo_comments GET /photos/:photo_id/comments(.:format) {:action=>"index", :controller=>"comments"}
POST /photos/:photo_id/comments(.:format) {:action=>"create", :controller=>"comments"}
new_photo_comment GET /photos/:photo_id/comments/new(.:format) {:action=>"new", :controller=>"comments"}
edit_photo_comment GET /photos/:photo_id/comments/:id/edit(.:format) {:action=>"edit", :controller=>"comments"}
photo_comment GET /photos/:photo_id/comments/:id(.:format) {:action=>"show", :controller=>"comments"}
PUT /photos/:photo_id/comments/:id(.:format) {:action=>"update", :controller=>"comments"}
DELETE /photos/:photo_id/comments/:id(.:format) {:action=>"destroy", :controller=>"comments"}
update_states_photos GET /photos/update_states(.:format) {:action=>"update_states", :controller=>"photos"}
upload_photo PUT /photos/:id/upload(.:format) {:action=>"upload", :controller=>"photos"}
photos GET /photos(.:format) {:action=>"index", :controller=>"photos"}
POST /photos(.:format) {:action=>"create", :controller=>"photos"}
new_photo GET /photos/new(.:format) {:action=>"new", :controller=>"photos"}
edit_photo GET /photos/:id/edit(.:format) {:action=>"edit", :controller=>"photos"}
photo GET /photos/:id(.:format) {:action=>"show", :controller=>"photos"}
PUT /photos/:id(.:format) {:action=>"update", :controller=>"photos"}
DELETE /photos/:id(.:format) {:action=>"destroy", :controller=>"photos"}
Here are the relevant routes when I changed the route to match 'upload':
photo_comments GET /photos/:photo_id/comments(.:format) {:action=>"index", :controller=>"comments"}
POST /photos/:photo_id/comments(.:format) {:action=>"create", :controller=>"comments"}
}
new_photo_comment GET /photos/:photo_id/comments/new(.:format) {:action=>"new", :controller=>"comments"}
edit_photo_comment GET /photos/:photo_id/comments/:id/edit(.:format) {:action=>"edit", :controller=>"comments"}
photo_comment GET /photos/:photo_id/comments/:id(.:format) {:action=>"show", :controller=>"comments"}
PUT /photos/:photo_id/comments/:id(.:format) {:action=>"update", :controller=>"comments"}
DELETE /photos/:photo_id/comments/:id(.:format) {:action=>"destroy", :controller=>"comments"}
update_states_photos GET /photos/update_states(.:format) {:action=>"update_states", :controller=>"photos"}
upload_photo /photos/:id/upload(.:format) {:action=>"upload", :controller=>"photos"}
photos GET /photos(.:format) {:action=>"index", :controller=>"photos"}
POST /photos(.:format) {:action=>"create", :controller=>"photos"}
new_photo GET /photos/new(.:format) {:action=>"new", :controller=>"photos"}
edit_photo GET /photos/:id/edit(.:format) {:action=>"edit", :controller=>"photos"}
photo GET /photos/:id(.:format) {:action=>"show", :controller=>"photos"}
PUT /photos/:id(.:format) {:action=>"update", :controller=>"photos"}
DELETE /photos/:id(.:format) {:action=>"destroy", :controller=>"photos"}
Unfortunately 'match' didn't work any better...
-- EDIT --
Just to confirm another scenario here... with this in the routes:
resources :photos do
resources :comments
collection do
get 'update_states'
end
member do
match 'upload'
end
end
and this in the view:
form_for #photo, :remote => true, :url => { :action => 'upload' }, :html => { :multipart => :true, :id => 'photo_upload' } do |f|
I still get:
No route matches {:action=>"upload", :controller=>"photos"}
What if you did just :url => upload_photo_path(#photo)?
It seems a little strange that you'd be uploading to a member though. Is this just a creation method (in which case you should just POST to the collection path)?
I had the same problem and finally worked through to a solution which I'm not sure was reached in the above case, since the original poster moved on to another approach.
My routes had
resources :members do
member do
get "invite"
post 'register'
end
end
And "rake routes" included
register_member POST /members/:id/register(.:format) {:protocol=>"http", :action=>"register", :controller=>"members"}
Yet I kept getting the error
Started POST "/members/149/register" for 127.0.0.1 at 2012-04-13 13:18:35 -0700
ActionController::RoutingError (No route matches "/members/149/register"):
Rendered /Users/lisa/.rvm/gems/ruby-1.9.2-p180#stv/gems/actionpack-3.0.9/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (1.1ms)
and the problem was limited only to the form generated by Rails according to the below form_for (note I confirmed this using HTTP client to manually POST to the URL and saw it was finding the route)
<%= form_for #account, :url => register_member_path(#account.id) do |account_form| %>
...
I checked the method, I checked the path, everything looked good. What I finally noticed, scouring the generated form line by line:
<form accept-charset="UTF-8" action="/members/149/register" class="edit_member" id="edit_member_149" method="post">
<div style="margin:0;padding:0;display:inline">
<input name="utf8" type="hidden" value="✓" />
<input name="_method" type="hidden" value="put" />
<input name="authenticity_token" type="hidden" value="74pkMgRHfdowSfzjJGMILkAsivVNrJZ0iWYXRUgxyF0=" />
</div>
...
Notice the hidden input name="_method". I wish the fact that Rails was interpreting this as a PUT had shown up in the logs, that would have made my debugging a lot faster. I fixed it by telling the form explicitly to use the POST method, which of course it was already, but telling it that removed the hidden _method override. I assume there's some facet about #account which triggered Rails to use the _method parameter, but #account should be an existing record.
Your url parameter should be
:url => { :action => "upload" }
(Original reply)
I would bet it's because your route expects a PUT and your form is sending a POST (probably because #photo = Photo.new). You have several options:
Change your route to post 'upload'
Create your form with form_for #photo, :as => :post with the rest of your arguments
Make sure #photo is an existing record (e.g. by calling create instead of new)
The most appropriate choice is probably one of the first 2.

Resources