Rails プラグインを学んでみる。(後編)
こんにちは、マリンです。
前回はRailsガイドの「プラグイン作成入門」の3まで書きました。今回は続きの4から書きます。
前回の記事はこちら。
4.“acts_as"メソッドをActive Recordに追加する。
acts_as~
- プラグインのモデルによく追加されるメソッドの名前。
ここでは後に作成する"squawk"メソッドをActive Recordに追加するためのメソッド、"acts_as_yaffle"を追加します。
<必要ファイルの準備>
# test/acts_as_yaffle_test.rb require 'test_helper' class ActsAsYaffleTest < ActiveSupport::TestCase end # lib/yaffle.rb require 'yaffle/core_ext' require 'yaffle/acts_as_yaffle' module Yaffle end # lib/yaffle/acts_as_yaffle.rb module Yaffle module ActsAsYaffle # ここにコードを書く end end # test/acts_as_yaffle_test.rb require 'test_helper' class ActsAsYaffleTest < ActiveSupport::TestCase end # lib/yaffle.rb require 'yaffle/core_ext' require 'yaffle/acts_as_yaffle' module Yaffle end # lib/yaffle/acts_as_yaffle.rb module Yaffle module ActsAsYaffle # ここにコードを書く end end
クラスメソッドを追加する
プラグインはホストアプリにインストールして使うものです。 そのため、もしかするとホストアプリとプラグインでメソッド名が被ってしまうことが起こるかもしれません。その問題を解決するためのクラスメソッドを追加します。
- “yaffle_text_field” : 名前を変更できるようにするメソッド。
<test作成>
# yaffle/test/acts_as_yaffle_test.rb require 'test_helper' class ActsAsYaffleTest < ActiveSupport::TestCase def test_a_hickwalls_yaffle_text_field_should_be_last_squawk assert_equal "last_squawk", Hickwall.yaffle_text_field end def test_a_wickwalls_yaffle_text_field_should_be_last_tweet assert_equal "last_tweet", Wickwall.yaffle_text_field end end
このテストはHickwallとWickwallモデルがないのでRedです。
<モデル作成>
テストを通すために必要なモデルをダミーアプリに作成します。
$ cd test/dummy $ bin/rails generate model Hickwall last_squawk:string $ bin/rails generate model Wickwall last_squawk:string last_tweet:string
マイグレーションを実行して、テストデータベースにテーブルを作成します。
$ cd test/dummy $ bin/rails db:migrate
作成したモデルがyaffles
として振る舞うよう指示します。
# test/dummy/app/models/hickwall.rb class Hickwall < ActiveRecord::Base acts_as_yaffle end # test/dummy/app/models/wickwall.rb class Wickwall < ActiveRecord::Base acts_as_yaffle yaffle_text_field: :last_tweet end
<acts_as_yaffleメソッドを定義>
前述のモデルに使用したacts_as_yaffle
を定義します。
# yaffle/lib/yaffle/acts_as_yaffle.rb module Yaffle module ActsAsYaffle extend ActiveSupport::Concern included do end module ClassMethods def acts_as_yaffle(options = {}) # ここにコードを書く end end end end ActiveRecord::Base.send :include, Yaffle::ActsAsYaffle
ここでテストを行うと、今度はyaffle_text_field
が定義されていないということでRedになると思います。前述のモデルに使用したacts_as_yaffle
メソッドを実装し、この中で定義してテストが通るようにします。
# yaffle/lib/yaffle/acts_as_yaffle.rb module Yaffle module ActsAsYaffle extend ActiveSupport::Concern included do end module ClassMethods def acts_as_yaffle(options = {}) cattr_accessor :yaffle_text_field self.yaffle_text_field = (options[:yaffle_text_field] || :last_squawk).to_s end end end end ActiveRecord::Base.send :include, Yaffle::ActsAsYaffle
cattr_accessor
- クラス外から対象のクラス変数へアクセスするためのメソッドです。
- 似たものに
attr_accessor
がありますが、これはインスタンス変数にアクセスするためのメソッドです。
これでテストはGreenになります。
インスタンスメソッドを追加する
先に述べた'squawk'メソッドを追加します。このメソッドはデータベースの値のいずれかひとつを設定するメソッドです。
<テスト作成>
# yaffle/test/acts_as_yaffle_test.rb require 'test_helper' class ActsAsYaffleTest < ActiveSupport::TestCase def test_a_hickwalls_yaffle_text_field_should_be_last_squawk assert_equal "last_squawk", Hickwall.yaffle_text_field end def test_a_wickwalls_yaffle_text_field_should_be_last_tweet assert_equal "last_tweet", Wickwall.yaffle_text_field end def test_hickwalls_squawk_should_populate_last_squawk hickwall = Hickwall.new hickwall.squawk("Hello World") assert_equal "squawk! Hello World", hickwall.last_squawk end def test_wickwalls_squawk_should_populate_last_tweet wickwall = Wickwall.new wickwall.squawk("Hello World") assert_equal "squawk! Hello World", wickwall.last_tweet end end
squawk
が定義されていないのでこれはRedになります。
<'squawk'を定義>
# yaffle/lib/yaffle/acts_as_yaffle.rb module Yaffle module ActsAsYaffle extend ActiveSupport::Concern included do end module ClassMethods def acts_as_yaffle(options = {}) cattr_accessor :yaffle_text_field self.yaffle_text_field = (options[:yaffle_text_field] || :last_squawk).to_s include Yaffle::ActsAsYaffle::LocalInstanceMethods end end module LocalInstanceMethods def squawk(string) write_attribute(self.class.yaffle_text_field, string.to_squawk) end end end end ActiveRecord::Base.send :include, Yaffle::ActsAsYaffle
これでテストはGreenになります。
ここまででプラグインの開発は終了です。
5. ジェネレータ
ジェネレータ
- 与えられた条件などに基づいてデータやプログラムコードを自動的に生成するプログラムなど。
もしgemにジェネレータを含めたい場合には、作成したジェネレータをプラグインのlib/generators
ディレクトリに置くだけで大丈夫です。
6. gemを公開する
せっかく作成したプラグインなので、公開したい場合があると思います。gemはGitリポジトリを使用して共有が可能です。
他のアプリケーションで使用するには、まずgemのコードをリモートリポジトリにコミットし、その後gemを使用したいアプリケーションのGemfileに書いてbundle install
することで利用できます。
gem 'yaffle', git: 'git://github.com/yaffle_watcher/yaffle.git'
この時コードのURLや、ローカルのディレクトリの場合はパスを忘れず書きましょう。
もしgemを正式なリリースとして一般公開するなら、RubyGemsでパブリッシュします。詳細はこちら(英語です。)
ここまでで直接開発に関わる説明は終わりです。
7項は「デプロイするならきちんとドキュメントを書きましょう」という内容なので省略します。
まとめ
基本的にはアプリの開発と同じですね。あとはファイル構成や、gemspec
、本アプリでの使用方法などでつまずかなければいけそうです。
私の場合は自分のサイトにブログ機能を追加することが目的なので、よりホストアプリに寄り添ってるっぽいエンジン(多分似たようなものだと思うのですが)を使って開発していこうと思います。
とはいえ、プラグインが作れるようになるとできることの幅が広がりそうなので、サラッとでも勉強しておくと良さそうですね。