Ticket #3196: multiple_associations_for_forms.patch
| File multiple_associations_for_forms.patch, 13.1 kB (added by benanderson.us@gmail.com, 3 years ago) |
|---|
-
actionpack/lib/action_view/helpers/form_helper.rb
old new 212 212 @object_name, @method_name = object_name.to_s, method_name.to_s 213 213 @template_object, @local_binding = template_object, local_binding 214 214 @object = object 215 if @object_name.sub!(/\[\]$/,"") 216 @auto_index = @template_object.instance_variable_get("@#{Regexp.last_match.pre_match}").id_before_type_cast 215 on = @object_name.clone 216 while on.sub!(/\[\]/,"") 217 @auto_indexes = Array.new if @auto_indexes == nil 218 on = Regexp.last_match.pre_match 219 poppers = @template_object.instance_variable_get("@#{on}").id_before_type_cast 220 @auto_indexes << poppers 221 @object_names = Array.new if @object_names == nil 222 @object_names << on 223 @object_name = on.clone 224 on = Regexp.last_match.post_match 217 225 end 218 226 end 219 227 … … 236 244 options["value"] = tag_value 237 245 options["checked"] = "checked" if value.to_s == tag_value.to_s 238 246 pretty_tag_value = tag_value.to_s.gsub(/\s/, "_").gsub(/\W/, "").downcase 239 options["id"] = @auto_index ? 240 "#{@object_name}_#{@auto_index}_#{@method_name}_#{pretty_tag_value}" : 241 "#{@object_name}_#{@method_name}_#{pretty_tag_value}" 247 if @auto_indexes 248 options["id"] = String.new 249 @auto_indexes.each_with_index do |ai, i| 250 options["id"] << "#{@object_names[i]}_#{ai}_" 251 end 252 options["id"] << "#{@method_name}_#{pretty_tag_value}" 253 else 254 options["id"] = "#{@object_name}_#{@method_name}_#{pretty_tag_value}" 255 end 256 if false 257 options["id"] = @auto_index ? 258 "#{@object_name}_#{@auto_index}_#{@method_name}_#{pretty_tag_value}" : 259 "#{@object_name}_#{@method_name}_#{pretty_tag_value}" 260 end 242 261 add_default_name_and_id(options) 243 262 tag("input", options) 244 263 end … … 300 319 end 301 320 302 321 def object 322 #puts "@object_name: #@object_name" 303 323 @object || @template_object.instance_variable_get("@#{@object_name}") 304 324 end 305 325 306 326 def value 307 327 unless object.nil? 308 object.send(@method_name) 328 o = object.send(@method_name) 329 #puts "o: #{o}" 330 o 309 331 end 310 332 end 311 333 … … 323 345 options["name"] ||= tag_name_with_index(options["index"]) 324 346 options["id"] ||= tag_id_with_index(options["index"]) 325 347 options.delete("index") 326 elsif @auto_index 327 options["name"] ||= tag_name_with_index (@auto_index)328 options["id"] ||= tag_id_with_index (@auto_index)348 elsif @auto_indexes 349 options["name"] ||= tag_name_with_index 350 options["id"] ||= tag_id_with_index 329 351 else 330 352 options["name"] ||= tag_name 331 353 options["id"] ||= tag_id … … 336 358 "#{@object_name}[#{@method_name}]" 337 359 end 338 360 339 def tag_name_with_index(index) 340 "#{@object_name}[#{index}][#{@method_name}]" 361 def tag_name_with_index 362 name = String.new 363 @auto_indexes.each_with_index do |ai, i| 364 if i == 0 365 name << "#{@object_names[i]}[#{ai}]" 366 else 367 name << "[#{@object_names[i]}][#{ai}]" 368 end 369 end 370 name << "[#{@method_name}]" 341 371 end 342 372 343 373 def tag_id 344 374 "#{@object_name}_#{@method_name}" 345 375 end 346 376 347 def tag_id_with_index(index) 348 "#{@object_name}_#{index}_#{@method_name}" 377 def tag_id_with_index 378 #"#{@object_name}_#{index}_#{@method_name}" 379 id = String.new 380 @auto_indexes.each_with_index do |ai, i| 381 id << "#{@object_names[i]}_#{ai}_" 382 end 383 id << "#{@method_name}" 349 384 end 350 385 end 351 386 -
actionpack/test/template/form_helper_test.rb
old new 14 14 alias_method :body_before_type_cast, :body unless respond_to?(:body_before_type_cast) 15 15 alias_method :author_name_before_type_cast, :author_name unless respond_to?(:author_name_before_type_cast) 16 16 end 17 Comment = Struct.new("Comment", :title, :author_name, :body, :secret, :written_on, :cost) 18 Comment.class_eval do 19 alias_method :title_before_type_cast, :title unless respond_to?(:title_before_type_cast) 20 alias_method :body_before_type_cast, :body unless respond_to?(:body_before_type_cast) 21 alias_method :author_name_before_type_cast, :author_name unless respond_to?(:author_name_before_type_cast) 22 end 17 23 end 18 24 19 25 def setup … … 29 35 @post.secret = 1 30 36 @post.written_on = Date.new(2004, 6, 15) 31 37 38 @comment = Comment.new 39 def @comment.errors() Class.new{ def on(field) field == "author_name" end }.new end 40 41 def @comment.id; 456; end 42 def @comment.id_before_type_cast; 456; end 43 44 @comment.title = "Goodbye World" 45 @comment.author_name = "" 46 @comment.body = "And here comes another hill..." 47 @comment.secret = 1 48 @comment.written_on = Date.new(1980, 6, 5) 49 32 50 @controller = Class.new do 33 51 def url_for(options, *parameters_for_method_reference) 34 52 "http://www.example.com" … … 176 194 177 195 def test_auto_index 178 196 pid = @post.id 197 cid = @comment.id 179 198 assert_dom_equal( 180 199 "<input id=\"post_#{pid}_title\" name=\"post[#{pid}][title]\" size=\"30\" type=\"text\" value=\"Hello World\" />", text_field("post[]","title") 181 200 ) 182 201 assert_dom_equal( 202 "<input id=\"post_#{pid}_comment_#{cid}_title\" name=\"post[#{pid}][comment][#{cid}][title]\" size=\"30\" type=\"text\" value=\"Goodbye World\" />", text_field("post[]comment[]","title") 203 ) 204 assert_dom_equal( 183 205 "<textarea cols=\"40\" id=\"post_#{pid}_body\" name=\"post[#{pid}][body]\" rows=\"20\">Back to the hill and over it again!</textarea>", 184 206 text_area("post[]", "body") 185 207 ) 186 208 assert_dom_equal( 209 "<textarea cols=\"40\" id=\"post_#{pid}_comment_#{cid}_body\" name=\"post[#{pid}][comment][#{cid}][body]\" rows=\"20\">And here comes another hill...</textarea>", 210 text_area("post[]comment[]", "body") 211 ) 212 assert_dom_equal( 187 213 "<input checked=\"checked\" id=\"post_#{pid}_secret\" name=\"post[#{pid}][secret]\" type=\"checkbox\" value=\"1\" /><input name=\"post[#{pid}][secret]\" type=\"hidden\" value=\"0\" />", 188 214 check_box("post[]", "secret") 189 215 ) 216 assert_dom_equal( 217 "<input checked=\"checked\" id=\"post_#{pid}_comment_#{cid}_secret\" name=\"post[#{pid}][comment][#{cid}][secret]\" type=\"checkbox\" value=\"1\" /><input name=\"post[#{pid}][comment][#{cid}][secret]\" type=\"hidden\" value=\"0\" />", 218 check_box("post[]comment[]", "secret") 219 ) 190 220 assert_dom_equal( 191 221 "<input checked=\"checked\" id=\"post_#{pid}_title_hello_world\" name=\"post[#{pid}][title]\" type=\"radio\" value=\"Hello World\" />", 192 222 radio_button("post[]", "title", "Hello World") 193 223 ) 224 assert_dom_equal( 225 "<input checked=\"checked\" id=\"post_#{pid}_comment_#{cid}_title_goodbye_world\" name=\"post[#{pid}][comment][#{cid}][title]\" type=\"radio\" value=\"Goodbye World\" />", 226 radio_button("post[]comment[]", "title", "Goodbye World") 227 ) 194 228 assert_dom_equal("<input id=\"post_#{pid}_title_goodbye_world\" name=\"post[#{pid}][title]\" type=\"radio\" value=\"Goodbye World\" />", 195 229 radio_button("post[]", "title", "Goodbye World") 196 230 ) 231 assert_dom_equal("<input id=\"post_#{pid}_comment_#{cid}_title_so_long_world\" name=\"post[#{pid}][comment][#{cid}][title]\" type=\"radio\" value=\"So Long World\" />", 232 radio_button("post[]comment[]", "title", "So Long World") 233 ) 197 234 end 198 235 199 236 def test_form_for -
activerecord/lib/active_record/base.rb
old new 243 243 # on to any new database connections made and which can be retrieved on both a class and instance level by calling +logger+. 244 244 cattr_accessor :logger 245 245 246 def self.load_hash(_h, key_in=nil) 247 if key_in == nil 248 key_in = self.to_s 249 end 250 h = _h.clone 251 if 0 == h.keys[0].to_i 252 h = Hash.new 253 h["1"] = _h 254 end 255 a = Array.new 256 h.each do |k, v| 257 c = eval("#{Inflector.camelize(key_in)}") 258 id = nil 259 pk = c.primary_key 260 id = v[pk] 261 if id 262 r = c.find(id) 263 else 264 r = c.new 265 end 266 a << r 267 v.each do |k2, v2| 268 if v2.is_a?(Hash) 269 m = Inflector.pluralize(k2) 270 children = self.load_hash(v2, k2) 271 if !children.is_a?(Array) 272 ch = Array.new 273 ch << children 274 children = ch 275 end 276 if false 277 childClass = children[0].class 278 children.each do |c| 279 if !origChildren.include?(c) 280 origChildren << children 281 end 282 end 283 end 284 origChildren = r.send("#{m}") 285 children.each do |c| 286 if !c.id 287 origChildren.push(c) 288 end 289 end 290 else 291 if k2 != pk 292 r.send("#{k2}=", v2) 293 end 294 end 295 end 296 r.save if id 297 end 298 if a.length == 0 299 return nil 300 else 301 return a 302 end 303 end 304 305 # Returns the connection currently associated with the class. This can 306 # also be used to "borrow" the connection to do database work unrelated 307 # to any of the specific Active Records. 308 def self.connection 309 retrieve_connection 310 end 311 312 # Returns the connection currently associated with the class. This can 313 # also be used to "borrow" the connection to do database work that isn't 314 # easily done without going straight to SQL. 315 def connection 316 self.class.connection 317 end 318 246 319 def self.inherited(child) #:nodoc: 247 320 @@subclasses[self] ||= [] 248 321 @@subclasses[self] << child -
activerecord/test/load_hash_test.rb
old new 1 require 'abstract_unit' 2 require 'fixtures/Developer' 3 require 'fixtures/Project' 4 require 'logger' 5 6 class LoadHashTest < Test::Unit::TestCase 7 fixtures :developers, :projects 8 9 cattr_accessor :logger 10 11 def setup 12 @david_before = Developer.find(1) 13 @active_record_before = Project.find(1) 14 @count_projects_before = @david_before.projects.length 15 @count_developers_before = Developer.count() 16 @h1 = { "1" => 17 { "id" => "1", 18 "name" => "update dev", 19 "project" => 20 { "2" => 21 { "id" => "1", 22 "name" => "cocoon", 23 "type" => ""}, 24 "3" => 25 { "name" => "myfaces", 26 "type" => "" } 27 } 28 }, 29 "4" => 30 { "name" => "new dev", 31 "project" => 32 { "5" => 33 { "name" => "struts", 34 "type" => "" }, 35 "6" => 36 { "name" => "tomcat", 37 "type" => "" } 38 } 39 } 40 } 41 @h2 = { "name" => "new dev", 42 "project" => 43 { "2" => 44 { "name" => "daddy", 45 "type" => ""}, 46 "3" => 47 { "name" => "baby", 48 "type" => "" } 49 } 50 } 51 @devs1 = Developer.load_hash(@h1) 52 @dev1 = Developer.load_hash(@h2) 53 end 54 55 def test_project_update 56 @devs1.each do |d| 57 d.projects.each do |p| 58 p.save 59 end 60 end 61 active_record_after = Project.find(1) 62 assert_not_equal(@active_record_before.name, active_record_after.name) 63 end 64 65 def test_correct_classes 66 assert_kind_of(Array, @devs1) 67 assert_kind_of(Array, @dev1) 68 @devs1.each do |d| 69 assert_kind_of(Developer, d) 70 d.projects.each do |p| 71 assert_kind_of(Project, p) 72 end 73 end 74 end 75 76 def test_dev_update 77 @devs1.each do |d| 78 d.save 79 end 80 david_after = Developer.find(1) 81 assert_not_equal(@david_before.name, david_after.name) 82 assert_equal(@count_projects_before + 1, david_after.projects.length) 83 developers_after = Developer.count() 84 assert_not_equal(@count_developers_before, developers_after) 85 end 86 87 def test_dev_insert 88 end 89 90 end 91 92 LoadHashTest.logger = ActiveRecord::Base.logger