Ruby On Rails tips and tricks

 

Ruby on Rails is a good technology, but like all rapidly expanding technologies, its documentation efforts struggle to keep up. I discovered that every time I got stuck, Google does not help because most hits take you to the main documentation web site, or one of its excerpts elsewhere. The main documentation website is mostly the generated output of Rdoc, so sometimes it is useful, sometimes it takes a long time to find the information you need. I am attempting to list the useful things I found along the way, but am trying to make it more search friendly by listing it by topics.

Hot loading of classes within WEBrick

  • All classes in the following directories are hot loaded and your changes will be reflected immediately upon browser reload:
    • app/controllers
    • app/models
    • app/views
  • All classes in the following directories are not hot loaded and require a restart of WEBrick:
    • app/helpers
    • all classes from your Rails Gems installation
    • all Ruby core classes
    • all files at the same level as the app directory e.g config, script, lib, components etc.

Actionable methods in the Controllers

By default, all the public methods in all the classes in the app/controllers directory are actionable method i.e. if you have a file called app/controllers/foo_controller.rb with the contents:

class FooController < ApplicationController
    def bar
        ...
    end

end

Then the you will be able to invoke the 'bar' method by doing http://localhost:3000/foo/bar. This is not a good thing if the method is declared for use by the views and are not intended to be mapped into an action. In order to prevent the method 'bar' from being mapped into an action, insert the following snippet of code:

class FooController < ApplicationController
    def bar
        ...
    end
    class << self
        def hidden_actions
            super + [ "bar" ]
        end
    end

end
OR replace the red block with

    def self.action_methods
        [ "bar" ]
    end
OR
class FooController < ApplicationController
    hide_action :bar

   def bar
        ...
    end
end

I prefere the first approach because you can specify multiple methods in one go, although the second approach allows the flexibility of maybe putting conditions around the methods you want to expose. For example, if the user is authenticated, you might return different actions than when he is not. The third approach is the standard Rails pattern, I think, although you will have to do each for each action you want to hide, and this can not be done on the fly either.

You must also be careful that any public method you declare in the app/controllers/application.rb will be mapped into actions too, so you might need to add this code into app/controllers/application.rb too:

class ApplicationController < ActionController::Base
    def bar
        ...
    end
    class << self
        def hidden_actions
            super + ApplicationController.public_instance_methods
        end
    end
end


Post a whole form contents back in an AJAX call

Rails has a ready made call which facilitates passing the contents of all the elements in a form in an AJAX call with the call form_remote_tag

form_remote_tag :html => { :action => url_for(:controller => "some", :action => "place") }

However, the problem with the above method is you can not pass the name of the form into the call, so if you have multiple forms on your page, this is the way to do it:

<form name='logon' id='logon'>
    <input name='name' />
    <input type='password' name='pass' />
    <%= link_to_remote "Log me in",
        :url => { :action => 'authenticate' },
        :with => "Form.serialize($('logon'))",
    %>
</form>
 

ActionMailer throws an error with "No rhtml, rxml, or delegate template found  for signup_notification"

Let's say you have a file called app/models/application_mailer.rb which contains

class ApplicationyMailer < ActionMailer::Base
    def signup_notification(u)
       @recipients = u.name
       @subject = "Validation request"
       @from = 'me@mydomain.com'
    end
end

Three possible reasons for this error:

  1. You have not defined the attribute ActionMailer::Base.template_root in either your code or in you configuration. This declaration can be added to the app/config/environment.rb file (do not forget to restart WEBrick to pick up the change)
  2. You have not declared the @body attribute in the  signup_notification method of your application mailer. If @body is declared, the rendering template is not used
  3. You have not created the file ActionMailer::Base.template_root + "/application_mailer/signup_notification.rhtml"