Edited at

RailsのmodelをEngineで共有する(実験中)

More than 3 years have passed since last update.

まだ全然実験中


目的

PC用とmobile用を別プロジェクトにしたいとか

管理ツールを別プロジェクトにしたいとか

そういう時にEngineを使うとmodelの共有がしやすい。

(かもしれない)


基本的なEngineのつくりかた

rails plugin new my_engine --mountable

bin/rails g model hoge

生成されたファイルをいつもどおり弄ればおk


RSpecとFactoryGirl を使う

普通にgemspecにgemを追加したあと lib/my_engine/engine.rb に以下を追加してジェネレータがrspecとfactory_girlを使うようにする

  class Engine < ::Rails::Engine

config.generators do |g|
g.test_framework :rspec, fixtures: false
g.fixture_replacement :factory_girl, dir: 'spec/factories'
end
end

これでジェネレータを実行すると

$bin/rails g model user

invoke active_record
create db/migrate/20141104193453_create_my_engine_users.rb
create app/models/my_engine/user.rb
invoke rspec
create spec/models/my_engine/user_spec.rb
invoke factory_girl
create spec/factories/my_engine_users.rb

な感じになる


アプリケーションからfactoryを使えるようにする

そのままではEngineを利用するアプリケーションからfactoryが見えない。

Engineの中でFactoryGirlにファイルのありかを教える。

  class Engine < ::Rails::Engine

initializer 'my_engine.factories', after: 'factory_girl.set_factory_paths' do
FactoryGirl.definition_file_paths.unshift File.expand_path('../../spec/factories', __FILE__)
end
end

FactoryGirl(Rails)を使っている場合は factory_girl.set_factory_paths が自動で呼ばれるので、その後にコードが実行されるようにする。

FactoryGirlを使っていない場合は実行されないので安心。


問題点 / 疑問点

まだよくわからんところ


Relationはどうなるの

特にアプリケーション側で条件を追加したりしたいときなど

Engineのmodelを拡張することになる。

もともとのコードが

class MyEngine::User

has_many :articles
end

class MyEngine::Article
belongs_to :user
end

な感じの時、

アプリケーション側で

class User < MyEngine::User

default_scope { where(:banned, false) }
end

class Article < MyEngine::Article
default_scope { where(:draft, false) }
end

とやったとき、 User.first.articles は MyEngine::Article を参照するようだ。

よってArticleで設定したdefault_scopeは効かない。

Engineのmodelを拡張して使いたいときはどうすればいいのだろうか?


  • 継承したクラスを作る


    • relationを定義し直す? めんどい

    • factoryも定義しなおしになる?



  • MyEngine::User を拡張する?


    • その場合どこに書く? initializerが太る

    • そもそもMyEngine::UserはEngineの中のコードしか見に行かない

    • MyEngine::User がロードされたら拡張のコードが走るようにinitializerでがんばる?



  • そもそもEngineのモデルを拡張なんて考えてはいけない

  • factoryはどうする?


    • factoryの再定義できないの辛い