Forum: Ruby on Rails collection_select won't recover from form validation error

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
3ff9c2544554b13c6c7877e76684751b?d=identicon&s=25 JL Smith (Guest)
on 2006-12-27 06:42
I can't quite put my finger on what's happening here...I'm still trying
to grasp this framework.  With the way my controller methods are
written, I thought that since I get a form validation error, it would
kick off the "new" action and gather up those collection_select
collections again (although I'm not even sure if that's the
problem...nil.inject?).  I can add and edit all day but it bombs if I
have a validation error.  Much thanks in advance if anybody can shove me
in the right direction!

schema:
CREATE TABLE `tickets` (
  `id` int(11) NOT NULL,
  `title` varchar(255) default NULL,
  `details` text,
  `status_id` int(11) default NULL,
  `priority_id` int(11) default NULL,
  `created_at` datetime default NULL,
  `opened_at` datetime default NULL,
  `closed_at` datetime default NULL,
  `updated_at` datetime default NULL,
  `last_activity_at` datetime default NULL,
  PRIMARY KEY  (`id`),
  KEY `fk_ticket_status` (`status_id`),
  KEY `fk_ticket_priority` (`priority_id`),
  CONSTRAINT `fk_ticket_priority` FOREIGN KEY (`priority_id`) REFERENCES
`ticket_priorities` (`id`),
  CONSTRAINT `fk_ticket_status` FOREIGN KEY (`status_id`) REFERENCES
`ticket_statuses` (`id`)
);

CREATE TABLE `ticket_statuses` (
  `id` int(11) NOT NULL,
  `status` varchar(255) default NULL,
  PRIMARY KEY  (`id`)
);

CREATE TABLE `ticket_priorities` (
  `id` int(11) NOT NULL,
  `rank` int(11) default NULL,
  `priority` varchar(255) default NULL,
  PRIMARY KEY  (`id`)
);

Ticket model:
belongs_to :ticket_status, :foreign_key => "status_id"
belongs_to :ticket_priority, :foreign_key => "priority_id"
...
validates_presence_of :title, :details, :status_id, :priority_id


controller:
...
def new
  @ticket = Ticket.new
  @ticket_status = TicketStatus.find_all
  @ticket_priority = TicketPriority.find_all
end

def create
  @ticket = Ticket.new(params[:ticket])
  @ticket.opened_at = DateTime.now
  @ticket.closed_at = nil
  @ticket.last_activity_at = DateTime.now
  if @ticket.save
    flash[:success] = 'Ticket was successfully created.'
    redirect_to :action => 'list'
  else
    render :action => 'new'
  end
end
...

error:
NoMethodError in Ticket#create

Showing app/views/ticket/_form.rhtml where line #11 raised:
You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occured while evaluating nil.inject

Extracted source (around line #11):

8: <%= text_area 'ticket', 'details', {:style => "width: 325px"}  %></p>
9:
10: <p><label for="ticket[status_id]">Status</label><br/>
11: <%= collection_select("ticket", "status_id", @ticket_status, "id",
"status", {:prompt => "Select status..."}, {:style => "width: 150px"})
%></p>
12:
13: <p><label for="ticket[priority_id]">Priority</label><br/>
14: <%= collection_select("ticket", "priority_id", @ticket_priority,
"id", "priority", {:prompt => "Select priority..."}, {:style => "width:
150px"}) %></p>
86e084334c00a932a3675adbf769de67?d=identicon&s=25 Paul Corcoran (Guest)
on 2006-12-28 00:58
Try changing this:

collection_select("ticket", "priority_id", @ticket_priority,
"id", "priority", {:prompt => "Select priority..."}

to this:

collection_select(@ticket, :priority_id, @ticket_priority,
:id, :priority, {:prompt => "Select priority..."}

-Paul
3ff9c2544554b13c6c7877e76684751b?d=identicon&s=25 Lee Smith (smitjel)
on 2006-12-28 03:04
(Received via mailing list)
Paul Corcoran wrote:
> -Paul
>
> --
> Posted via http://www.ruby-forum.com/.

Hmm...now it won't even render the form.

 NameError in Ticket#new

Showing app/views/ticket/_form.rhtml where line #11 raised:

`@#<Ticket:0xb75ee748>' is not allowed as an instance variable name

Extracted source (around line #11):

8: <%= text_area 'ticket', 'details', {:style => "width: 325px"}
%></p>
9:
10: <p><label for="ticket[status_id]">Status</label><br/>
11: <%= collection_select(@ticket, :status_id, @ticket_status, :id,
:status, {:prompt => "Select status..."}, {:style => "width: 150px"})
%></p>
12:
13: <p><label for="ticket[priority_id]">Priority</label><br/>
14: <%= collection_select(@ticket, :priority_id, @ticket_priority, :id,
:priority, {:prompt => "Select priority..."}, {:style => "width:
150px"}) %></p>
3ff9c2544554b13c6c7877e76684751b?d=identicon&s=25 Lee Smith (smitjel)
on 2006-12-28 04:12
(Received via mailing list)
Well, I found one solution at least.  Something must be going on behind
the scenes that's not really obvious.

First, I tried this combination:
controller:
def new
  @ticket = Ticket.new
  @ticket_status = TicketStatus.find_all.collect {|s| [ s.status, s.id
] }
  @ticket_priority = TicketPriority.find_all.collect {|p| [ p.priority,
p.id ] }
end

view:
<p><label for="ticket[status_id]">Status</label><br/>
<%= select('ticket', 'status_id', @ticket_status, {:prompt => "Select
status..."}, {:style => "width: 150px"}) %></p>

<p><label for="ticket[priority_id]">Priority</label><br/>
<%= select('ticket', 'priority_id', @ticket_priority, {:prompt =>
"Select priority..."}, {:style => "width: 150px"}) %></p>

And that still didn't work.  So then I removed both of the collections
from the controller and did it all in the view like this and it works:
<p><label for="ticket[status_id]">Status</label><br/>
<%= select('ticket', 'status_id', TicketStatus.find_all.collect {|s| [
s.status, s.id ] }, { :include_blank => true }, {:style => "width:
150px"}) %></p>

<p><label for="ticket[priority_id]">Priority</label><br/>
<%= select('ticket', 'priority_id', TicketPriority.find_all.collect
{|p| [ p.priority, p.id ] }, { :include_blank => true }, {:style =>
"width: 150px"}) %></p>

I'm also not using the collection_select anymore but I guess when I
have a form validation error, it must do it's own thing somehow and
clears out those two .find_all collections.  It just doesn't feel right
to select data from the view like that...I'd really be interested to
know what happens when the validation fails and how I could put those
.find_all's in the controller and not the view...
This topic is locked and can not be replied to.