LoginSignup
1
0

More than 1 year has passed since last update.

delegateとは

Railsにおけるdelegate移譲するの意味で使われていると思われます。

delegateメソッドを使うことによって、異なるクラスに定義されているメソッドをそのオブジェクトのメソッドとして呼び出せます。
これによって、リレーションを持つクラスのインスタンスメソッドを委譲することができます。

user has_many posts && post belongs to useの場合を考えます

  • User(id: integer, name: string, age: integer)
  • Post(id: integer, title: string, content: string)

delegateを使わずにuserのnameを参照する場合

.rb
    post = Post.first
    post.user.name

delegateを使って参照する場合

post.rb
    class Post < ApplicationRecord
        belongs_to :user
    
        delegate :name, to: :user
    end
.rb
    post = Post.first
    post.name

このように、リレーション関係にあるクラスのメソッドをそのオブジェクトのメソッドであるかのように使うことができます。

delegateメソッドを呼び出すことによって何が起こっているのかというと、呼び出したクラスにインスタンスメソッドが定義されます。

  • delegateメソッドを使っていない場合
    pry(main)> Post.instance_method(:name)
    # => NameError: undefined method `name' for class `Post (call 'Post.connection' to establish a connection)'
  • delegateメソッドを使った場合
    pry(main)> Post.instance_method(:name)
    # => #<UnboundMethod: Post (call 'Post.connection' to establish a connection)#name(...) /app/app/models/post.rb:14>

delegateメソッドを使う際には、1対1の関係であることと、指定するメソッドがpublicメソッドである必要があります。

上記の例で言えば、user has_many postsであるため、PostクラスのインスタンスメソッドをUserクラスにおけるdelegateメソッドの引数に指定することはできません。

オプション

delegateメソッドのオプションには:to, :prefix, :allow_nil, :privateがあります

  • to
    :toでは、ターゲットになるオブジェクトを指定します。基本的にはbelongs_to, has_oneの対象になるオブジェクトと同じと考えていいかと思います。
  • prefix
    prefixをつけることができます。下記のようにprefixを指定すると、post.hello_nameのように参照することができるようになります。
    delegate :name, to: :user, prefix: :hello
  • allow_nil
    allow_nil: trueを指定すると、Module::DelegationErrorが生じなくなります。
  • private
    private: trueを指定するとprivateメソッドとして、自クラスに定義されます。

参考にしたサイト

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0