简体   繁体   中英

Rails best practice - Engines

I'm currently upgrading an app to rails 4. I planned to install this app for few persons but they have different needs. I decide to use this upgrading version time to put some of my models in engines. The objective is to spend less time tweaking the app for the needs of the situation. The core app will manage the basic resources and the engines will add features (The app is managing membership for small organizations). I read a lot documentation including the "guides". I tested some engines to see the behaviour of the app. Here are my questions I couldn't answer by my searches:

1 - Naming convention:

How do you name your engines? My first attempt was to name it by their function but when I generated my first model I saw that I can't use the function name for my model.

I was think about something like: Coreappname_functionality

for exemple I want to add activities for my members the engine will be named : member_activities

2 - full vs mountable

I read a lot about this subject, lot of people seem to use mountable engines. I try both of them and I think that the full option is really fast to implement (no routing, no namespace isolation that I have to be aware of). But I also understand the risk for the class collisions. If I'm the only one writing code for this app is it a bad habit to use a full engine(it's just a laziness question). Are there others advantages of mountable engine even if I'm not planning to use them in another app?

3 - "if engine exists?"

Inside the core app i'll put the code that all the engines need. For example inside the side bar I want to display the list of the last activities but only if the activities engine is used. The objective is to put all the necessary code inside the core app but use this code depending on the present of engines or not.

During my test time I used:

if defined? Activity
  @activities = Activity.all
end

and render it the views something like this:

<% if defined? Activity %>
 <h3><%= @activities.first.title %></h3>
<% end %>

It's working well but I'm not sure that it is a good practice. Is there an alternative?

Do you have any advices before I jump in the engine's world? I prefer posting my questions before instead of posting my errors after the attempt!

For anybody reading that...

I think there is a misunderstanding about what an isolated engine is. In fact it is a bit confusing. Some may think that's choosing between isolated and not isolated is a bit like a matter of preference. But that's not entirely true.

Isolated engine is just that. An isolated engine. It's not suitable for a "module" of your application. It's more like a "subapplication" of you application. The difference is critical. Modules of your application probably will share models, api or some business logic. Still, encapsulation of responsibilities is important, but there will be some connections. For example probably almost all of your modules will be using something like EventDispatcher module. While isolated engine is a whole application on it's own. Although it could use models from the host application it can't use models from different isolated engine (at least without hacks, a lot of pain in 'certain situations' and that's generally a bad idea causing bad design).

So if you try to implement your app modules using isolated engines your probably end up storing all your models in main/host application to be reusable between your - in fact - subapplications. Probably the same with views. And maybe with assets too. And if some business logic have to be shared it probably would end up in main application too. So that's basically defeats the whole purpose. That's why you should use not isolated engines for your modules. While isolated engines are good for a - totally encapsulated - subapplication. For example if you want to have an e-commerce shop alongside with your main application (spree gem does exactly that).

A more enterprise example would be an ERP system. It could have subapplications like: CRM, Resource Management, etc (isolated engines). And those subapplications could have their own modules (not isolated engines).

Just for the completeness of my answer. As a isolated engine i mean that generated using rails plugin new engine_name --mountable , while a not isolated would be generated using rails plugin new engine_name --full .


Disclaimer:

Maybe there are some cases when you would want to go different way (probably when implementing some kind of magic gem doing some magic things), but that's up to you to figure it out. By this answer I just mean it should be applicable in most applications.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM