Rails app使用表单fields_for section和collection_select创建连接记录(has_many through)

时间:2015-06-30 18:54:52

标签: ruby-on-rails forms

我正用这个撕掉我的头发。我有三个模型:GameGenreGameGenre。游戏通过GameGenres有很多类型,类型通过GameGenres有许多游戏。

我有games/new表格可以创建新的游戏记录。在这个表单中,我添加了一个fields_for :game_genres部分,该部分允许用户将game_genre关系记录添加到他们创建的新游戏记录中。

我认为我非常接近这个工作。目前,在提交时它返回错误:“游戏类型游戏不能为空。”我认为这意味着表单连接到game_genres表。我不确定为什么控制器没有提交:game_id值。

这是我的代码。

new.html.erb

<%= form_for(@game) do |f| %>

  <%= render 'shared/error_messages', object: f.object %>

  <div class="form-group">
    <%= f.label :title_en, "Game title (English)" %>
    <%= f.text_field :title_en, class: 'form-control',
                            placeholder: "E.g. Marble Madness" %>
  </div>

  <div class="form-group">
    <%= f.label :year, "Year" %>
    <%= f.select :year, options_for_select((1950..2017).reverse_each),
                                  {},
                                  {:class => 'form-control'} %>
  </div>

  <div class="form-group">
    <%= f.label :description_en, "Summary" %>
    <%= f.text_area :description_en, class: 'form-control' %>
  </div>

  <hr />

  <div class="form-group">
    <%= f.fields_for :game_genres do |gf| %>

      <%= gf.label :genre_id, "Select a genre" %>
      <%= gf.collection_select(:genre_id, Genre.all, :id, :name,
            {},
            {:class => "form-control"}) %>
    <% end %>
  </div>

  <%= f.submit "Save", class: "btn btn-primary center-block" %>

<% end %>

games_controller.rb (摘录)

def new
  @game = current_user.games.build
  @game.game_genres.build
end

def create
  @game = current_user.games.build(game_params)
  if @game.save
    flash[:success] = "Game saved: #{@game.title_en} (#{@game.year})"
    redirect_to game_path(@game.id)
  else
    render 'new'
  end
end

private

  def game_params
    params.require(:game).permit(:title_en, :year, :description_en,
                      game_genres_attributes: [:genre_id])

game.rb

class Game < ActiveRecord::Base
  belongs_to :user

  has_many :game_genres,  foreign_key:  :game_id,
                          dependent: :destroy

  has_many :genres, through: :game_genres

  accepts_nested_attributes_for :game_genres,
                                allow_destroy: true

genre.rb

class Genre < ActiveRecord::Base
  belongs_to :user

  has_many :game_genres,  foreign_key:  :genre_id,
                          dependent: :destroy

  has_many :games, through: :game_genres

game_genre.rb

class GameGenre < ActiveRecord::Base

  belongs_to :game, inverse_of: :game_genres
  belongs_to :genre, inverse_of: :game_genres

据我了解,我不需要将game_genres的资源添加到routes.rb。

当我尝试提交新的游戏记录时,这是rails开发服务器的输出:

Started POST "/games" for ::1 at 2015-06-30 18:59:24 +0100
Processing by GamesController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"cUbIu3i9niI0R8b9E3KZeYEbNpx8NDj9Jx1MeGvylYDKQj54d3BwSdLsMiPsRBoUTzoTEuMGTk5/KTKAXH7DMA==", "game"=>{"title_en"=>"fdsdcdc", "year"=>"2017", "description_en"=>"dsdc", "game_genres_attributes"=>{"0"=>{"genre_id"=>"8"}}}, "commit"=>"Save"}
  User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1  ORDER BY "users"."id" ASC LIMIT 1  [["id", 1]]
   (0.1ms)  BEGIN
  Genre Load (0.3ms)  SELECT  "genres".* FROM "genres" WHERE "genres"."id" = $1  ORDER BY "genres"."name" ASC LIMIT 1  [["id", 8]]
   (0.1ms)  ROLLBACK
  Rendered shared/_error_messages.html.erb (0.6ms)
  Genre Load (0.3ms)  SELECT "genres".* FROM "genres"  ORDER BY "genres"."name" ASC

据我了解,game_genres_attributes已正确嵌套并允许。为什么不识别和保存game_id?

非常感谢能够提供帮助的任何人。

修改

我通过从GameGenre模型中删除此验证来使表单正常工作:

validates :game_id, presence: true

我想要这条线,所以我现在想知道如何解决它?

编辑2:

我想这是答案(来自http://makandracards.com/makandra/1346-popular-mistakes-when-using-nested-forms):

  

嵌套记录正在验证其嵌套父级的存在   记录的外键。如果执行此操作,则无法创建新父级   与新的儿童记录一起记录并需要保存   父母可以保存孩子。你可以选择只显示   父节点之前保存的嵌套子表单,或者只是让它   进行验证。

0 个答案:

没有答案