Creating a rails 3 engine / plugin / gem

Keith Schacht| September 12th, 2010
Post to Twitter

One of the things I was most looking forward to in rails 3 was the plugin / engine architecture. Recently, I sat down to figure out how to create my first engine and package it up as a gem and it took me awhile of time just to get the structure of the engine setup. It’s missing a lot of the “rails” you get in a normal rails app.

In it’s simplest form engines are quite easy, however for a full-featured engine (such as creating a forum) there are a lot of extras that you’re going to want. These are the things I spent time figuring out that I’ve packaged up into an easy starting point:

  • Namespacing models & controllers so they don’t collide with those in the main app
  • Creating a global layout within your engine that gets nested within your application layout
  • Generating migrations from your engine
  • Creating an “acts_as_[plugin]” declaration for use inside your main app’s models
  • Easy plugin configuration file editable from main app directory
  • Rake tasks within engine
  • Writing tests for models complete with fixtures
  • Serving static assets within engine
  • Packaging and distributing as a gem

Code is here – I’ve created an engine stub that has all the things setup for you already. I want to see a lot more rails 3 engines get created, I hope this helps! I’d love to hear feedback from you if you try it out.

Here’s how you get ready to create your first gem by using this starting point:

  • git clone http://github.com/krschacht/rails_3_engine_demo.git
  • cd rails_3_engine_demo
  • [edit test/database.yml]
  • rake test (this will initialize your test database and run the basic test suite)

