0

I'm tearing my hair out with this. I have three models: Game, Genre and GameGenre. Games have many Genres through GameGenres, Genres have many Games through GameGenres.

I have a games/new form which creates new game records. To this form, I've added a fields_for :game_genres section, which is supposed to allow the user to add game_genre relationship records to the new game records they create.

I think I'm pretty close to getting this working. At the moment, on submission it returns the error: "Game genres game can't be blank." I take this to mean the form is connecting to the game_genres table. I'm not sure why the controller isn't submitting the :game_id value.

Here's my code.

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 (excerpt)

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

As I understand it I do not need to add resources for game_genres to routes.rb.

This is the output from the rails development server when I try to submit a new game record:

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

As I understand it, the game_genres_attributes are properly nested and permitted. Why isn't game_id being recognised and saved?

Thanks so much to anyone who can help.


EDIT:

I got the form working by removing this validation from the GameGenre model:

validates :game_id, presence: true

I want this line in though, so I'm now wondering how to work around it?


EDIT 2:

I guess this is the answer (from http://makandracards.com/makandra/1346-popular-mistakes-when-using-nested-forms):

Nested records are validating the presence of their nesting parent record’s foreign key. If you do this, you cannot create a new parent record together with a new child record and will need to save the parent before you can save the child. You can opt to only show the nested child form when the parent has been saved before, or simply let go of the validation.

Neil Wheatley
  • 71
  • 1
  • 10
  • Try after adding this `game_genres_attributes: [ :id, :genre_id, :game_id]`..... and then see [this answer](http://stackoverflow.com/questions/2182428/rails-nested-form-with-has-many-through-how-to-edit-attributes-of-join-model) – Arup Rakshit Jun 30 '15 at 19:33
  • @ArupRakshit - Thanks but I had tried that line to no avail. I will read your linked answer in a moment. I have just got the form working by removing the line `validates :game_id, presence: true` from the GameGenre model. Ideally I want that validation in, so how can I work around it? – Neil Wheatley Jun 30 '15 at 19:44
  • Need to check the full code.. sometimes at least me not able to help by looking at the RoR post. Most the problem I solved by doing _debugging_ .. Rails app is a mixture of lots of things.. So need to debug to help.. Only these code wouldn't help me to help you.. :/ – Arup Rakshit Jun 30 '15 at 19:47
  • you need to pass the `game_id` while submitting the form.. see it is absent here `"game_genres_attributes"=>{"0"=>{"genre_id"=>"8"}`.. – Arup Rakshit Jun 30 '15 at 19:48
  • @ArupRakshit But the game_id doesn't exist until after the new game record is saved... – Neil Wheatley Jun 30 '15 at 19:50
  • @ArupRakshit how do I pass it? – Neil Wheatley Jun 30 '15 at 19:55
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/82016/discussion-between-neil-wheatley-and-arup-rakshit). – Neil Wheatley Jun 30 '15 at 19:57

0 Answers0