データベース操作がどういう風に実現されてるのか、特に SQL文はどうなってるのかを中心に追いかけてみる。
基本的にモデルの新規レコードの作製は ActiveRecord::Baseクラスを継承したモデルのクラスの create()メソッド(パブリック)を各種 attribute値を引数にして呼ぶ。
new して、saveするとか他の流れもあるけど。
ActiveRecord::Baseクラスの active_record/base.rbファイルをみる。
567行目から
def create(attributes = nil) if attributes.is_a?(Array) attributes.collect { |attr| create(attr) } else object = new(attributes) object.save object end end
createメソッド自体が new() して、save してる。saveメソッド(パブリック)は
1971行目から
def save create_or_update end
create_or_updateメソッドはプライベート。
2235行目から
private def create_or_update raise ReadOnlyRecord if readonly? result = new_record? ? create : update result != false end
この中の createメソッドは下記プライベートメソッド。上のパブリックメソッドとは別、引数の有り無しでこんな呼び分けできたのか。(updateメソッドも同様)
2257行目から
def create if self.id.nil? && connection.prefetch_primary_key?(self.class.table_name) self.id = connection.next_sequence_value(self.class.sequence_name) end quoted_attributes = attributes_with_quotes statement = if quoted_attributes.empty? connection.empty_insert_statement(self.class.table_name) else "INSERT INTO #{self.class.quoted_table_name} " + "(#{quoted_column_names.join(', ')}) " + "VALUES(#{quoted_attributes.values.join(', ')})" end self.id = connection.insert(statement, "#{self.class.name} Create", self.class.primary_key, self.id, self.class.sequence_name) @new_record = false id end
ここで INSERT文を作ってデータベースコネクションを呼び出している。コネクションの prefetch_primary_key?() とか empty_insert_statement() メソッドも使ってる。
このSQL文を、データベース呼び出しとは独立して取り出すのは無理っぽい。updateとか、SQL文を一度ローカル変数にいれないで直接コネクションのメソッド呼び出しの引数にかいてるので、さらに無理っぽい。