Both forms of new do the same thing (though your code does not) just in different ways.
model = Model.new(key1: value1, key2: value2) makes a new object, initializes it with the given values, and returns the new object.
model = Model.new { |m|
m.key1 = value1
m.key2 = value2
}
Makes a new object, and passes it to the block uninitialized. The block can now initialize the object in any way it pleases. Then the new, initialized object is returned.
The block form just offers more flexibility.
Why not just write this?
model = Model.new
model.key1 = value1
model.key2 = value2
If there is an after_initialize callback it will be called after new and before the object is initialized. That may cause problems because the object is not yet initialized.
But its really for create:
model = Model.create
model.key1 = value1
model.key2 = value2
create will call many callbacks on the uninitialized object, and it may violate database constraints such as not null.
Back to your code: the problem is you've tried to separate statements with commas in order to cram it into one line.
validation_code = ValidationCode.new { |v|
v.email = params[:email], v.kind = 'sign_in', v.verify_code = code
^ ^
}
v.kind and v.verify_code are fine, but v.email is an Array. You don't need the [] to make an Array. Ruby has parsed your code as:
v.email = [ params[:email], v.kind = 'sign_in', v.verify_code = code ]
Let's do the equivalent in IRB.
3.1.2 :001 > a = 4, b = 8, c = 12
=> [4, 8, 12]
3.1.2 :002 > a
=> [4, 8, 12]
3.1.2 :003 > b
=> 8
3.1.2 :004 > c
=> 12
3.1.2 :005 >
Instead, use semicolons to separate statements.
validation_code = ValidationCode.new { |v|
v.email = params[:email]; v.kind = 'sign_in'; v.verify_code = code
}
Better yet, use newlines for clarity.
validation_code = ValidationCode.new { |v|
v.email = params[:email]
v.kind = 'sign_in'
v.verify_code = code
}