24

I've been reading a lot on the topic and nothing seems to quite cover my needs. I'm sorry if I'm repeating or unclear about something I'm both new to ruby and rails and new to stackoverflow.

I have an existing rails application with a lot of infrastructure in it. I want to take a few of it's models, nest them in a namespace and put all that into a ruby gem for use in other rails applications. From my understanding there's a problem with the loading paths for rails as they are a convention and a problem with defining another engine as then you have two and they crash.

I've been looking for a guide or tutorial to learn how to do this without much luck but I'm positive there's something out there if someone can point me at it that would be wonderful.

My attempts at making a gem with an engine fails on collisions or lack of rails.

I'm running rails 3.2.3 and ruby 1.9.3.

tshepang
  • 12,111
  • 21
  • 91
  • 136
Shrewd
  • 731
  • 5
  • 14
  • 1
    The problem you are describing is typically solved by refactoring your code out to a new Rails engine. How are you trying to create the engine, and exactly what errors are you getting? – PinnyM Aug 09 '12 at 20:40
  • 1
    As far as a guide, have you looked at [this](http://edgeguides.rubyonrails.org/engines.html) or [this](http://stackoverflow.com/questions/4993166/making-a-custom-plugin-gem-engine-for-rails-3-app)? – PinnyM Aug 09 '12 at 20:42
  • I'll try and better describe what I'm trying to do: I've made the sample app for the basic Rails tutorial (the blog) with posts, comments and tags. Now say I want to take tags and make that into a gem such that any Rails app can add tags onto any model. What I tried doing was making a gem containing everything tags (model, partials, migration) And I install said gem, then when I require it I get thrown out, for example if I run irb (posting output in another comment because I'm out off characters – Shrewd Aug 14 '12 at 10:11
  • 1.9.3p194 :001 > require "tag_model_gem" NameError: uninitialized constant TagModelGem::Rails 1.9.3p194 :002 > require "rails" => true 1.9.3p194 :003 > require "tag_model_gem" TypeError: already initialized class – Shrewd Aug 14 '12 at 10:12
  • 1
    What you are describing ought to just work, I do it all the time. So you're probably doing something not quite right. I don't entirely understand the nature of the problem you are having, sorry. But the thing you are trying to do is possible, and normal, and normally works. – jrochkind Jun 06 '14 at 20:20
  • Check this out [Mixable Engine](https://github.com/asee/mixable_engines) – abookyun May 13 '15 at 03:27

2 Answers2

26

Yes, you can create a gem containing models and include them in multiple Rails applications. This is one way to do it:

  • Create a gem: bundle gem demo_gem

  • Create or move your models to the demo_gem. I prefer putting them in lib/ folder of the gem like for example demo_gem/lib/app/models/student.rb.

    module DemoGem
      class Student < ActiveRecord::Base
      end
    end
    
  • Require all your models in demo_gem/lib/demo_gem.rb

    require "demo_gem/version"
    require "demo_gem/app/models/student.rb"
    module DemoGem
      # Your code goes here...
    end
    
  • Include the gem in your Rails applications Gemfile (I'm assuming that your code is not open source and you don't plan to publish the gem):

    gem 'demo_gem', path: '../demo_gem'
    

Now you can use these models anywhere in multiple rails application, just by using DemoGem::Student.

It is assumed here that you are using single database and that the tables exist. However you can create migrations in the gem itself and copy them to app using Rails generators.

Roope Hakulinen
  • 7,326
  • 4
  • 43
  • 66
vikas
  • 668
  • 6
  • 10
  • I can get it to work as long as I have all the classes in the one file you show. I attempt to put them in lib/.demo_gem/ where the Version file is and I get uninitialized constant DemoGem::Theresa. It is defined in lib/demo_gem/theresa.rb. I put the require in the demo_gem.rb file. If I put it as a class in the demo_gem.rb file in the module it is fine. I have 40+ files I want to make available as models in the gem. What am I missing? – Donald French Sep 11 '18 at 21:14
1

Start with this manual - http://guides.rubyonrails.org/engines.html

Create an engine with comand

$ rails plugin new "EngineName" --mountable

Than put all that you need, models, controllers e.t.c into you engine. Generate gem from it. Add this gem to you MasterApp. All models will be available under EngineName namespace.

rossmari
  • 81
  • 5
  • 2
    The question isn't just how to make a mountable plugin but involves things being added to said plugin and made to work silently in the background. – Shrewd Feb 16 '15 at 13:29