<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xml:base="http://townx.org" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
 <title>townx - Showing validation errors for &amp;quot;belongs_to&amp;quot; drop-down boxes in Rails - Comments</title>
 <link>http://townx.org/blog/elliot/showing-validation-errors-belongs-to-drop-down-boxes-rails</link>
 <description>Comments for &quot;Showing validation errors for &quot;belongs_to&quot; drop-down boxes in Rails&quot;</description>
 <language>en</language>
<item>
 <title>Still no better solution?</title>
 <link>http://townx.org/blog/elliot/showing-validation-errors-belongs-to-drop-down-boxes-rails#comment-40282</link>
 <description>&lt;p&gt;I&#039;m stuck with the same issue here. Is there still no better way to achieve this?&lt;/p&gt;</description>
 <pubDate>Sun, 24 Jan 2010 18:44:31 -0600</pubDate>
 <dc:creator>Paddor</dc:creator>
 <guid isPermaLink="false">comment 40282 at http://townx.org</guid>
</item>
<item>
 <title>Thanks</title>
 <link>http://townx.org/blog/elliot/showing-validation-errors-belongs-to-drop-down-boxes-rails#comment-39940</link>
 <description>&lt;p&gt;This seems to do the trick, has this not been fixed yet in Rails 2? A google search about this problem yields very little information, i thought it would be a very common problem. Thats for the info.&lt;/p&gt;</description>
 <pubDate>Wed, 07 Oct 2009 10:58:44 -0500</pubDate>
 <dc:creator>Guest</dc:creator>
 <guid isPermaLink="false">comment 39940 at http://townx.org</guid>
</item>
<item>
 <title>Thanks for the suggestion. I</title>
 <link>http://townx.org/blog/elliot/showing-validation-errors-belongs-to-drop-down-boxes-rails#comment-14086</link>
 <description>&lt;p&gt;Thanks for the suggestion. I think I used to do this. Presumably you&#039;re suggesting:&lt;/p&gt;



&lt;pre&gt;
class Task &amp;lt; ActiveRecord::Base
  belongs_to :project
  validates_presence_of :project_id
  validates_associated :project
end
&lt;/pre&gt;



&lt;p&gt;The issue here is if you create a new project (without saving it), assign the project to the task, then try to save the task. Even if the task is valid, and the project is valid, the project doesn&#039;t have an ID yet; so project_id isn&#039;t set on the task; so the task won&#039;t save. If you do &lt;tt&gt;validates_presence_of :project&lt;/tt&gt; instead, you can create a new project then assign it to a new task without having to save the project; then save the whole lot together; the ID of the project automatically gets assigned to the task&#039;s project_id.&lt;/p&gt;

&lt;p&gt;It doesn&#039;t make much difference when you&#039;re working through forms, but can make a difference if you&#039;re working from a script or the command line; or if you want to add a new project and associated task simultaneously from one form, but don&#039;t want to have to save the project before you can save the task. It makes validation simpler in the long run, as you can leave it to the validates_* methods, rather than having to save the project, check it&#039;s valid, then save the task only if it&#039;s valid; and if the task isn&#039;t valid, and you shouldn&#039;t have saved it, roll back the project save. (This happened to me when working on a system which added one record to each of two tables from a single form, which is where I started noticing this behaviour.)&lt;/p&gt;</description>
 <pubDate>Wed, 28 Mar 2007 09:07:00 -0500</pubDate>
 <dc:creator>elliot</dc:creator>
 <guid isPermaLink="false">comment 14086 at http://townx.org</guid>
</item>
<item>
 <title>Use project_id</title>
 <link>http://townx.org/blog/elliot/showing-validation-errors-belongs-to-drop-down-boxes-rails#comment-14085</link>
 <description>&lt;p&gt;Why don&#039;t you use directly:&lt;/p&gt;



&lt;pre&gt;
  validates_presence_of :project_id
&lt;/pre&gt;



&lt;p&gt;?&lt;/p&gt;</description>
 <pubDate>Wed, 28 Mar 2007 08:47:53 -0500</pubDate>
 <dc:creator>Guest</dc:creator>
 <guid isPermaLink="false">comment 14085 at http://townx.org</guid>
</item>
<item>
 <title>Showing validation errors for &quot;belongs_to&quot; drop-down boxes in Rails</title>
 <link>http://townx.org/blog/elliot/showing-validation-errors-belongs-to-drop-down-boxes-rails</link>
 <description>&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; See the comments for an explanation of why I&#039;m not doing &lt;tt&gt;validates_presence_of :project_id&lt;/tt&gt; (instead of &lt;tt&gt;validates_presence_of :project&lt;/tt&gt;). I&#039;m prepared to be proved wrong on my assertions there, but they seem to hold up to my testing.&lt;/p&gt;