Now, create a plain rails app and set it up to use your engine. FYI: even though the engine’s directory is ‘rails_3_engine_demo’, internally the engine is named ‘cheese’

  • cd .. [ this is to take you outside the 'rails_3_engine_demo' directory that was created above' ]
  • rails new demo_app_to_use_gem -d mysql
  • cd demo_app_to_use_gem
  • [edit config/database.yml]
  • [edit Gemfile, add line: ] gem ‘cheese’, :path => “../rails_3_engine_demo”
  • rails generate cheese
  • [examine config/initializers/cheese.rb to see basic config parameters]
  • rake db:create
  • rake db:migrate (one of the migrations that you’ll see run came from the engine)

You have now setup a empty rails app that utilizes your engine. To test out the functionality, startup the demo app’s webserver:

  • rails server
  • Then visit: http://localhost:3000/cheese (this is a controller included within the engine)
  • rake cheese:report (this is a a rake task that is included inside the engine)

Lastly, let’s package up your engine as a real gem. You’ll need Jeweler installed for this:

  • cd rails_3_engine_demo
  • sudo gem install jeweler
  • rake gemspec
  • rake build
  • rake install (you have now installed your engine as a gem locally)
  • [ At this point if you wanted your demo app to use your installed gem, edit the Gemfile in your demo app and remove the 'path' option from your gem line. It should look like this: ] gem ‘cheese’
  • rake gemcutter:release (this pushes your gem up to Gemcutter, a public gem repository)

Now you’re ready to start customizing this engine for your own purposes. Do a global find in your engine directory and replace every instance of “cheese” and “Cheese” with your engine name (be sure to preserve capitalization). Likewise, rename every directory and file that’s named “cheese” with your engine name. I should really automate this but I haven’t figured out how to create a rake task that I can run from within the engine directory itself.

BTW, the following resources were helpful in figuring all this out:

The Modest Rubyist, Jon Swope, Rails Dispatch

44 Responses to “Creating a rails 3 engine / plugin / gem”

  1. Rodrigo Dellacqua Says:
    September 22nd, 2010 at 2:13 pm

    You got a typo there,

    rails (new) demo_app_to_use_gem -D mysql

  2. Frank Says:
    September 27th, 2010 at 9:06 am

    Hi, when I run in production mode the static assets aren’t served properly. The files a empty. Have you experienced the same problem? Do you have a solution?

  3. Boris Says:
    September 29th, 2010 at 6:37 am

    Thanks for the post, just what I was looking for!

    I had a few problems though. For one, I couldn’t run the tests with “rake test” – I always get:

    no such file to load — app/models/cheese/widget.rb (LoadError)

    …even though the path seems to be correct – not sure what’s wrong here. Also using

    gem ‘cheese’, :path => “../cheese”

    didn’t work since there is no directory cheese, I had to use:

    gem ‘cheese’, :path => “../”

  4. Keith Schacht Says:
    September 29th, 2010 at 9:00 pm

    @Rodrigo: I fixed the typo, thanks for catching

    @Boris: Sorry, I had another typo. It should be: gem ‘cheese’, :path => ‘../rails_3_engine_demo’

    Basically, the demo rails app needs to point to the root directory where you have your engine.

    @Frank: Does it work locally when your Gemfile points to the directory? Does it work locally when your Gemfile refers to your locally installed gem?

    I did have that issue at one time too. My issue was that it worked when my Gemspec pointing to my local directory, but it failed once it’s compiled into an actual gem (both locally and in production). My solution was in the engine’s Rakefile, I added this line:

    gem.files = Dir["{lib}/**/*", "{app}/**/*", "{public}/**/*", "{config}/**/*"]

    Notice the “public” in there, this makes sure that the gem includes the public directory.

    However, all this should already be included in my demo above so maybe you’ve encountered a new issue. I haven’t been able to duplicate though.

  5. dave Says:
    October 1st, 2010 at 9:42 am

    Thanks! Spent a few hours hunting down a clear presentation on creating Rails 3 engines. Just what I needed!

  6. Ben Says:
    October 6th, 2010 at 12:42 pm

    Thanks a lot for your work!

  7. Yuriy Says:
    October 8th, 2010 at 12:42 pm

    Good job Keith!

    But you have mistake here:

    # rails db:create
    # rails db:migrate (one of the migrations that you’ll see run came from the engine)

    should be:
    # rake db:create
    # rake db:migrate (one of the migrations that you’ll see run came from the engine)

    :)

  8. Keith Schacht Says:
    October 8th, 2010 at 4:07 pm

    Ah, thanks for catching that, I just fixed it above.

  9. Andy Pearson Says:
    November 17th, 2010 at 2:40 am

    First off – thanks for releasing this! I’ve been putting together a gem of a custom CMS and this has been my one stop for finding out how to put things together.

    One thing I’m coming up against – is there anyway to extend the functionality of the host apps ApplicationController? I’ve tired a few different things but nothing seems to work. Thinking that would be a great thing to add to this demo!

    Thanks again!

  10. Keith Schacht Says:
    November 19th, 2010 at 11:48 am

    Andy, good question! I actually haven’t figured that out yet. I should look into that. I did include a way to create Application Helpers within the engine, maybe that would work for your purposes?

    If you figure out the Application Controller, can you fork my code and ping me with the commit? I’d love to pull that back in for other people.

  11. Mike Mondragon Says:
    December 15th, 2010 at 4:04 pm

    Awesome write up on Engines, I will definitely use your experience on an upcoming project. Here’s the clone command for the public:

    git clone http://github.com/krschacht/rails_3_engine_demo.git

    Also, the version I checked out didn’t have a plural cheese report, just singular

    rake cheese:report

  12. Keith Schacht Says:
    December 23rd, 2010 at 10:27 am

    Thanks Mike, I just corrected those two typos.

  13. Joel Dezenzio Says:
    December 29th, 2010 at 7:21 am

    Hi Keith, you might want to update the test_helper.rb file to account for port configurations with mysql as some people use separate ports when developing. I’ve modified the test_helper.rb file to fix the path to widget.rb (someone above complained about receiving an error so this will fix it so that all OS environments find the right path). See the gist below:

    https://gist.github.com/758616

  14. Joel Dezenzio Says:
    December 29th, 2010 at 7:34 am

    Hi Keith, also, how are you handling engines that will require gems or plugins? For instance, I’m planning on converting a forum software (which is very deeply coded) to an engine and I believe that any gems/plugin requirements should be maintained in the engine since they are essentially separate from the application. Thoughts?

  15. Joel Dezenzio Says:
    December 29th, 2010 at 8:02 am

    Hi Keith, third post of the day for me!

    I corrected your engine routing as the map is deprecated in rails 3.1 upcoming and so is name_prefix. See the gist for the corrected version.

    https://gist.github.com/758668

  16. Joel Dezenzio Says:
    December 29th, 2010 at 11:14 am

    I corrected my gist above to also include scope as path_prefix does not work when used with resources. To make things easier, you should probably surround all of the resources you want to use with one dry scope…

    scope mount_at do

    .. your resources
    .. more resources

    end

  17. Joel Dezenzio Says:
    December 29th, 2010 at 11:38 am

    I created a gist that shows a full fledged example of rails 3.0.3 routing from the inside and out using your rails engine.

    By the way, I really like your engine. It’s fairly adaptable. Nice job!

    https://gist.github.com/758952

  18. choonkeat Says:
    January 23rd, 2011 at 7:52 pm

    should checkout https://github.com/eregon/app2engine too, it converts rails3 app into an engine

  19. Raoul Says:
    January 26th, 2011 at 7:47 am

    If I would have my models in a different directory than app; how should I configure the configuration files ?

    Suppose I have the models under lib in a directory structure A/B/C/x.rb where x is the model and the rest of the configuration, controllers, views reside under app.

    thanks.

  20. erwin Says:
    February 15th, 2011 at 3:22 am

    Thanks for this tuts … As Rails 3.1 coming .. I needed to work on some engine building now…

    Some point I did not get right … what should be written in the demo_app routes to know about the engine routes…

    running rake routes, I don’ get any cheese/widgets route at all…. I surely missed an important point .. but which one ?

  21. kie Says:
    November 27th, 2011 at 3:52 am

    small correction in the genator when the tree is not typical:

    tmp_real_path = File.expand_path(“tmp/~application.html.erb”)

    tmp = File.open tmp_real_path, “w”
    tmp.write layout; tmp.close

    remove_file ‘app/views/layouts/application.html.erb’
    copy_file tmp_real_path, ‘app/views/layouts/application.html.erb’
    remove_file tmp_real_path

  22. Nicholas Hughes Says:
    January 31st, 2012 at 5:29 pm

    @Frank (or for anyone else who stumbles across this):

    Mounting a Rails 3.1 engine (with assets at /app/assets) on our 3.1 app (expecting assets at root/public) required adding the following to our engine’s engine.rb file to serve assets in staging/production:

    initializer “static assets” do |app|
    app.middleware.insert_before ::Rack::Lock, ::ActionDispatch::Static, “#{root}/app/assets”
    end

    It seems to me that there is probably a more elegant way to present the mounted engine’s static assets to its host application, but my work today didn’t yield any insight.

    I hope this helps someone!

  23. Renaud Says:
    February 16th, 2012 at 1:46 am

    thanks for this tuto.

    My first engine was a pure success, but I decided to make one more and the second one override the first one:
    I lost roots of my first engine, if i debug I can see the Engine.config.mount_at is replaced by the second one, even if my second engine is not in the same namespace or has a different name.

    thank you for helping me

  24. σχεδιασμός ιστοσελίδων Says:
    August 15th, 2012 at 12:48 am

    I like this weblog very much, Its a real nice place to read and get information. “Talents are best nurtured in solitude character is best formed in the stormy billows of the world.” by Johann von Goethe.

  25. Parking Lot Says:
    August 15th, 2012 at 11:07 am

    I loved your article.Thanks Again. Keep writing….

    Major thanks for the article post.Really looking forward to read more. Much obliged….

  26. Rails Mountable Engine Creation, installation, unistallation | Learning with Earning Says:
    September 25th, 2013 at 8:20 am

    [...] Engine Points [...]

  27. na gabinet.waw.pl znajdziesz masaz leczniczy Says:
    March 28th, 2014 at 6:23 pm

    Somebody essentially lend a hand to make severely articles I’d state.

    This is the first tine I frequented your website page and to this
    point? I amazed with the research you made to create tthis actual post extraordinary.
    Wonderful task!

  28. search engine Says:
    July 26th, 2014 at 8:43 am

    Great web site you have here.. It’s difficult
    to find high-quality writing like yours nowadays. I truly appreciate individuals like you!
    Take care!!

    Here is my webpage – search engine

  29. Tasha Says:
    August 1st, 2014 at 3:18 am

    This website was… how do you say it? Relevant!! Finally
    I have found something that helped me. Thank you!

  30. websites melbourne Says:
    August 14th, 2014 at 2:04 pm

    Terrific post but I was wondering if you could write a litte more on this subject?
    I’d be very thankful if you could elaborate a little bit more.
    Many thanks!

  31. Contemporary Australian Aboriginal Paintings Says:
    August 15th, 2014 at 7:18 pm

    Wow, that’s what I was searching for, what a material!
    existing here at this website, thanks admin of this web page.

  32. china Says:
    August 21st, 2014 at 3:54 am

    Despite the fact that bringing china,it gets more difficult to steer. This man actually stated that Take part in go around as a typical man or women even while walks through china.

  33. tinnitus solutions Says:
    August 24th, 2014 at 9:22 pm

    This is a topi that’s near to my heart… Best wishes!
    Exzctly where are your contact details though?

    my webpage … tinnitus solutions

  34. Lace Front Wigs Says:
    August 26th, 2014 at 7:04 pm

    Creating a rails 3 engine / plugin / gem » Keith Schacht njsdqcnvp Lace Wigs

  35. Pedro Says:
    August 31st, 2014 at 11:59 pm

    Among the feasible reasons for this is because of a very hectic agenda specifically with people that
    are currently employed and tied up within an office-based environment.

  36. project management professional Says:
    September 4th, 2014 at 4:26 am

    I’m more than happy to discover this website. I wanted to thank you for your time just for this
    wonderful read!! I definitely loved every bit of it and I have
    you saved as a favorite to see new things on your blog.

    Take a look at my page – project management professional

  37. blogs sites Says:
    September 8th, 2014 at 10:37 am

    I was wondering if you ever thought of changing the structure of your site?
    Its very well written; I love what youve got to say.
    But maybe you could a little more in the way of content so people could connect with it better.
    Youve got an awful lot of text for only having one or two pictures.

    Maybe you could space it out better?

    My blog … blogs sites

  38. csoki-a-leleknek.tumblr.com Says:
    September 16th, 2014 at 11:31 am

    We stumbled over here by a different web page and thought I
    might as well check things out. I like what I see so i am just
    following you. Look forward to going over your web page again.

    my web page … csoki-a-leleknek.tumblr.com

  39. for beginners Says:
    September 22nd, 2014 at 10:29 am

    Great delivery. Great arguments. Keep up the good effort.

    My web site for beginners

  40. womens road bikes Says:
    September 23rd, 2014 at 12:29 am

    I’ve been browsing online mopre than 4 hours today, yet I
    never found any interestng article like yours. It
    is pretty worth enough foor me. Personally, if aall web owners and
    bloggers made good content ass you did, the web will be a lot more useful than ever before.

    my wweb blog womens road bikes

  41. southbaycareers.com Says:
    September 23rd, 2014 at 6:18 am

    The following crucial essential skill folks you need to
    learn in working with pictures is approximately visual applications.

  42. http://taxe2013.com/ Says:
    October 12th, 2014 at 7:13 am

    Creating a rails 3 engine / plugin / gem » Keith Schacht eyrlgogije louis vuitton sacs pas cher

  43. Lace Wigs Says:
    October 12th, 2014 at 7:13 am

    Creating a rails 3 engine / plugin / gem » Keith Schacht anksoed louis vuitton handbags

  44. penis stretcher product Says:
    October 24th, 2014 at 9:12 pm

    Great goods from you, man. I’ve be aware your stuff prior to and you are just too wonderful.

    I really like what you have bought here, certainly like
    what you’re stating and the way in which during which you say it.
    You make it enjoyable and you still take care of to stay it
    sensible. I cant wait to learn much more from you.
    This is really a wonderful site.

Leave a Comment