Не удалось найти мир с 'id'=

У меня есть родительский объект World и дочерний объект State. Я пытаюсь создать новый объект State, и рельсы не находят идентификатор мира. Я пытаюсь сослаться на новую форму состояния со страницы мирового шоу, и URL-адрес показывает .../worlds/1/states/new, так почему же это не соответствует родительскому идентификатору? Ошибка предположительно исходит из этой строки в контроллере @world = World.find(params[:id]). Я даже пытался использовать (params[:world_id]).

Для краткости я размещаю здесь только соответствующий код.

мир.rb

class World < ApplicationRecord
  belongs_to :user
  has_many :states
end

гос.рб

class State < ApplicationRecord
  belongs_to :world
  belongs_to :user
end

States_controller.rb

class StatesController < ApplicationController
  before_action :set_state, only: [:show, :edit, :update, :destroy]
  before_action :authenticate_user!, except: [:index, :show]

  def index
    @states = State.all
  end

  def new
    @world = World.find(params[:id])
    @state = @world.states.build
  end

  def create
    @world = World.find(params[:id])
    @state = @world.states.build(state_params)
    @state.user = current_user

    respond_to do |format|
      if @state.save
        format.html { redirect_to @state, notice: 'State was successfully created.' }
      else
        format.html { render :new }
      end
    end
  end

  private
    def set_state
      @state = State.find(params[:id])
    end

    def state_params
      params.require(:state).permit(:name, :summary, :history, :population, :inception, :life_expectancy, :land_mass,
                                    :climate, :industry, :education, :mythology, :law, :culture, :world_id, :user_id)
    end
end 

Ссылка на форму нового состояния в worlds/show.html.erb:

<%= link_to 'New State', new_world_state_path(@world) %>

маршруты.rb

Rails.application.routes.draw do
  resources :states
  resources :worlds
  devise_for :users, path: '', path_names: { sign_in: 'login', sign_out: 'logout', sign_up: 'register' }
  root to: "home#index"

  resources :users
  resources :worlds do
    resources :states
  end
end

состояния/_form.html.erb

<div class="form">
  <%= form_for(state) do |f| %>
    <% if state.errors.any? %>
      <div id="error_explanation">
        <h2><%= pluralize(world.errors.count, "error") %> prohibited this state from being saved:</h2>

        <ul>
        <% state.errors.full_messages.each do |message| %>
          <li><%= message %></li>
        <% end %>
        </ul>
      </div>
    <% end %>

    <%= f.text_field :name, placeholder: 'Name' %><br />

    <fieldset>
      <legend>Basic Info</legend>
        <%= f.text_area :summary, placeholder: 'Summary About', rows: 6 %><br />
        <%= f.text_area :history, placeholder: 'History', rows: 6 %><br />
        <%= f.text_area :climate, placeholder: 'Climate', rows: 3 %><br />
        <%= f.text_area :industry, placeholder: 'Industry', rows: 3 %><br />
        <%= f.text_area :education, placeholder: 'Education', rows: 3 %><br />
        <%= f.text_area :culture, placeholder: 'Culture', rows: 3 %><br />
        <%= f.text_area :law, placeholder: 'Legal System, Crime & Punishment', rows: 3 %><br />
        <%= f.text_area :mythology, placeholder: 'Mythology', rows: 3 %><br />
    </fieldset>

    <fieldset>
      <legend>Quick Stats</legend>
        <%= f.text_field :inception, placeholder: 'Inception' %><br />
        <%= f.text_field :population, placeholder: 'Population' %><br />
        <%= f.text_field :life_expectancy, placeholder: 'Ave. Life Expectance' %><br />
        <%= f.text_field :land_mass, placeholder: 'Land Mass' %><br />
    </fieldset>

    <p><%= f.submit %></p>
  <% end %>
</div>

результаты консоли rails при нажатии ссылки «Новое состояние»

