Pothibo

Customize Rails view & controller with Railtie

All the posts I could find about railtie explained pretty much the same thing and I wanted to know how to interact with ActionController & ActionView with railtie. Unfortunately, I couldn't find much information about that. I thought it would be a good idea to put my findings into writing so I don't forget them and it also might be useful for someone out there.

Create a gem

It's easier to start developing if you create a gem and start playing with your railtie within the dummy app created for you with that gem.

$ rails plugin new my_gem

Dummy application already has your gem loaded

If you have a look at my_gem/test/dummy/config/application.rb, you will see that it manually requires your gem already. That means you can test you railtie by running rails s from the dummy/ folder. Create a controller in the dummy application

$ cd my_gem/test/dummy/ $ rails g controller post

And now create a new resources :post inside route.rb.

This railtie aims at providing extra functionalities to ActionView and ActionController. I'll use the new posts_controller and it's view to make sure everything works.

ActiveSupport: Where everything starts

There is an initialization process that you can read about but it's a bit hard to read. What you need to know is that before models, controllers & views are loaded and configured, ActiveSupport is loaded first. Railtie is defined there so it makes sense that this is the first thing to be loaded.

You have probably seen already the initializer method that railtie has. From there, you can inject module to any other component using the on_load method ActiveSupport provides. In my case, I want to include a module in ActionView and another module in ActionController.

my_gem/railtie.rb
module MyGem class Railtie > ::Rails::Railtie initializer "my_gem.configure_view_controller" do |app| ActiveSupport.on_load :action_view do include MyGem::ActionView::Helpers end ActiveSupport.on_load :action_controller do include MyGem::ActionController::Filters end end end end

For the sake of this post, I will ignore the controller and focus on the ActionView inclusion.

my_gem/action_view/helpers.rb
module MyGem::ActionView::Helpers def new_method_from_gem "Hello World!" end end

Don't forget to require your files in my_gem/my_gem.rb!

require 'my_gem/action_controller/filters' require 'my_gem/action_view/helpers' require 'my_gem/railtie' if defined?(Rails)

Test our method

Remember that we created a controller named post. Let's try our new method in post#index.

dummy/app/views/posts/index.html.erb
<%= new_method_from_gem %>

Accessing localhost:3000/posts/index should now print "Hello World!" in the browser. If you declare class inside your new helper module, you might experience missing methods or context error (output buffer error).

Let's fix that, shall we?

ActionView::Helpers && ActionView::Context

If you want to use link_to, content_tag, etc. method on a class inside your module, you will need to have those 2 modules included. Remember that include only works on instance methods, if you want to use those helpers methods on a class method, you need to extend your module with the 2 ActionView modules.

my_gem/action_view/helpers.rb
module MyGem::ActionView::Helpers class MyGemClass include ActionView::Helpers include ActionView::Context extend ActionView::Helpers extend ActionView::Context def self.status # Possible because of extend content_tag :span, "Published" end def author # Possible because of include content_tag :span, "Me!" end end end

If you liked this post, you should follow me on Twitter.

Get more ideas like this to your inbox

You will never receive spam, ever.