&lt;p&gt;A common Rails pattern is to have two models with a &lt;tt&gt;has_many&lt;/tt&gt;/&lt;tt&gt;belongs_to&lt;/tt&gt; association, e.g.&lt;/p&gt;



&lt;pre&gt;
class Task &amp;lt; ActiveRecord::Base
  belongs_to :project
  validates_presence_of :project
  validates_associated :project
end

class Project &amp;lt; ActiveRecord::Base
  has_many :tasks
  validates_presence_of :name
end
&lt;/pre&gt;



&lt;p&gt;Then in the form for creating/editing a task, you might provide a drop-down box to select the associated project in the view, and display project error messages underneath it:&lt;/p&gt;



&lt;pre&gt;
&amp;lt;p&amp;gt;Project: &amp;lt;%= collection_select :task, :project_id, Project.find(:all), :id, :name %&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;%= error_message_on :task, :project %&amp;gt;
&lt;/pre&gt;



&lt;p&gt;Now if you try to save a task, you&#039;ll get the appropriate error message if you fail to select a project; also, if an invalid project gets assigned (e.g. invalid &lt;span class=&quot;caps&quot;&gt;URL &lt;/span&gt;or incomplete &lt;tt&gt;Project&lt;/tt&gt; instance), you&#039;ll get a validation error. I think this in uncontroversial.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;span class=&quot;caps&quot;&gt;BUT&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If an error occurs on the project associated with the task, although you get an error message in the view, the drop-down box isn&#039;t highlighted (as it is with other fields). This is because the highlighting is done by looking at the &lt;tt&gt;errors&lt;/tt&gt; object associated with the task, finding errors for any fields in the form with the same name, then altering the &lt;span class=&quot;caps&quot;&gt;HTML &lt;/span&gt;for that field. So if there is an error for &lt;tt&gt;description&lt;/tt&gt; and there&#039;s a field called &lt;tt&gt;task[description]&lt;/tt&gt;, that field gets an extra &lt;span class=&quot;caps&quot;&gt;HTML &lt;/span&gt;&amp;lt;div&amp;gt; wrapped round it, e.g.&lt;/p&gt;



&lt;pre&gt;
&amp;lt;div class=&amp;quot;fieldWithErrors&amp;quot;&amp;gt;
&amp;lt;input id=&amp;quot;task_description&amp;quot; name=&amp;quot;task[description]&amp;quot; size=&amp;quot;30&amp;quot; 
type=&amp;quot;text&amp;quot; value=&amp;quot;&amp;quot; /&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/pre&gt;



&lt;p&gt;The issue with my task and project is that the validation errors are added for the &lt;tt&gt;project&lt;/tt&gt;attribute on the &lt;tt&gt;Task&lt;/tt&gt; instance; but there isn&#039;t an &lt;span class=&quot;caps&quot;&gt;HTML &lt;/span&gt;form field called &lt;tt&gt;task[project]&lt;/tt&gt;: the drop-down is actually called &lt;tt&gt;task[project_id]&lt;/tt&gt;. I tried to create a select element called &lt;tt&gt;task[project]&lt;/tt&gt; instead, but this doesn&#039;t work (ActiveRecord complains that it is expecting a &lt;tt&gt;Project&lt;/tt&gt; and you supplied a &lt;tt&gt;String&lt;/tt&gt;).&lt;/p&gt;

&lt;p&gt;My solution is to copy any &lt;tt&gt;project&lt;/tt&gt; error for the &lt;tt&gt;Task&lt;/tt&gt; to an error for &lt;tt&gt;project_id&lt;/tt&gt;. I did this in the model, in the &lt;tt&gt;after_validation&lt;/tt&gt; callback, like this:&lt;/p&gt;



&lt;pre&gt;
class Task &amp;lt; ActiveRecord::Base
  belongs_to :project
  validates_presence_of :project
  validates_associate :project

  def after_validation
    project_error = errors.on(:project)
    errors.add(:project_id, project_error) if project_error
  end
end
&lt;/pre&gt;



&lt;p&gt;This works fine: now any errors for the project are reflected onto project_id, so the &lt;tt&gt;task[project_id]&lt;/tt&gt; drop-down box gets the error &amp;lt;div&amp;gt; (with &lt;tt&gt;class&lt;/tt&gt; attribute set to &quot;fieldWithErrors&quot;) wrapped around it. However, this doesn&#039;t feel quite right, and it makes me think I&#039;m missing something. Is there some Rails voodoo I&#039;ve overlooked which can be used to do this more cleanly?&lt;/p&gt;</description>
 <comments>http://townx.org/blog/elliot/showing-validation-errors-belongs-to-drop-down-boxes-rails#comments</comments>
 <category domain="http://townx.org/tech">tech</category>
 <pubDate>Wed, 28 Mar 2007 05:26:08 -0500</pubDate>
 <dc:creator>elliot</dc:creator>
 <guid isPermaLink="false">627 at http://townx.org</guid>
</item>
</channel>
</rss>
