Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Check for Blank Record in form_for #7314

Merged
merged 1 commit into from

5 participants

Richard Schneeman Rafael Mendonça França Steve Klabnik Carlos Antonio da Silva thefool808
Richard Schneeman
Collaborator

If nil or an empty array is passed into form_for you get a horrible error message, this one is much more indicative of what the programmer needs to know to fix the problem.

ATP in actionpack

Screenshot goodness:

Rafael Mendonça França

@schneems seems good. Could you add tests to this feature?

Richard Schneeman
Collaborator

I added tests, also discovered the first implementation wouldn't catch the [nil, nil] case. Let me know if you have any other problems/questions.

Rafael Mendonça França

I think the message is not good. Because in the array case [:foo, nil] should brake too, and this is not empty. Maybe "Form object in cannot be nil"

Steve Klabnik
Collaborator

"cannot contain nil"? [:foo, nil] is not nil either.

Rafael Mendonça França

But this is not the Form object. When you pass an Array for the form helper the object is the last element of the array.

Steve Klabnik
Collaborator

Hmmmm.

Whatever, I want the error message to be blue. :p

Richard Schneeman
Collaborator

How about:

First argument in form cannot contain nil or be empty

It is technically correct for nil, [nil], and [:foo, nil]

Rafael Mendonça França

Seems better.

actionpack/test/template/form_helper_test.rb
@@ -1045,6 +1045,20 @@ def test_form_for_requires_block
end
end
+ def test_form_for_requires_arguments
+ error = assert_raises(ArgumentError) do
+ form_for(nil, :html => { :id => 'create-post' }) do
+ end
+ end
+
+ assert_match /cannot be nil or empty/, error.message

I think the blank line should be swapped - assertion should be right below assert_raises block).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Carlos Antonio da Silva

Seems a nice improvement :+1:

Richard Schneeman
Collaborator

Changed text, fixed whitespace.

Carlos Antonio da Silva

@schneems thanks, can you squash? Github shows me two commits (though both have the same desc).

actionpack/test/template/form_helper_test.rb
@@ -1045,6 +1045,20 @@ def test_form_for_requires_block
end
end
+ def test_form_for_requires_arguments
+ error = assert_raises(ArgumentError) do
+ form_for(nil, :html => { :id => 'create-post' }) do
+ end
+ end
+ assert_match /cannot be nil or empty/, error.message
Rafael Mendonça França Owner

I think these tests will break. The message is different. Can we assert all the message?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Richard Schneeman
Collaborator

Squashed, fixed tests. ATP

Richard Schneeman schneems check for nil or empty record in form_for
if nil or an empty array is passed into form_for you get a horrible error message, this one is much more indicative of what the programmer needs to know to fix the problem.
60b650b
Rafael Mendonça França rafaelfranca merged commit a6e0d8c into from
Rafael Mendonça França rafaelfranca merged commit 60b650b into from
thefool808

This change means that I can't use an ActiveRecord model that has a "blank" boolean attribute (if the attribute is true). A small consequence for an equally small gain.

Rafael Mendonça França

@thefool808 I din't get. I think we are checking only if the object is blank and not if the attribute of the object is blank.

thefool808
rails generate model Foo blank:boolean

form_for(Foo.new(:blank => true)) => ArgumentError, "First argument in form cannot contain nil or be empty"

This patch only checks whether blank? returns true on the object, not whether or not it is suitable for form_for. Not that important, but it crossed my mind when reading schneems blog post about this patch. Food for thought. Thanks for the reply.

Rafael Mendonça França

lol. I got the error. Yeah, maybe is better to not check blank? and only check:

raise ArgumentError, "First argument in form cannot contain nil or be empty" unless object
thefool808

I think you meant nil?. That's actually a really good solution, as a blank array will already be nil by that point ([].last) and a blank string will never get there. I'm just being nitpick-y for no good reason... Thanks for listening :)

Rafael Mendonça França

Oops. I forgot to change the copied code. Now it is right

thefool808

That's cool too.

Richard Schneeman
Collaborator

@thefool808 theoretically one could over-ride the nil? or is_a? or any other method on an object, but that doesn't make it a good idea. If someone makes a column named blank or present in their database they will have more issues than just in this one method. In this situation i believe you can pass non AR objects such as an empty string "". That would not get caught by a simple nil check

We need to support this use case too:

<%= form_for :person do |f| %>
Rafael Mendonça França

I think checking for the empty string is too defensive. I don't see why someone in the earth want to pass a string to a form_for call. We never encourage this in the documentation.

Richard Schneeman
Collaborator

Agreed, was just being paranoid. Both seem to catch the majority of invalid use-cases.

thefool808

A string or symbol will miss the safety check anyways. Also, I agree having a "blank" boolean attribute on a model is a terrible idea that maybe should never be considered, however I think overriding nil? is anti-ruby (i.e. most ruby developers will know not to do this, or at least understand the consequences, even if they've never used rails) whereas blank? is a rails construct.

Just checking for nil? will cover the most common case where an uninstantiated object being passed to form_for. Checking blank? does the same thing but has this tiny little (probably stupid to even point out) consequence where you could have a perfectly suitable object for form_for that gets rejected for no good reason.

Craig Sheen craigsheen referenced this pull request in plataformatec/devise
Closed

First argument in form cannot contain nil or be empty #2451

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Aug 11, 2012
  1. Richard Schneeman

    check for nil or empty record in form_for

    schneems authored
    if nil or an empty array is passed into form_for you get a horrible error message, this one is much more indicative of what the programmer needs to know to fix the problem.
This page is out of date. Refresh to see the latest.
1  actionpack/lib/action_view/helpers/form_helper.rb
View
@@ -423,6 +423,7 @@ def form_for(record, options = {}, &proc)
object = nil
else
object = record.is_a?(Array) ? record.last : record
+ raise ArgumentError, "First argument in form cannot contain nil or be empty" if object.blank?
object_name = options[:as] || model_name_from_record_or_class(object).param_key
apply_form_for_options!(record, object, options)
end
14 actionpack/test/template/form_helper_test.rb
View
@@ -1045,6 +1045,20 @@ def test_form_for_requires_block
end
end
+ def test_form_for_requires_arguments
+ error = assert_raises(ArgumentError) do
+ form_for(nil, :html => { :id => 'create-post' }) do
+ end
+ end
+ assert_equal "First argument in form cannot contain nil or be empty", error.message
+
+ error = assert_raises(ArgumentError) do
+ form_for([nil, nil], :html => { :id => 'create-post' }) do
+ end
+ end
+ assert_equal "First argument in form cannot contain nil or be empty", error.message
+ end
+
def test_form_for
form_for(@post, :html => { :id => 'create-post' }) do |f|
concat f.label(:title) { "The Title" }
Something went wrong with that request. Please try again.