22

I'm currently building 2 API's using Ruby on Rails. One if for reading (finding objects, querying) and the other one is for actually writing to it, involving a kind of complicated process with queues and another API. Both applications require the exact same models and logic inside them.

My question is, what's the most common best practice or approach to share models specifications (relationships, scopes, methods) between 2 rails applications?

Thank you!

Gotjosh
  • 1,019
  • 4
  • 13
  • 34

5 Answers5

4

The way I would do it is a 'Mountable Engine'. Check out the excellent Railscast by Ryan Bates for starters and the engine-section at api.rubyonrails.org for further details.

With best regards, Mandi

klaffenboeck
  • 6,297
  • 3
  • 23
  • 33
  • The railscast is suppose to be intended for new applications but the first API it's already made, besides though engines you would share controllers and views if i'm right which is not my case... – Gotjosh May 08 '12 at 20:18
  • 2
    @Gotjosh You can extract your existing models into the engine (which is best packaged into a gem). Then include this gem into your old app and voilà, your models are available. You can include the gem into any other app you like. And no, engines don't automatically provide controllers. An engine can provide any or all of the pieces of a Rails app, models, views, controllers, asset files (JS, CSS), etc. A good book on this is José Valim's "Crafting Rails Applications". – Wolfram Arnold Jun 05 '12 at 22:27
1

If you just want to share models, you can add the other project models folder into your autoload paths:

rails new test1
rails new test2
cd test1
rails g model User 
cd ../test2/
# ACTION REQUIRED: edit config/application.rb adding this line
# inside the class Application < Rails::Application block:
#
# config.autoload_paths += %W(#{config.root}/../test1/app/models)
#
mkdir db/migrate
cp ../test1/db/migrate/*_create_users.rb db/
mv db/*_create_users.rb db/migrate/
rake db:migrate
rails r 'puts User.inspect' 
#=> User(id: integer, created_at: datetime, updated_at: datetime)

You can also set the whole thing in order to have the two app/models folders as private, using a third shared folder, adding this to the projects:

# config.autoload_paths += %W(/path/to/a/shared/folder)

This folder can even be not the same folder for each project, so it could be a path to a git submodule , for example (if you use GIT, I reccomend this solution).

Another option could be pointing app/models to a shared folder with a soft link

mdesantis
  • 8,257
  • 4
  • 31
  • 63
1

My trick for doing this is to not actually use Rails tricks. I use "git" tricks, and pull in code from a 3rd, shared-code repo. I put this into both apps as an engine, and as an external git reference.

It's a little more work, but once you have done it once in one app, it's easy to use that as a template for the next one, too.

Michael Graff
  • 495
  • 1
  • 4
  • 14
  • Doesn't that mean you have to push the changes in one app to Git before you can see them in the other app? How would you develop and test something new? What do you mean by 'an engine'? – Chloe Feb 11 '13 at 01:41
0

You could try git submodule for that job.

http://git-scm.com/book/en/Git-Tools-Submodules

fl00r
  • 82,987
  • 33
  • 217
  • 237
  • 1
    Although Git Submodules are useful, one limitation is that it is not possible to deploy a submodule to Heroku. – B Seven Mar 04 '15 at 00:10