2009-05-03 45 views
2

我有一个叫做Contact的模型,has_one是这样的。如何让form.select在Rails中返回一个模型?

class Contact < ActiveRecord::Base 
    has_one :guest, :class_name => "Contact", :foreign_key => "guest" 
end 

在我创建视图我使用的是选择辅助方法,列出了可能被选择作为像这样客人的所有联系人...

<% 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 %> 

每当这个表单提交,我得到一个错误表示它期待一个联系人,但得到一个字符串。

在将当前联系人保存到数据库之前,我应该在何处以及如何将表单提交的字符串转换为联系人?

回答

6

当您在Rails中创建关联(如has_one)时,会为您的对象动态生成某些方法以方便分配。

现在,您使用的方法是

@contact.guest = @guest 

以及您的联系对象能接收另一个ActiveRecord的对象,它可能与自身关联。你正在尝试做什么,在包装模型对象的窗体中,这种方法很“假”。 (从参数中输入的信息是以字符串形式输入的,这就是为什么你会得到这个错误)

有几种方法可以执行此操作。第一个是使用嵌套的模型属性。 。 。复杂的形式,允许你在你正在使用的form_for(使用fields_for表单助手)中包装一个子关联。这方面的一个解释是需要很长时间打字了,幸好有复杂的形式令人难以置信的免费资源:,

Railscasts Complex Forms part 1

Railscasts Complex Forms part 2

Railscasts Complex Forms part 3

此外,如果你正在使用Rails 2.3然后检查一下“accepts_nested_attributes_for”的一些信息。 。 。现在有一个明显的缺乏教程,但我想2.3版的发布将会有很多。这个方便的小助手将删除Ryan在他的屏幕中使用的大约一半的代码,以使表单接受一个从属模型。

最后有一个解决方法。如果你的关系很简单,如果你想要关联的客人已经在数据库中,并且你不需要从你使用的表单创建新的关系,那么你可以使用类似虚拟属性的东西。在您的形式,简单地改变你的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 

这将分配ActiveRecord的模型,而无需执行复杂的形式来为你做!

+1

是的。我的用例是解决方案场景......谢谢。 – 2009-05-04 22:30:37

相关问题