• J
    Fix undefined method `to_i' introduced since 3.2.8 · 8d98c83b
    Jason Stirk 提交于
    This commit fixes a bug introduced in 96a13fc7 which breaks behaviour of
    integer fields.
    
    In 3.2.8, setting the value of an integer field to a non-integer (eg.
    Array, Hash, etc.) would default to 1 (true) :
    
        # 3.2.8
        p = Post.new
        p.category_id = [ 1, 2 ]
        p.category_id # => 1
        p.category_id = { 3 => 4 }
        p.category_id # => 1
    
    In 3.2.9 and above, this will raise a NoMethodError :
    
        # 3.2.9
        p = Post.new
        p.category_id = [ 1, 2 ]
    
        NoMethodError: undefined method `to_i' for [1, 2]:Array
    
    Whilst at first blush this appear to be sensible, it combines in bad
    ways with scoping.
    
    For example, it is common to use scopes to control access to data :
    
        @collection = Posts.where(:category_id => [ 1, 2 ])
        @new_post = @collection.new
    
    In 3.2.8, this would work as expected, creating a new Post object
    (albeit with @new_post.category_id = 1). However, in 3.2.9 this will
    cause the NoMethodError to be raised as above.
    
    It is difficult to avoid triggering this error without descoping before
    calling .new, breaking any apps running on 3.2.8 that rely on this
    behaviour.
    
    This patch deviates from 3.2.8 in that it does not retain the somewhat
    spurious behaviour of setting the attribute to 1. Instead, it explicitly
    sets these invalid values to nil :
    
        p = Post.new
        p.category_id = [ 1, 2 ]
        p.category_id # => nil
    
    This also fixes the situation where a scope using an array will
    "pollute" any newly instantiated records.
    
        @new_post = @collection.new
        @new_post.category_id # => nil
    
    Finally, 3.2.8 exhibited a behaviour where setting an object to an
    integer field caused it to be coerced to "1". This has not been
    retained, as it is spurious and surprising in the same way that setting
    Arrays and Heshes was :
    
        c = Category.find(6)
        p = Post.new
    
        # 3.2.8
        p.category_id = c
        p.category_id # => 1
    
        # This patch
        p.category_id = c
        p.category_id # => nil
    
    This commit includes explicit test cases that expose the original issue
    with calling new on a scope that uses an Array. As this is a common
    situation, an explicit test case is the best way to prevent regressions
    in the future.
    
    It also updates and separates existing tests to be explicit about the
    situation that is being tested (eg. AR objects vs. other objects vs.
    non-integers)
    8d98c83b
column.rb 10.3 KB