Action Controller error. Url Generation error. No route matches - ruby-on-rails

I'm working through the "Ruby on rails 3 essential training" on lynda.com and am having an issue while generating my server. So far I have a subjects_controller.rb, linked to my views folder, to the file list.html.erb. My error when trying to start the server is:
No route matches {:action=>"show", :controller="subjects", :id=>1}
In my list.html.erb file I have written the code:
<td class="actions">
<%= link_to("Show", {:action => 'show', :id => subject.id}, :class => 'action show') %>
<%= link_to("Edit", '#', :class => 'action edit') %>
<%= link_to("Delete", '#', :class => 'action delete') %>
</td>
My subjects_controller.rb looks like:
class SubjectsController < ApplicationController
def list
#subjects = Subject.order("subjects.position ASC")
end
end
I have double checked to make sure I have everything written the same as the instructor but there seems to be a missing link. Any ideas? If I totally cut out the action:
<%= link_to("Show", {:action => 'show', :id => subject.id}, :class => 'action show') %>
Then the server starts up. There must be a problem here but I'm not sure what it is. Also when the instructor inputs link_to on his text editor, the txt turns a different color and mine does not. Same thing with his "#" instance variable. Mine doesn't change color. Not sure if this means anything either. Thanks for any input!
Here is my config/routes.rb file:
Rails.application.routes.draw do
root :to => "demo#index"
get 'demo/index'
get 'demo/hello'
get 'demo/other_hello'
get 'subjects/list'
end

Short version: The error message is telling you exactly what is wrong. You have no route that matches, because while your action is named list, your link specifies :action => 'show'.
Longer version: The second argument to the link_to helper is supposed to tell Rails what URL to generate for the link, usually by specifying one of your routes by name, but sometimes (as in this case), by specifying the action (and optionally the controller). You're specifying the action show. The subjects controller is implied. Therefore, Rails is trying to find a route (in the ones defined in your routes.rb) that GETs the SubjectsController#show action. However, as you can see from your routes.rb, you only define one route on the SubjectsController, and that's list.
If you're ever confused about what routes you have or what their names are, you can use the rake routes task to list them all out in a nice readable format.
Edit to respond to followup question:
The instructor is telling me that when you generate a controller and
action that its supposed to add a route to the routes.rb folder. This
worked for me earlier but when creating these actions that I'm having
trouble with now, it didn't generate anything in the routes.rb folder.
Do you know why that is?
When your instructor says 'generate', they probably mean 'use the rails generate command'. When you use the generator to create a controller and specify the actions in it, the it will also add those actions to the routes file.
If, on the other hand, you write the action into an existing controller (including using the generator for the controller but not specifying actions), or create the controller file yourself, you'll have to update the routes file manually. If you are using the generator and specifying actions and aren't getting updated routes, I'm not sure what's going on.
Personally, I prefer to write my routes by hand anyway - the generator often doesn't get them exactly right.

Related

Move one page to another in Ruby on rails?

In my rails project there is a controller and view named "Welcome/index" where index is an action and another one named "home/page" . As i set root"home#page" as my root page. Now i want to transfer from "page.html.erb" into "index.html.erb" . How can i do that. And the code i written is below.Do i have to enter some thing in my controller class. please suggest.
these are the links that i tried. (How to create an anchor and redirect to this specific anchor in Ruby on Rails)
<a rel="nofollow" href="index.html.erb">Transfer to index</a>
You are not supposed to link to .html.erb files, you should link to the methods (not exactly the name of the method, but the name of the route) of a controller.
I strongly encourage you to review the ruby on rails MVC principles. You can read about routing and linking aswell.
Responding to your question, check out the command "rake routes". It will list the defined routes of your app and helps you to use them.
Try to replace your code by this:
<%= link_to 'welcome', welcome_path %>
<%= link_to "Link", controller:"controllername" %>
is the code you should use
You need to make sure a named route is defined for welcome/index and then can use the Rails helper link_to to automatically build your link for you in the view.
In routes.rb:
match '/welcome' => 'welcome#index', :as => :welcome
In your page.html.erb view:
<%= link_to 'Go to Welcome Page', welcome_path %>
If you want go for index action of Welcome controller then you can use:
<%= link_to "Transfer to index", welcome_path %>
Check the rake routes for path.
Plese refer link

How to create an arbitrary link in Rails?

