如何使form.select在Rails中返回一个模型?

Jas*_*yon 2 forms select ruby-on-rails

我有一个名为Contact的模型,有这样的客人.

class Contact < ActiveRecord::Base
  has_one :guest, :class_name => "Contact", :foreign_key => "guest"
end
Run Code Online (Sandbox Code Playgroud)

在我的创建视图中,我使用select helper方法列出所有可以选择为guest的联系人,如此...

<% form_for(@contact) do |f| %>
  <%= f.error_messages %>
    ...
    <p>
        <%= f.label :guest %><br />
        <% @guests = Contact.find(:all, :order => "lastname").map { |u| [u.lastname + ', ' + u.firstname, u.id] } %>
        <%= f.select :guest, @guests, {:include_blank => true} %>
    </p>
    ...
<% end %>
Run Code Online (Sandbox Code Playgroud)

每当提交此表单时,我都会收到一条错误消息,说它正在等待联系但是有一个字符串.

在将当前联系人保存到数据库之前,应该将表单提交的字符串转换为联系人的位置和方式?

Bus*_*ark 6

在Rails中创建关联时,例如has_one,有一些为对象动态生成的方法,以便于分配.

现在,您正在使用的方法是

@contact.guest = @guest
Run Code Online (Sandbox Code Playgroud)

并且您的联系对象期望接收可能与其关联的另一个ActiveRecord对象.你想要做的是,在你的形式包装模型对象时,这种方法是"假的".(来自params的信息以字符串形式出现,这就是你收到错误的原因)

有几种方法可以实现这一点.第一个是使用嵌套模型属性...复杂的表单,允许您在form_for您正在使用的内容中包装子关联(使用fields_for表单帮助程序).对此进行解释需要花费很长时间才能打字,幸运的是,复杂表格上有令人难以置信的免费资源:

Railscasts复杂表单第1部分

Railscasts复杂表单第2部分

Railscasts Complex Forms第3部分

此外,如果您使用的是Rails 2.3,请查看有关" accepts_nested_attributes_for"的一些信息...现在有一个明显缺乏教程,但我想,随着2.3的发布,将有很多即将到来.这个方便的小助手将削减Ryan在他的屏幕演员中使用的代码的大约一半,以使表单接受一个次级模型.

最后有一个解决方法.如果您的关系很简单,如果要关联的guest虚拟机已经在数据库中,并且您不需要从正在使用的表单创建新的guest虚拟机,那么您可以使用类似虚拟属性的内容.在您的表单中,只需将您更改f.select :guest为类似的内容f.select :guest_select并在模型中实现方法:

def guest_select=(incoming_id_from_form)
  contact = Contact.find(incoming_id_from_form)
  self.guest = contact
end
Run Code Online (Sandbox Code Playgroud)

这将分配ActiveRecord模型,而无需为您执行复杂的表单!