我是 Ruby on Rails 的初学者。目前,我有以下问题:我有一个类 Game
,其中包含交替的图片和句子数组。我希望创建新 Game
的用户需要提供一张起始图片或句子。如果他不这样做,我不想将新创建的游戏保存到数据库中。
class Game < ActiveRecord::Base
has_many :sentences
has_many :paintings
validates_inclusion_of :starts_with_sentence, :in => [true, false]
[...]
end
我的方法是,在/games/new 上,用户必须先给出一幅画或一个句子,但我不确定如何强制执行此操作,尤其是如何创建和保存子对象与父对象合二为一步。
最佳答案
所以你有两个问题。第一个(尽管在您的问题中是第二个)是“如何一步创建和保存子对象以及父对象。”这是一个常见的模式,看起来像这样:
class Game < ActiveRecord::Base
has_many :sentences
has_many :paintings
accepts_nested_attributes_for :sentences, :paintings # <-- the magic
end
然后在
views/games/new.html.erb
中,你可以有这样的东西:<%= form_for :game do |f| %>
<%= label :name, "Name your game!" %>
<%= text_field :name %>
<%= fields_for :sentence do |s| %>
<%= label :text, "Write a sentence!" %>
<%= text_field :text %>
<% end %>
<%= fields_for :painting do |s| %>
<%= label :title, "Name a painting!" %>
<%= text_field :title %>
<% end %>
<% end %>
当这个表单被提交时,Rails 将解释
POST
参数,你最终会得到一个看起来像这样的 params
对象:# params ==
{ :game => {
:name => "Hollywood Squares",
:sentence => {
:text => "Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo."
},
:painting => {
:title => "Les Demoiselles d'Avignon"
}
}
}
最后,在接收这些
params
的 Controller 中:def create
new_game = Game.create params[:game] # magic! the associated Sentence and/or
end # Painting will be automatically created
这是对您将要做什么的一个非常非常高级的窥视。嵌套属性有自己的 section in the docs 。
您的另一个问题是如何执行此操作。为此,您需要编写一些自定义验证。有两种方法可以做到这一点。最简单的方法是使用
validate
,例如:class Game < ActiveRecord::Base
# ...
validate :has_sentence_or_painting # the name of a method we'll define below
private # <-- not required, but conventional
def has_sentence_or_painting
unless self.sentences.exists? || self.paintings.exists?
# since it's not an error on a single field we add an error to :base
self.errors.add :base, "Must have a Sentence or Painting!"
# (of course you could be much more specific in your handling)
end
end
end
另一种方法是创建一个位于另一个文件中的自定义验证器类。如果您需要进行大量自定义验证,或者您想在多个类上使用相同的自定义验证,这将特别有用。这与单个方法 er 方法一起都包含在 Validations Rails Guide 中。
希望这有帮助!
关于ruby-on-rails-3 - Rails : Force user to create child object before saving parent,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/7851046/