Ticket #6896: attr_readonly.diff
| File attr_readonly.diff, 7.4 kB (added by dcmanges, 2 years ago) |
|---|
-
test/associations_test.rb
old new 1126 1126 assert_equal 0, Topic.find(t1.id).replies.size 1127 1127 assert_equal 0, Topic.find(t2.id).replies.size 1128 1128 end 1129 1130 def test_belongs_to_counter_after_save 1131 topic = Topic.create("title" => "monday night") 1132 topic.replies.create("title" => "re: monday night", "content" => "football") 1133 assert_equal 1, Topic.find(topic.id).send(:read_attribute, "replies_count") 1129 1134 1135 topic.save 1136 assert_equal 1, Topic.find(topic.id).send(:read_attribute, "replies_count") 1137 end 1138 1139 def test_belongs_to_counter_after_update_attributes 1140 topic = Topic.create("title" => "37s") 1141 topic.replies.create("title" => "re: 37s", "content" => "rails") 1142 assert_equal 1, Topic.find(topic.id).send(:read_attribute, "replies_count") 1143 1144 topic.update_attributes("title" => "37signals") 1145 assert_equal 1, Topic.find(topic.id).send(:read_attribute, "replies_count") 1146 end 1147 1130 1148 def test_assignment_before_parent_saved 1131 1149 client = Client.find(:first) 1132 1150 apple = Firm.new("name" => "Apple") -
test/base_test.rb
old new 47 47 attr_accessible :phone_number 48 48 end 49 49 50 class ReadonlyTitlePost < Post 51 attr_readonly :title 52 end 53 50 54 class Booleantest < ActiveRecord::Base; end 51 55 52 56 class Task < ActiveRecord::Base … … 767 771 assert_nil TightDescendant.protected_attributes 768 772 assert_equal [ :name, :address, :phone_number ], TightDescendant.accessible_attributes 769 773 end 774 775 def test_readonly_attributes 776 assert_equal [ :title ], ReadonlyTitlePost.readonly_attributes 777 778 post = ReadonlyTitlePost.create(:title => "cannot change this", :body => "changeable") 779 post.reload 780 assert_equal "cannot change this", post.title 781 782 post.update_attributes(:title => "try to change", :body => "changed") 783 post.reload 784 assert_equal "cannot change this", post.title 785 assert_equal "changed", post.body 786 end 770 787 771 788 def test_multiparameter_attributes_on_date 772 789 attributes = { "last_read(1i)" => "2004", "last_read(2i)" => "6", "last_read(3i)" => "24" } … … 1136 1153 end 1137 1154 1138 1155 def test_increment_attribute 1139 assert_equal 1, topics(:first).replies_count1140 topics(:first).increment! :replies_count1141 assert_equal 2, topics(:first, :reload).replies_count1142 1143 topics(:first).increment(:replies_count).increment!(:replies_count)1144 assert_equal 4, topics(:first, :reload).replies_count1156 assert_equal 50, accounts(:signals37).credit_limit 1157 accounts(:signals37).increment! :credit_limit 1158 assert_equal 51, accounts(:signals37, :reload).credit_limit 1159 1160 accounts(:signals37).increment(:credit_limit).increment!(:credit_limit) 1161 assert_equal 53, accounts(:signals37, :reload).credit_limit 1145 1162 end 1146 1163 1147 1164 def test_increment_nil_attribute … … 1151 1168 end 1152 1169 1153 1170 def test_decrement_attribute 1154 topics(:first).increment(:replies_count).increment!(:replies_count) 1155 assert_equal 3, topics(:first).replies_count 1156 1157 topics(:first).decrement!(:replies_count) 1158 assert_equal 2, topics(:first, :reload).replies_count 1171 assert_equal 50, accounts(:signals37).credit_limit 1159 1172 1160 topics(:first).decrement(:replies_count).decrement!(:replies_count) 1161 assert_equal 0, topics(:first, :reload).replies_count 1173 accounts(:signals37).decrement!(:credit_limit) 1174 assert_equal 49, accounts(:signals37, :reload).credit_limit 1175 1176 accounts(:signals37).decrement(:credit_limit).decrement!(:credit_limit) 1177 assert_equal 47, accounts(:signals37, :reload).credit_limit 1162 1178 end 1163 1179 1164 1180 def test_toggle_attribute -
lib/active_record/associations.rb
old new 739 739 module_eval( 740 740 "before_destroy '#{reflection.name}.class.decrement_counter(\"#{cache_column}\", #{reflection.primary_key_name})" + 741 741 " unless #{reflection.name}.nil?'" 742 ) 742 ) 743 744 module_eval( 745 "#{reflection.class_name}.send(:attr_readonly,\"#{cache_column}\".intern) if defined?(#{reflection.class_name})" 746 ) 743 747 end 744 748 end 745 749 -
lib/active_record/base.rb
old new 569 569 read_inheritable_attribute("attr_accessible") 570 570 end 571 571 572 # Attributes listed as readonly can be set for a new record, but will be ignored in database updates afterwards. 573 def attr_readonly(*attributes) 574 write_inheritable_array("attr_readonly", attributes - (readonly_attributes || [])) 575 end 572 576 577 # Returns an array of all the attributes that have been specified as readonly. 578 def readonly_attributes 579 read_inheritable_attribute("attr_readonly") 580 end 581 573 582 # Specifies that the attribute by the name of +attr_name+ should be serialized before saving to the database and unserialized 574 583 # after loading from the database. The serialization is done through YAML. If +class_name+ is specified, the serialized 575 584 # object must be of that class on retrieval or +SerializationTypeMismatch+ will be raised. … … 1783 1792 def update 1784 1793 connection.update( 1785 1794 "UPDATE #{self.class.table_name} " + 1786 "SET #{quoted_comma_pair_list(connection, attributes_with_quotes(false ))} " +1795 "SET #{quoted_comma_pair_list(connection, attributes_with_quotes(false, false))} " + 1787 1796 "WHERE #{self.class.primary_key} = #{quote_value(id)}", 1788 1797 "#{self.class.name} Update" 1789 1798 ) … … 1995 2004 attributes.reject { |key, value| self.class.protected_attributes.include?(key.gsub(/\(.+/,"").intern) || attributes_protected_by_default.include?(key.gsub(/\(.+/, "")) } 1996 2005 end 1997 2006 end 2007 2008 # Removes attributes which have been marked as readonly. 2009 def remove_readonly_attributes(attributes) 2010 unless self.class.readonly_attributes.nil? 2011 attributes.reject { |key, value| self.class.readonly_attributes.include?(key.gsub(/\(.+/,"").intern) } 2012 else 2013 attributes 2014 end 2015 end 1998 2016 1999 2017 # The primary key and inheritance column can never be set by mass-assignment for security reasons. 2000 2018 def attributes_protected_by_default … … 2005 2023 2006 2024 # Returns copy of the attributes hash where all the values have been safely quoted for use in 2007 2025 # an SQL statement. 2008 def attributes_with_quotes(include_primary_key = true )2009 attributes.inject({}) do |quoted, (name, value)|2026 def attributes_with_quotes(include_primary_key = true, include_readonly_attributes = true) 2027 quoted = attributes.inject({}) do |quoted, (name, value)| 2010 2028 if column = column_for_attribute(name) 2011 2029 quoted[name] = quote_value(value, column) unless !include_primary_key && column.primary 2012 2030 end 2013 2031 quoted 2014 2032 end 2033 include_readonly_attributes ? quoted : remove_readonly_attributes(quoted) 2015 2034 end 2016 2035 2017 2036 # Quote strings appropriately for SQL statements.