我有两个资源:主题和帖子。 我试图找出如何通过Post控制器创建主题。 模型看起来像这样:
class Topic < ActiveRecord::Base
has_many :posts, :dependent => :destroy
validates :name, :presence => true,
:length => { :maximum => 32 }
attr_accessible :name
end
class Post < ActiveRecord::Base
belongs_to :topic, :touch => true
has_many :comments, :dependent => :destroy
accepts_nested_attributes_for :topic
attr_accessible :name, :title, :content, :topic
end
帖/ _form.html.erb:
<%= simple_form_for @post do |f| %>
<h1>Create a Post</h1>
<%= f.input :name, :label => false, :placeholder => "Name" %>
<%= f.input :title, :label => false, :placeholder => "Title" %>
<%= f.input :content, :label => false, :placeholder => "Content" %>
<%= f.input :topic, :label => false, :placeholder => "Topic" %>
<%= f.button :submit, "Post" %>
<% end %>
posts_controller.rb#创建:
def create
@post = Post.new(params[:topic])
respond_to do |format|
if @post.save
format.html { redirect_to(@post, :notice => 'Post was successfully created.') }
else
format.html { render :action => "new" }
end
end
end
使用posts / _form.html.erb我可以创建帖子,但不会随之创建相关主题。任何人都可以告诉我为什么我会得到这种行为,并可能如何纠正它?我正在使用Ruby 1.9.2,Rails 3.0.7和simple_form gem。
答案 0 :(得分:3)
Railscasts有几个关于这个问题的剧集。 第16集(需要订阅)
源代码: https://github.com/railscasts/016-virtual-attributes-revised
这一集 http://railscasts.com/episodes/57-create-model-through-text-field
视图/产品/与_form.rhtml
<p>
<label for="product_category_id">Category:</label><br />
<%= f.collection_select :category_id, Category.find(:all), :id, :name, :prompt => "Select a Category" %>
or create one:
<%= f.text_field :new_category_name %>
</p>
模型/ product.rb
belongs_to :category
attr_accessor :new_category_name
before_save :create_category_from_name
def create_category_from_name
create_category(:name => new_category_name) unless new_category_name.blank?
end
我认为Ryan在类别上的解决方案比@nathanvda的选项更优雅1.因为它处理Model中的数据而不是Controller。如果您需要在不同的控制器/操作中执行相同的工作,您将看到好处。
答案 1 :(得分:2)
根据您的想法,我可以看到两个选项。
选项1:使用文本框创建或查找现有主题(如您所见)。在您的控制器中,您可以编写如下内容:
def create
topic_name = params[:post].delete(:topic)
@topic = Topic.find_or_create_by_name(topic_name)
@post = Post.new(params[:post])
@post.topic = @topic
if @post.save
format.html { redirect_to(@post, :notice => 'Post was successfully created.') }
else
format.html { render :action => "new" }
end
end
这是快速而肮脏的方式。对于您键入的每个topic
,它会尝试按名称查找该主题,或者创建并分配该主题。但是,这很容易出错。如果您的主题集有限,则有一种更简单的方法。
选项2:使用选择框,可用主题列表。在您的视图中写道:
<%= simple_form_for @post do |f| %>
<h1>Create a Post</h1>
<%= f.input :name, :label => false, :placeholder => "Name" %>
<%= f.input :title, :label => false, :placeholder => "Title" %>
<%= f.input :content, :label => false, :placeholder => "Content" %>
<%= f.association :topic %>
<%= f.button :submit, "Post" %>
<% end %>
这将呈现包含可能主题的选择框。在你的控制器中你只需要写:
def create
@post = Post.new(params[:post])
if @post.save
format.html { redirect_to(@post, :notice => 'Post was successfully created.') }
else
format.html { render :action => "new" }
end
end
虽然第二个选项非常简单,但动态添加主题却不那么容易。你可以在两者之间做一些事情,使用一个自动填充字段,如果它们存在则允许查找值,或者如果它们不存在则添加新值。
希望这有帮助。
答案 2 :(得分:1)
您是否在服务器日志中收到批量分配错误?您可能需要将:topic_attributes添加到attr_accessible列表中。