Where do you put your engines in your Rails project? - ruby-on-rails

I have been putting them in the toplevel. I am wondering if it is more logical to put them in lib. Is there a general consensus or convention?

vendor/engines is my default choice.

I generally make them gems (by creating them with the bundle gem command) and keep them as separate projects on GitHub. Then I can include them into my application like this:
gem 'forem', :git => "git://github.com/radar/forem"
This way, I can make commits to my application and have them be separate to the commits for my engine.
The reasoning for doing it this way is because the engine may be shared across multiple applications and I'd rather not have to make the same change multiple times.

Related

Include a gem's code as part of a rails project

My rails 4 project depends on Comfortable Mexican Sofa (CRM) which is loaded as a gem.
I checked out this gem as a submodule of my git repository.
Moving forward, this gem is becoming part of my project: I'm adding features to it
that depends on classes of my projects.
I would like to keep this gem as a submodule (to be able to pull changes from
the main repository) but still be able to add code that rely on my project.
What's the cleanest way to achieve that ?
(should I put the whole gem submodule into my lib folder for instance ?
should I keep it referenced as a gem ? etc...)
should I keep it referenced as a gem
Yes, you need to keep it referenced as a gem.
One of the benefits of using external libraries is that they are maintained by a group of very clever people (most of the time). It would be highly unlikely that you're going to be able to keep the submodules you include up to date as much as the gem owners etc.
What you're best doing is either overriding specific parts of the gem (EG like how many people override Devise functionality with their own controllers), or to see about creating an API for the gem, which you can populate from your app.
For me, in development, separation is always better then binding. I would recommend to leave it as gem and develop in the separate repository.

Integrating multiple apps in Rails

I am working on a project in Rails. It contains multiple sub-projects. They have a common login and the rest is separate for all. I want to integrate them all in the main project. The sub-projects are pretty big, so putting them all together will make it cumbersome to manage the code. Is there any way to integrate the sub-apps or gems in the main project?
You might consider breaking your apps into engines. It's a great way to isolate functionality and make code modular. Here's a link to the Rails engine docs: http://guides.rubyonrails.org/engines.html
If you need examples of real-world uses of engines you might consider looking at the code for Spree: https://github.com/spree/spree
With Spree you can add custom functionality by installing or building extensions, which are effectively Rails engines.
If you want to reference local gems/engines, you can point to them in your Gemfile like this:
gem 'mygem', :path => '/path/to/gem'
But make sure that the individual gems within your project don't have a .git folder, or you might run into errors regarding sub-modules.

Organizing shared layout and assets between several projects

Every time I create a new Rails application, and for the admin part, I copy the layout and assets from another project to the new project.
I think it's obvious how many problems this approach causes. I am thinking about organizing my layout, and assets in a proper way.
What I have in mind is creating a gem and putting everything in that gem. But before I try that, I wonder if there is a better way for organizing these files?
Gem is good if you want to share codes among apps.
If, like your case, the shared parts have routes/views, an engine would be better suited, which is also a kind of gem. You can check the guide for details: http://guides.rubyonrails.org/engines.html

What's the best way to require source files when writing a gem

I'm converting the models folder of a rails app into a gem so more rails app can use the same domain model layer.
In the initial rails app, the loading of all model files is handled by activesupport so there no require statement everywhere. But in the gem version, it has to be done manually. I had a look at the code of popular gems such as rspec, factory_girl and state_machine and it looks like they all require all necessary source files in one file, usually named after the project.
The downside of this approach is that you need to maintain one file listing all the others and that seems a bit clumsy. And even though I have hit that problem yet, I can foresee cirular dependency issues.
Another way would be to have each source file requiring the files it needs. That would work in the standalone gem as well as in the rails app. But I haven't seen examples of gems using that technique so I'm wondering if there is a downside I'm not seeing?
thanks
You're talking about model files, if so, simply adopt the same structure as a standard Rails app and make your gem inherit from Engine. Everything will be included painlessly.

Create plugins or gems for Rails 3?

I have features I would like to be portable between my own Rails applications.
I wonder if I should create a gem or a plugin for each feature I want to be portable (sharable).
They are just for Rails (for now) because they include css, html, js and image files.
But I have been wondering, the things provided with plugins could be provided with gems too but not the opposite? So maybe it's better to learn how to create gems, because then you I don't have to learn how to create both gems and plugins? And gems seem to be more popular these days.
But then, from what I can understand one gem is shared between all rails app in the OS. So that means I can not customize it for each Rails app right? In that case, maybe creating a plugin is better cause it should be allowed to customize (editing css, js etc) each feature and to have it stored inside the Rails app itself and not in the OS level.
Some advices would be appreciated!
UPDATE:
So gem works great with css, html, js and image files? In a plugin I think you can have a MVC, your own models, views and controllers. Quoted from Rails guides "Storing models, views, controllers, helpers and even other plugins in your plugins". Is this possible too in a gem? Eg. I want to add a extension that gives me a nice Shopping cart (with own migrations, mvc, asset files) that will be hooked into the current Rails app. Is this possible as gem or only as plugin?
You're right that gems offer a little more than plugins. Versioning and dependencies on other gems being the main ones for me.
One gem needn't be shared across everything using ruby. You can install multiple versions of a single gem and specify in your environment.rb that a gem requires a specific version. E.g.
config.gem 'my-gem', :version => '1.2.3'
Also you can freeze gems into your rails application so that you know you are working with a specific version.
You might want to look at the jeweler gem which makes creating your own gems easier.
UPDATE
To include CSS, javascript etc I think you'll need to make an Rails engine which can then be bundled as a plugin or a gem. I've not done this but there's some coverage here and here.
The push with Rails 3 seems to be towards gems and away from plugins as a lot of support has been added to make gems work as well or better than plugins ever did. A well constructed gem is a great thing to have and share between different applications, and also reduces the amount of testing you will have to do since you can test the gem thoroughly before integration.
For extensions to Rails that use CSS, HTML and other assets, it might be that you need to build an engine to bundle this all up and allow it to fit neatly into an application.
As of Rails 4, plugins will no longer be supported.
Gems are the way forward.

Resources