93412


`included do ~ end`
で囲ったメソッドは[includeされた時実行される](https://qiita.com/Momozono/items/433a1a7d397bb62f076e#included-
doend)と聞きました。  
ここでenumを定義しているのはincludeしたクラスでこのenumを使用したいからだと思うのですが、 `included do ~ end`
の元々の用途とは違う気がするのですが、これは正しい使い方なのでしょうか。  
実行 = 定義と同じような感じなのでしょうか。  
詳しい方教えて頂けると嬉しいです。

[class_eval do ~ end と included do ~
endが同じ動作みたいな書き方がされている記事もある](https://www.techscore.com/blog/2013/03/22/activesupportconcern-%E3%81%A7%E3%83%8F%E3%83%83%E3%83%94%E3%83%BC%E3%81%AA%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB%E3%83%A9%E3%82%A4%E3%83%95%E3%82%92%E9%80%81%E3%82%8B/)

[code]

    module A
      extend ActiveSupport::Concern
    
      included do
        enum status: { published: 0, draft: 1 }
      end
    end
    
[/code]


CC BY-SA 4.0
2023-01-16T15:10:17.833
93390
2023-01-17T11:28:42.243
2023-01-17T11:10:28.597
19110
22565
question
ruby-on-rails ruby
railsのincluded do 内にenumを定義している理由が分からない。


`enum` は `included` の中にあるべきです。これはそれぞれの行がいつ評価されるのかを考えると納得しやすいです。`included`
に渡したブロックの中身はクラスで `include` されたときに評価されます。

`enum` の話をする前に、例として以下のモジュールを考えてみます。

[code]

    module M
      extend ActiveSupport::Concern
    
      puts "foo"
    
      included do
        puts "bar"
      end
    end
    
[/code]

Rails console でこのモジュールを定義してみると、定義したモジュール自体を返すところで `foo` のみが出力されます。

[code]

    irb(main):001:1* module A
    irb(main):002:1*   extend ActiveSupport::Concern
    irb(main):003:1*
    irb(main):004:1*   puts "foo"
    irb(main):005:1*
    irb(main):006:2*   included do
    irb(main):007:2*     puts "bar"
    irb(main):008:1*   end
    irb(main):009:0> end
    foo
    => #<Proc:0x00007fd91d38a038 (irb):6>
    
[/code]

そしてこのモジュールを `include` したクラスを定義してみると、そのようなクラスを定義するたびに `bar` が出力されます。

[code]

    irb(main):010:1* class C
    irb(main):011:1*   include A
    irb(main):012:0> end
    bar
    => C
    irb(main):013:1* class D
    irb(main):014:1*   include A
    irb(main):015:0> end
    bar
    => D
    
[/code]

このように、似たような場所に書かれた `puts` でも、そのメソッド呼び出しが評価されるタイミングが異なっています。

さて、`ActiveRecord::Enum` モジュールに定義されている `enum` は、それ自体はメソッドです:
<https://api.rubyonrails.org/v7.0.4/classes/ActiveRecord/Enum.html>

したがってこの `puts` と同じように、`included` に渡すブロックの中に入れるか否かで評価のタイミングが異なります。

`enum` を呼び出すのはクラスの中で `include` されたときであるべきなので、質問文にあるように `included`
の中に含めるべきなのです。


CC BY-SA 4.0
2023-01-17T11:28:42.243
93412
2023-01-17T11:28:42.243
19110
93390
answer