ActiveRecordの内部的な仕組みを調べてみた
なにこれ
Ruby on RailsにはActive RecordというアプリケーションとDBを繋げるORMが使用できます。
この記事は、Active Recordの内部的な仕組みをコードを見ながら調べていきます。
内容
1 Modelの作成 ~ ActiveRecord::Base
Modelクラスの作成からActive Recordを使用するまでの流れを確認します。
user.rb
class User < ApplicationRecord ・・・①
end
①Userクラスを作成するときに、ApplicationRecordを継承しています。
継承元のApplicationRecordは以下のようになっています。
application_record.rb
class ApplicationRecord < ActiveRecord::Base ・・・②
self.abstract_class = true
end
②ApplicationRecordはActiveRecord::Baseを継承しています。
これが、ActiveRecordの基になります。
2 ActiveRecord::Base ~ ActiveRecord::Relation
ActiveRecord::Baseのコードはこちらになります。
以下は一部抜粋です。
・
・
・
class Base
・
・
・
extend Delegation::DelegateCache ・・・①
・
・
・
end
①extendしているDelegation::DelegateCache
がActiveRecord::Relationを呼び出している部分になります。
Delegation::DelegateCachenのコードはこちらになります。
以下は一部抜粋です。
・
・
・
module DelegateCache # :nodoc:
・
・
・
def initialize_relation_delegate_cache
@relation_delegate_cache = cache = {}
[
ActiveRecord::Relation, ・・・②
ActiveRecord::Associations::CollectionProxy,
ActiveRecord::AssociationRelation,
ActiveRecord::DisableJoinsAssociationRelation
].each do |klass|
delegate = Class.new(klass) {
include ClassSpecificRelation
}
include_relation_methods(delegate)
mangled_name = klass.name.gsub("::", "_")
const_set mangled_name, delegate ・・・③
private_constant mangled_name
cache[klass] = delegate
end
end
・
・
・
②ActiveRecord::Relation
のインスタンスをClassSpecificRelation
をincludeした形で作成しています。
③インスタンス名をモデル名::ActiveRecord_Relation
のフォーマットで保存しています。
今回の例では、User::ActiveRecord_Relation
が作成されます。
つまり、モデルクラスが作成されるタイミングで、モデル名::ActiveRecord_Relation
が作成されて、このインスタンスを利用してActiveRecord::Relation
内の各メソッドを利用できます。
3 ActiveRecord::Relation
ActiveRecord::Relationのコードはこちらになります。
以下はnewメソッドのコードになります。
def new(attributes = nil, &block)
if attributes.is_a?(Array)
attributes.collect { |attr| new(attr, &block) }
else
block = current_scope_restoring_block(&block)
scoping { _new(attributes, &block) }
end
end
findメソッドなど一部のメソッドは外部のファイルに分けられて、includeされています。
このように、ActiveRecordを利用してモデルクラスを作成した場合は、内部でActiveRecord::Relation
を利用して各メソッドを使用していることが分かりました。
以上!!!!!!!!!!