Started GET "/worlds/1/states/new" for 70.196.17.76 at 2017-05-22 13:43:47 +0000
Cannot render console from 70.196.17.76! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by StatesController#new as HTML
  Parameters: {"world_id"=>"1"}
  User Load (0.3ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ?  [["id", 2], ["LIMIT", 1]]
  World Load (0.1ms)  SELECT  "worlds".* FROM "worlds" WHERE "worlds"."id" = ? LIMIT ?  [["id", nil], ["LIMIT", 1]]
Completed 404 Not Found in 3ms (ActiveRecord: 0.4ms)



ActiveRecord::RecordNotFound (Couldn't find World with 'id'=):

app/controllers/states_controller.rb:13:in `new'
  Rendering /usr/local/rvm/gems/ruby-2.3.0/gems/actionpack-5.0.3/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb within rescues/layout
  Rendering /usr/local/rvm/gems/ruby-2.3.0/gems/actionpack-5.0.3/lib/action_dispatch/middleware/templates/rescues/_source.html.erb
  Rendered /usr/local/rvm/gems/ruby-2.3.0/gems/actionpack-5.0.3/lib/action_dispatch/middleware/templates/rescues/_source.html.erb (4.7ms)
  Rendering /usr/local/rvm/gems/ruby-2.3.0/gems/actionpack-5.0.3/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb
  Rendered /usr/local/rvm/gems/ruby-2.3.0/gems/actionpack-5.0.3/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (2.6ms)
  Rendering /usr/local/rvm/gems/ruby-2.3.0/gems/actionpack-5.0.3/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb
  Rendered /usr/local/rvm/gems/ruby-2.3.0/gems/actionpack-5.0.3/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (1.1ms)
  Rendered /usr/local/rvm/gems/ruby-2.3.0/gems/actionpack-5.0.3/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb within rescues/layout (36.6ms)

person ddonche    schedule 22.05.2017    source источник


Ответы (2)


Измените свой помощник link_to, чтобы указать и сообщить Rails, какой параметр вы отправляете через него:

Из:

<%= link_to 'New State', new_world_state_path(@world) %>

To:

<%= link_to 'New State', new_world_state_path(id: @world) %>

id, потому что вы пытаетесь найти параметры с World по :id в качестве параметра.

Попробуйте также изменить param, полученный в контроллере, где вы устанавливаете переменную @world:

def new
  @world = World.find(params[:world_id])
  ...
end

В show.html.erb:

<%= link_to 'New World', new_world_state_path(world_id: @world) %>

Обновление: что мы сделали:

В app/views/worlds/show.html.erb изменить способ установки параметра:

Из:

<%= link_to 'New Nation', new_world_state_path(world_id: @world_id) %> # @world_id wasn't defined

To:

<%= link_to 'New Nation', new_world_state_path(world_id: @world.id) %>

В /app/views/states/_form.html.erb добавить world_id как hidden_field:

<%= f.hidden_field :world_id, value: @world.id %>

А затем в app/controllers/states_controller.rb изменить способ получения параметров:

def new
  @world = World.find(params[:world_id])
  @state = @world.states.build
end

def create
  @world = World.find(params[:state][:world_id])
  ...
person Sebastian Palma    schedule 22.05.2017
comment
Я получаю сообщение Нет совпадений маршрутов {:action=>"new", :controller=>"states", :id=>#<World id: 1, ... (every value in the world 1 entry) } missing required keys: [:world_id]. - person ddonche; 22.05.2017
comment
Вы не против опубликовать параметры, отображаемые в консоли рельсов, когда вы нажимаете ссылку New State?. - person fanta; 22.05.2017
comment
Я также пытался использовать <%= link_to 'New State', new_world_state_path(@world_id) %> и ...path(@world.world_id), но они оба очень неверны. - person ddonche; 22.05.2017
comment
Отредактировал мой вопрос, включив в него элементы консоли. - person ddonche; 22.05.2017
comment
да, параметр world_id , вы сможете получить его оттуда. - person fanta; 22.05.2017
comment
Измените его с id в помощнике link_to на world_id в обоих случаях, в представлении и в контроллере. - person Sebastian Palma; 22.05.2017
comment
Что вы подразумеваете под этим: And be sure the link_to is inside the each block in order to get a value to send through it:? У меня нет цикла на моей странице шоу. - person ddonche; 22.05.2017
comment
Извините, я думал, что вы делаете это внутри блока each, как вы написали worlds/show/index.html.erb, я запутался, в любом случае передачи объекта должно быть достаточно, чтобы получить идентификатор. - person Sebastian Palma; 22.05.2017
comment
Прошу прощения, я не понял, что опечатался в этой части. Это страница show.html.erb. Я согласен, передача объекта должна работать, я понятия не имею, почему это не так. - person ddonche; 22.05.2017
comment
Здесь есть репозиторий, который, я думаю, работает так же, как и ваш. Если вам это нужно, мы можем перенести обсуждение в чат. - person Sebastian Palma; 22.05.2017
comment
Давайте продолжим обсуждение в чате. - person ddonche; 22.05.2017

Если world_id передается действию :new, его нельзя передать обратно в форме действию создания.

Ваши state_params ожидают, что :world_id будет отправлен обратно, поэтому добавьте скрытое поле, чтобы отправить его обратно в форму.

новый.html.erb

<%= f.hidden_field :world_id, :value => @world.id %>

и обновите действие создания до

@world = World.find(params[:world_id])
person John    schedule 22.05.2017
comment
Это заставило меня пройти новое действие и, наконец, показать форму, но после отправки формы я получаю ту же ошибку. Couldn't find World with 'id'= - person ddonche; 22.05.2017