link_to and helpers use the names of my models and their IDs while I want to have a couple of different, arbitrary, variables in my link. I have no problems to route them, I actually keep the default routing as well, but I suddenly stuck that I cannot easily generate an arbitrary link. For instance I want to have a link like ":name_of_board/:post_number", where :name_of_board and :post_number are variables set by me, and when I use link_to I get instead "posts/:id", where "posts" it's the name of the controller. While it's not hard to use an arbitrary id like
link_to 'Reply', :controller => "posts", :action => "show", :id => number
I cannot get how I can get rid of "posts". So, is there an easy way to generate a link by variables or to convert a string into link? Sure, I can add other queries to the line above, but it will make the link even more ugly, like "posts/:id?name_of_board=:name_of_board".
You can create additional routes for your posts resource in your routes.rb, or make standalone named routes:
resources :posts do
get ':name_of_board/:id' => 'posts#show', as: :with_name_of_board
end
get ':name_of_board/:id' => 'posts#show', as: :board
Now this
#name_of_board = "foo"
#post_id = 5
link_to 'Reply', posts_with_name_of_board_path(#name_of_board, #post_id)
link_to 'Reply', board_path(#name_of_board, #post_id)
would link to /posts/foo/5 and /foo/5 respectively.
You should first edit your route entry, for example a classic show route is the follow:
get "post/:id" => "post#show", :as => :post
# + patch, put, delete have the same link but with different method
And you can call it with the following helper
link_to "Show the post", post_path(:id => #post.id)
You can edit or create a new entry in the routes, applying the parameters you want to use, e.g.:
get "post/:id/:my_platform" => "post#show", :as => :post_custom
Then
link_to "Show the post with custom", post_custom_path(:id => #post.id, :my_platform => "var")
Finally, the link generated for this last entry is for example:
"/post/3/var"
Even in this situation, you can add some other params not defined in the routes, e.g.:
link_to "Show post with params", post_custom_path(:id => #post.id, :my_platform => "var", :params1 => "var1", :params2 => "var2")
=> "/post/3/var?params1=var1&params2=var2"
RoR match your variable defined in the routes when you render a link (remember that these variables are mandatory), but you can ever add other vars that come at the end of the url ("?...&..")

Rails: Generated URL has double backslash

In my Rails project, in my index view, I have a link
<%= link_to 'Show all posts', show_all_path %>
In routes.rb, I have a route:
match "show_all" => "Posts#show_all"
When I click on that link, it goes from
http://<domain name>/my_rails_project
to
http://<domain name>/my_rails_project//show_all
It works fine, but I'm wondering why there are two backslashes in front of show_all instead of one. And can I make it so that only one backslash appear?
I think your route needs more information:
`match "/:project_name/show_all" => "posts#show_all", :as => "show_all"
In your view:
link_to 'Show all posts', show_all_path(#project.name)
This assumes you have a #project variable in the page you're viewing.
try use get
get "show_all", :to => 'posts#show_all', as: 'show_all'

Ruby on Rails: How to print out a string and where does it display at?

I know this is a trivial question. But I have search all over google but cannot find a simple answer to this question.
Basically I have a line that says <%= link_to 'Run it', :method => 'doIt' %> in the view, then in the corresponding controller, I have the doIt method as follows:
def doIt
puts "Just do it"
end
I just want to check that if i click on Run it, it will output the string "Just do it". I ran this on localhost and there is no errors, but I can't find the output "Just do it" anywhere. It is not displayed in the rails console or rails server log. I just want to know where does puts output the string to , where to find it ?
Round 2: So this is what I tried ....
Added this line in the index.html.erb (which is the root)
<%= link_to 'Run it', :method => 'do_it' %>
and in the url, it is just basically http://localhost:3000/ (since i route controller#index as root)
The display is just an underlined 'Run it' that links to 'do_it' method in the controller.
In the controller, i include this method
def do_it
logger.debug "Just do it"
end
when i click on 'Run it', the url change to http://localhost:3000/gollum_starters?method=do_it and in the development.log, the following is written into it:
Started GET "/gollum_starters?method=do_it" for 127.0.0.1 at 2011-08-25 15:27:49 -0700
Processing by GollumStartersController#index as HTML
Parameters: {"method"=>"do_it"}
[1m[35mGollumStarter Load (0.3ms)[0m SELECT "gollum_starters".* FROM "gollum_starters"
Rendered gollum_starters/index.html.erb within layouts/application (3.6ms)
Completed 200 OK in 16ms (Views: 7.7ms | ActiveRecord: 0.3ms)
Additionally, i tried all the logger.error/info/fatal/etc ... and Rails.logger.error/info/fatal/etc, all did not print out the line "Just do it" in the development log
#Paul: I did not touch the environment folder or file, i assume by default when a new rails app is created, it is in development ?
#Maz: Yes you are right, I am just trying to test if the do_it method is getting called. To do that, I just want to print something out in the controller. Can't think of any way simpler that just print a string out, but this problem is making me miserable. I am just using textmate, no IDE.
Round 3:
#Paul thx alot, but i encountered error
My routes files is now:
resources :gollum_starters
root :to => "gollum_starters#index"
match 'gollum_starters/do_it' => 'gollum_starters#do_it', :as => 'do_it'
My index.html.erb is now:
<%= link_to "Do it", do_it_path %>
My gollum_starters_controller.rb
def do_it
logger.debug 'Just do it'
end
I am getting this error:
Couldn't find GollumStarter with ID=do_it
the error is in here, 2nd line:
def show
#gollum_starter = GollumStarter.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #gollum_starter }
end
end
I wonder why does it route to show ? When i click do_it, it actually goes to localhost:3000/gollum_starters/do_it which is correct, but apparently the error points to the show method ?
Round 4:
#Paul, i shifted resources :gollum_starters down:
root :to => "gollum_starters#index"
match 'gollum_starters/do_it' => 'gollum_starters#do_it', :as => 'do_it'
resources :gollum_starters
but got this error (omg i wanna kill myself),
Template is missing
Missing template gollum_starters/do_it with {:handlers=>[:erb, :rjs,
:builder, :rhtml, :rxml], :formats=>[:html], :locale=>[:en, :en]} in
view paths "~/project_name/app/views"
:/
---------- Answer to Round 4 ------------
Basically as the error explains, there is no template(i.e a webpage) to show hence error thrown. The solution is to add a redirect_to , in this case I redirect to root_url.
def do_it
logger.debug 'Just do it'
redirect_to(root_url)
end
Everything works now, "Just do it" finally outputs to development.log and the rails server console.
Thank you Maz and Paul and Andrew for helping me out. Learn a lot.
That link_to does not do what you think it does the value for :method is referring to the HTTP verbs.
Taken from the docs for ActionView::Helpers::UrlHelper
:method - Symbol of HTTP verb. Supported verbs are :post, :get, :delete and :put. By default it will be :post.
You would need to define a route in your routes.rb file that uses your method
# The order of routes is important as the first matched will be used
# therefore the match needs to be above 'resources :controller'
match 'controller/do_it' => 'controller#do_it', :as => 'do_it'
resources :gollum_starters # <--- This needs to be below the match or this will catch first
The controller/do_it is the route to be matched
The controller#do_it is the controller followed by the action to be used (separated by #)
The value for :as creates the path do_it_path that can be used in your link_to
Your link_to may look something like
<%= link_to "Do it", do_it_path %>
And to complete the lifecycle of a request you will need to add a view to be rendered
app/views/gollum_startes/do_it.html.erb # <-- Add file
Summary
Doing all of this creates a bit of a mess just to print something out to the logs, but it should help you understand the whole lifecycle a bit better now. Plus this answers serves as a document to help you rewind this mess.
You are not understanding what "method" means in the context of a link.
The "method" here refers to the request method, which means the kind of request you are asking the browser to make. From the perspective of a RESTful application like Rails there are four relevant request types: GET, POST, PUT, and DELETE. These request types affect how the controller responds to a request.
GET => INDEX or SHOW
POST => CREATE
PUT => UPDATE
DELETE => DESTROY
There are two other "standard" rails actions, NEW and EDIT. These are GET requests to present an interface to the user. NEW gives you a form to POST (CREATE) a new object, and EDIT gives you a form to PUT (UPDATE) and existing one.
See the rails guide for more on how HTTP Verbs relate to CRUD operations.
The important, basic thing to understand is that links, by default, are GET requests, and forms, by default, are POST requests.
So, when your link looks like this:
<%= link_to 'Run it', :method => 'do_it' %>
...it is bogus. There is no such HTTP method as "do_it", so you're not triggering anything. Because there is no such method, Rails actually passes this on as a parameter of the URL. Hence if you click that you should see your url bar now says ?method=do_it at the end.
There are several problems with what you're trying to do. First of all, the link_to helper expects at least two arguments: 1, the text for the link, and 2 the HREF for the link. So, you really need to use:
link_to 'Run it', url
Second, you need to know what URL to pass to get your controller action.
Please be familiar with the following rails convention: When referring to a controller action you can abbreviate it using the form: controller_name#controller_action. e.g. pages#show or articles#index.
Assuming your controller is called ExamplesController, you can manually trigger the seven standard controller actions as follows:
link_to 'examples#index', '/examples'
link_to 'examples#show', '/examples/123' # 123 is the id of a specific example
link_to 'examples#new', '/examples/new'
link_to 'examples#create', '/examples', :method => :post
link_to 'examples#edit', '/examples/123/edit'
link_to 'examples#update', '/examples/123', :method => :put
link_to 'examples#destroy', '/examples/123', :method => :delete
Note that in the above, INDEX, SHOW, NEW, and EDIT are all GET requests. You could specify :method => :get but that is unnecessary
To abstract this away and take care of assigning the ID when required Rails provides path helpers.
So, to repeat the above using the path helpers you could use:
link_to 'examples#index', examples_path
link_to 'examples#show', example_path( #example )
link_to 'examples#new', new_example_path
link_to 'examples#create', examples_path, :method => :post
link_to 'examples#edit', edit_example_path( #example )
link_to 'examples#update', example_path( #example ), :method => :put
link_to 'examples#destroy', example_path( #example ), :method => :delete
Now, you get these path helpers from the router, and they are defined in your routes.rb file. Within that file if you define:
resources :examples
...then you will get all the path_helpers above.
If you are using a normal RESTful controller and you want to add a custom action, then you need to make one decision: does the action operate on the entire set of objects handled by that controller (like index) or just a single specific one (like show). The reason this is important is this tells the router whether the new action you're defining needs to receive a record ID as part of the request.
If you want to act on the entire collection of objects, you define:
resources :examples do
collection do
get 'do_it'
end
end
If you want to act on just a single member of the collection you define:
resources :examples do
member do
get 'do_it'
end
end
Where I wrote 'get' in the examples above you can use any of the four verbs -- GET is normally what you do if you want to show a page, and POST is normally what I'd use if you're submitting a form. You can also write this shorthand like so:
resources :examples do
get 'do_it', :on => :collection
post 'something', :on => :member
end
For more on defining custom controller actions, see the rails guide.
Now that you've defined a route, you should run rake routes in terminal to see the name of the new path helper. Let's assume you added do_it as a collection method, your path helper would be: do_it_examples_path.
Now then, back to your link, if you put:
<%= link_to 'Do it.', do_it_examples_path %>
... then you would trigger the do_it action. When the action is triggered your puts should normally render to the server log (assuming you're running rails s in a terminal window you should see it right after started GET on examples#do_it...).
Now, in the browser you would get a missing template error as a GET request is going to expect to render a view, but that's a subject for another question. Basically, now you should understand what the controller actions are, how you get to them. If you want to learn more about what to do with your controller action, see the guide :)
I hope you understand what's going on now. Feel free to ask questions.
You want to use the Rails logging mechanism:
http://guides.rubyonrails.org/debugging_rails_applications.html#sending-messages
This means that even if you don't launch the server using rails s the output will still go to the right place.

Calling a controller action with link_to

After playing around with links in Rails for a view hours i've managed to actually get a link to invoke a method in my controller. But i still don't understand why all my other attempts failed. Im hoping you could help me out with that.
I have the scaffold "Cars". When in the show view for a car, id like to click a link that invokes the method "drive" in my Car controller.
This WORKS: <%= link_to "Drive", drive_car_path(#car) %>
It seems this only works if i have this is my routes.rb:
resources :cars do
member do
get 'drive'
end
end
Why does <%= link_to "Drive", car_path, :method => :drive %> not work?
Do I need to put a GET in the routes.rb file for every method I create in my controller?
I can't seem to find any sites explain how to use links together with routes. They only seem to come separate. Do you guys have any easily understandable tutorials on this?
Try link_to "Drive", :controller => "car", :action => "drive"
Also, method is for choosing the HTTP method (GET, POST, ...). It's not method as in routine.
Be sure to check out Rails Routing from the Outside In and The Lowdown on Routes in Rails 3, they're both awesome resources.

Resources