yosaku_ibs
@yosaku_ibs

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

【Ruby】ActiveRecordはmoduleですか?

Q&A

Closed

質問

ActiveRecordはmoduleという認識で間違いありませんでしょうか?

②下記ソースコードにおけるAddPublisherIdToBooksというクラスは ActiveRecordというmoduleMigration[6.0]というメソッドを継承したクラスという認識で間違いありませんでしょうか?

ソースコード

class AddPublisherIdToBooks < ActiveRecord::Migration[6.0]
  def change
    add_reference :books, :publisher, foreign_key: true
    change_column :books, :publisher_id, :integer, null: false
  end
end

自分で試したこと

ネットでの検索。(ActiveRecordはModelに関係するものであるということはわかったのですが、ActiveRecord自体の正体についてはわかりませんでした。)

以上、お手数ではございますが
もしご存知の方がいらっしゃいましたら
ご教示の程よろしくお願い申し上げます。

0

1Answer

①モジュールです。これはソースコードを読むか Rails console で確認すれば確かめられます。

% bin/rails console
Loading development environment (Rails 7.0.2.2)
irb(main):001:0> ActiveRecord.class
=> Module
irb(main):002:0> module MyModule; end; MyModule.class # 比較用
=> Module
irb(main):003:0> class MyClass; end; MyClass.class # 比較用
=> Class

②「Migration[6.0]というメソッド」が違います。 ActiveRecord::Migration はクラスです。このクラスは [] メソッドを持っており、 ActiveRecord::Migration[6.0] のように呼び出すことで、 ActiveRecord::Migration::Compatibility::V6_0 クラスを返します。 AddPublisherIdToBooks はそれを継承しています。

irb(main):003:0> ActiveRecord::Migration.class
=> Class
irb(main):004:0> ActiveRecord::Migration.respond_to?(:[])
=> true
irb(main):005:0> ActiveRecord::Migration[6.0]
=> ActiveRecord::Migration::Compatibility::V6_0
irb(main):006:0> ActiveRecord::Migration[6.0].class
=> Class

ようするに class AddPublisherIdToBooks < ActiveRecord::Migration::Compatibility::V6_0 と書くのと同じです。なぜ今のようになっているかというと、 Rails は処理を複雑にしてでも見た目がすっきりしたコードに重きを置く(ことが多い)設計だからです。

1Like

Comments

  1. @yosaku_ibs

    Questioner

    uasi様
    いつも大変お世話になっております。
    夜分遅いところご回答くださり誠にありがとうございます。

    `.class`で「classなのかmoduleなのか?」を調べられるとは知りませんでした。
    ご教示くださり誠にありがとうございます。


    ②へのご回答内容につきまして、さらに質問させてください。
    質問②-1:`[ ]メソッド`というのはどういう意味でしょうか?

    質問②-2:`ActiveRecord::Migration::Compatibility::V6_0`の読み方ですが、「`ActiveRecord`という`module`の中の`Migration`という`class`の中の`Compatibility`という`module`の中の`V6_0`という`class`」という読み方で合っていますでしょうか?

    以上、お手数おかけし申し訳ございませんが
    ご教示よろしくお願い致します。
  2. ②-1 Array から値を取り出すとき foo[0] のように書きますが、この後置角カッコは実は [] という名前の Array のインスタンスメソッドを呼び出しています。これは見た目が異なるだけで普通のメソッドと同じ扱いです。自分でクラスに [] メソッドを定義することもできます。

    ```
    class MyClass
    # インスタンスメソッド版
    def [](n)
    n * 2
    end

    # クラスメソッド版
    def self.[](message, name)
    "Hi #{name}, #{message}!"
    end
    end

    c = MyClass.new
    c[3] == 6

    MyClass["hello", "John"] == "Hi John, hello!"
    ```

    ActiveRecord::Migration[6.0] の場合は Migration クラスのクラスメソッドとして [] が定義されています。

    自分で定義した [] メソッドは、上のコード例からも分かるように「値を取り出す」という意味にする必要さえなく、普通のメソッドと同じように自由な処理を実装して構いません。

    ただ、やはり慣習的には、なんらかの値を複数保持するオブジェクトから指定した値を取り出すような意味合いの処理を実装することが多いです。

    質問②-2 合っています。`ActiveRecord::Migration::Compatibility::V6_0` の読み方は見た目では判断できない(どの部分についても、クラスでもモジュールでも成り立つ)ので、適宜確認してください。
  3. ちなみに、配列を my_array = [1, 2, 3] のように作るとき使われる角カッコは、メソッドではなく配列リテラル記法の一部です。混同しないようにしてください。
  4. @yosaku_ibs

    Questioner

    @uasi様

    こんにちは。
    いつも大変お世話になっております。
    早急なご回答いつもありがとうございます。

    ②-1のご回答について:衝撃です。。まさかarrayが`[ ]という名前のインスタンスメソッド`を持っているとは気づきもしませんでした。。
    また一つ新しい知識が増えました。誠にありがとうございます。

    質問②-2のご回答につきまして:モジュールの中にクラスが入って、さらにそのクラスの中にモジュールが入ったり...と、複雑なネストが存在するのだと気づきました。


    いつも丁寧にご説明くださり誠にありがとうございます。
    厚く御礼申し上げます。

Your answer might help someone💌