ARのsaveとかupdate_attributeとか
ActiveRecordのsaveやupdate_attribute(s)がどのような仕組みになっているのかのメモ
環境
- rails1.2.3
ソースコード
# activerecord/lib/active_record/base.rb 1545 def save 1546 create_or_update 1547 end # 中略 1584 def update_attribute(name, value) 1585 send(name.to_s + '=', value) 1586 save 1587 end # 中略 1591 def update_attributes(attributes) 1592 self.attributes = attributes 1593 save 1594 end # 中略 1787 private 1788 def create_or_update 1789 raise ReadOnlyRecord if readonly? 1790 result = new_record? ? create : update 1791 result != false 1792 end 1793 1794 # Updates the associated record with values matching those of the instance attributes. 1795 # Returns the number of affected rows. 1796 def update 1797 connection.update( 1798 "UPDATE #{self.class.table_name} " + 1799 "SET #{quoted_comma_pair_list(connection, attributes_with_quotes(false))} " + 1800 "WHERE #{connection.quote_column_name(self.class.primary_key)} = #{quote_value(id)}", 1801 "#{self.class.name} Update" 1802 ) 1803 end 1804 1805 # Creates a record with values matching those of the instance attributes 1806 # and returns its id. 1807 def create 1808 if self.id.nil? && connection.prefetch_primary_key?(self.class.table_name) 1809 self.id = connection.next_sequence_value(self.class.sequence_name) 1810 end 1811 1812 self.id = connection.insert( 1813 "INSERT INTO #{self.class.table_name} " + 1814 "(#{quoted_column_names.join(', ')}) " + 1815 "VALUES(#{attributes_with_quotes.values.join(', ')})", 1816 "#{self.class.name} Create", 1817 self.class.primary_key, self.id, self.class.sequence_name 1818 ) 1819 1820 @new_record = false 1821 id 1822 end
結局は、saveメソッドもupdate_atteribute(s)も全ては、createメソッドもしくは、updateメソッドを呼び出している
それらのメソッドの内容をもとに、SQLが走る
では、validation周りはどのように制御されているのか?
validationのソースコード
# activerecord/lib/active_record/validations.rb # module Validations 218 def self.included(base) # :nodoc: 219 base.extend ClassMethods 220 base.class_eval do 221 alias_method_chain :save, :validation 222 alias_method_chain :save!, :validation 223 alias_method_chain :update_attribute, :validation_skipping 224 end 225 end
saveメソッドやupdate_attributeメソッドがoverrideされている。
その内容は?
# activerecord/lib/active_record/validations.rb # module Validations 733 private 750 def save_with_validation(perform_validation = true) 751 if perform_validation && valid? || !perform_validation 752 save_without_validation 753 else 754 false 755 end 756 end
単にDBに突っ込む前にvalid?かどうかを見ている。
valid? #=> trueであればAR::Base#saveが実行される
さて、perform_validationは何をしているのか?
save(false)として呼び出したときに、validationを通さずに、DBに保存するようにしている。
# activerecord/lib/active_record/validations.rb # module Validations 733 private 771 def update_attribute_with_validation_skipping(name, value) 772 send(name.to_s + '=', value) 773 save(false) 774 end
update_attributeメソッドの場合、save(false)として呼び出しており、
validationを通らないので、誤った情報がDBに書き加えられることになる可能性があるので、要注意
最後までお読みいただきありがとうございました。