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

36,043

Solution 1

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.

Solution 2

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.

Share:
36,043
John Lee
Author by

John Lee

Troublemaker

Updated on July 09, 2022

Comments

  • John Lee
    John Lee almost 2 years

    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.

  • John Lee
    John Lee over 12 years
    so basically 'puts' is ruby specific. It does not work on ror even though I use it in a .rb file ?
  • Maz
    Maz over 12 years
    no, puts sends output to STDOUT, most of the times STDOUT is the terminal, but sometimes it's not. In this case it's not. puts still works, it just doesn't output content to where you want it outputted. The text that scrolls by in the console is also written to the development log. It is to this log, not to the terminal, which you want to write to.
  • John Lee
    John Lee over 12 years
    Thx for the explanation. I have tried all of this logger.(debug|info|warn|error|fatal) and check the development log for it, but it still does not write to the log. I even did ctrl-shift-f on my project folder and can't find it logged anywhere except in the controller where i did logger.debug "Just do it". So basically i click on "Run it", and the method do_it (changed from doIt to follow rails convention) is called, and i did logger.debug/info/etc ... but i check the development log and "Just do it" is not written to it.
  • John Lee
    John Lee over 12 years
    Can someone please help me ? THis is frustrating, java has a system.out.println, javascript has a console.log, prints things out easily, good for debugging, how come it's so hard to print things out on rails ?
  • Paul.s
    Paul.s over 12 years
    Can you show the code you tried for logger? What environment are running under e.g. development?
  • Maz
    Maz over 12 years
    you say you click on "Run It" are you using an IDE? try also looking at the development.log file itself. Also, are you sure the method is actually getting called? It seems from your example that you are trying to test whether the method is getting called.
  • John Lee
    John Lee over 12 years
    I have edited my first post on top to explain what i did in detail. See under 'Round 2'
  • John Lee
    John Lee over 12 years
    Hi Paul, this makes sense, but i got an error, see my post on Round 3
  • John Lee
    John Lee over 12 years
    Sorry to trouble you. Got another missing template error, see Round 4.
  • John Lee
    John Lee over 12 years
    Ok i realize the problem, there was no template to show, so I had to manually redirect_to something, and I redirect to root
  • Andrew
    Andrew over 12 years
    The logger is not the problem in this case -- his link isn't going anywhere because the method argument isn't valid and is being misunderstood.