在兩個應用程序之間共享一個mongoid模型 - 使用引擎與插件

[英]Sharing a mongoid model between 2 applications - using engine vs. plugin

I want to share a model between 2 (maybe more in the future) of my rails apps. I couldn't find any clear suggestions, but I picked up some of the questions and answers I've read and came to a conclusion that it has to be done with a "gemmed" plugin engine. I decide to go with an plugin, because I read that engine is simply a kind of a "full" plugin.


So I created a plugin using: rails plugin new my_models --skip-active-record --skip-test-unit --dummy-path=spec/dummy (the options are for skipping activerecord as an ORM and using rspec for testing).

所以我創建了一個插件使用:rails plugin new my_models --skip-active-record --skip-test-unit --dummy-path = spec / dummy(選項用於跳過activerecord作為ORM並使用rspec進行測試) 。

After I created the plugin, I got the following files:


my_models.gemspec  Gemfile  Gemfile.lock  lib  MIT-LICENSE  Rakefile  README.rdoc  spec

I tried to include the model using the following methods:


  1. Just creating an app/models directory and put my model inside
  2. 只需創建一個app / models目錄並將我的模型放入其中
  3. As suggested in this tutorial (and I could see in devise's github), I created a generator in an attempt to generate the model.
  4. 正如本教程中所建議的(我可以在devise的github中看到),我創建了一個生成器來嘗試生成模型。

Both of them failed, and then I decided to go with the engine suggestion (by just adding --mountable to the options list of the "rails new" command), I got the full rails app structure (with app, bin, db and the rest of the directories), put my model in the app/models dir and it worked like a magic!

他們兩個都失敗了,然后我決定采用引擎建議(只需將--mountable添加到“rails new”命令的選項列表中),我得到了完整的rails應用程序結構(帶有app,bin,db和其余的目錄),把我的模型放在app / models目錄中,它就像魔術一樣!

As I believe I'm a programmer and not I magician, I don't to do such magics, so can you tell me what's wrong with both of my thin plugin solutions (using generator/creating a model)?? Moreover, what are the advantages of using those generators?


I'm attaching my generator's code, maybe I miss something:


require 'rails/generators/named_base'
require 'mongoid'

module Mongoid
  module AttackGenerator
    def generate_model
      invoke "mongoid:model", [name] unless model_exists? && behavior == :invoke

    def inject_field_types
      inject_into_file model_path, migration_data, after: "include Mongoid::Document\n" if model_exists?

    def migration_data
      field :link_url, type: String
      field :token, type: String

    def model_exists?
      File.exists?(File.join(destination_root, model_path))

    def model_path
      @model_path ||= File.join("app", "models", "#{file_path}.rb")

1 个解决方案



An engine (very good guide) is basically a small Rails app: has controllers, can inject into your rails code in various ways (sharing classes/controllers and such) and most important, can use your main Rails application code transparently.


After thinking a bit about it, I believe you need an engine, the reason is, a simple model still require migrations. Notice that an engine is basically a gem plus some few additions provided by rails.


Although miguiding (plugins in rails are not used anymore), the command rails plugin new blorgh --mountable creates a gem which is a rails engine.

雖然miguiding(不再使用rails中的插件),但命令rails plugin new blorgh --mountable會創建一個gem作為rails引擎。

How do you understand if a gem is a rails engine? By the file engine.rb (can be named differently, the contents are the important stuff).


module Blorgh
  class Engine < ::Rails::Engine
    isolate_namespace Blorgh

The other important thing you should be aware of, is that rails (actually Bundler.require) auto requires one file for you when you add your custom gem to your gemfile: the file named lib/yourgemname.rb, in this case, lib/blorgh.rb. That's your entry point. Aside from that, all the other things (gemspec and all the other files) are things created for rubygems. The important part is that you use .gemspec file as your gemfile, just add gems using add_dependency instead of the standard Gemfile syntax. If you want (and you should) learn more about ruby gems, this article is really good

您應該注意的另一件重要事情是,當您將自定義gem添加到gemfile時,rails(實際上是Bundler.require)auto需要一個文件:名為lib / yourgemname.rb的文件,在本例中為lib / blorgh.rb。這是你的切入點。除此之外,所有其他的東西(gemspec和所有其他文件)都是為rubygems創建的東西。重要的是你使用.gemspec文件作為你的gemfile,只需使用add_dependency而不是標准的Gemfile語法添加gems。如果你想(並且你應該)了解更多關於紅寶石的信息,那么這篇文章真的很棒

The app directory is autoloaded like rails does, so adding app/models/yourmodel.rb is a good way to have your model autoloaded and shared with all your apps. The last important thing, are migrations. You have to remember to run your_engine_name:install:migrations in your Rails app to copy your migrations from your engine to your rails app and run them (otherwise you can see the suggestions on this article)

應用程序目錄像rails一樣自動加載,因此添加app / models / yourmodel.rb是讓您的模型自動加載並與您的所有應用共享的好方法。最重要的是遷移。您必須記住在Rails應用程序中運行your_engine_name:install:migrations,將您的遷移從引擎復制到rails應用程序並運行它們(否則您可以看到本文中的建議)

And you are ready. One note! To install your gem you have two options: use your remote git repository (best option) or for local development you can use :path, here two examples that can be added to your Rails apps gemfiles:


# Use this only for development purposes
gem 'yourgem', '1.0.0', path: 'your/local/path/to/gem'

# Use this for deploy and such, you'll need access to that repository
gem 'yourgem', '1.0.0', git: 'yourgiturl'

This should be enough




粤ICP备14056181号  © 2014-2021 ITdaan.com