Rails 5.1 form_with тройной вложенной формы дочерний (внучка ??) дочерний не наследующий атрибут и не сохраняющий - PullRequest
0 голосов
/ 26 августа 2018

Мое приложение (на основе учебника по Hartl Rails 5) имеет модель User, которая имеет has_many Rooms, а модель Room, в свою очередь, has_many Students.У меня есть форма для пользователя, чтобы создать комнату (с атрибутом: номер) со студентами (с атрибутом: имя).Хотя форма создания пользователя отделена от формы создания комнаты, я использовал код ассоциации из этого примера: https://medium.com/@mindovermiles262/triple-nested-forms-in-rails-dedbcccb5799.

Когда я отправляю форму, она возвращает ошибку «Комната для студентов не может быть пустой»,Где-то связь между комнатой и учеником теряется.Ниже приведен скриншот отправленной формы с сообщением об ошибке: Screenshot of Students room can't be blank error

Вот соответствующий код user.rb:

class User < ApplicationRecord
has_many        :rooms, dependent: :destroy
has_many        :students, through: :rooms
accepts_nested_attributes_for   :rooms, allow_destroy: true
accepts_nested_attributes_for   :students, allow_destroy: true

...

end

users_controller.rb

    private

def user_params
  params.require(:user).permit(:name, :email, :school, :password,
                               :password_confirmation,
                               :rooms_attributes => [:id, :number, 
                               :students_attributes => [:id, :name]
                               ] )

end

room.rb:

    class Room < ApplicationRecord
  belongs_to                        :user, optional: true
  has_many                          :students, dependent: :destroy, inverse_of:  
                                    :room
  accepts_nested_attributes_for     :students, allow_destroy: true
  default_scope ->                  { order(number: :asc) }
  validates                         :number, presence: true
  validates                         :user_id, presence: true    
end

rooms_controller.rb

    class RoomsController < ApplicationController

before_action :logged_in_user, only: [:create, :destroy, :edit, :update, :show]
before_action :correct_user,   only: [:show]

    def new
        @room = current_user.rooms.build if logged_in?
        @student = @room.students.build
    end

  def create

    @room = current_user.rooms.build(room_params)


    if @room.save && @student.save
      flash[:success] = "New class created."
      redirect_to current_user
    else
      render 'rooms/new'
    end
  end

  def destroy
  end

  def edit
  end

  def update
    @room = Room.find(params[:id])
    if @room.update_attribute(room_params)
        redirect_to @room
        flash[:success] = "Class updated."
    end
  end

  def show
    @user = User.find(params[:id])
    @rooms = @user.rooms
    # @number = @rooms.number
  end

  private

    def room_params
      params.require(:room).permit(:number, :students_attributes => [:id, :name])

    end

end

метод current_user из session_helper.рб:

      def current_user
    if (user_id = session[:user_id])
      @current_user ||= User.find_by(id: user_id)
    elsif (user_id = cookies.signed[:user_id])
      user = User.find_by(id: user_id)
      if user && user.authenticated?(:remember, cookies[:remember_token])
        log_in user
        @current_user = user
      end
    end
  end

student.rb:

    class Student < ApplicationRecord
  belongs_to        :room, optional: true, inverse_of: :students
  validates         :name, presence: true, length: { maximum: 50 }
  validates         :room_id, presence: true
end

Students_controller.rb

    class StudentsController < ApplicationController

    before_action   :logged_in_user, only: [:create, :destroy, :edit, :update, :show]
    before_action   :correct_user,   only: [:show]




    def new
        @room = current_user.rooms.build if logged_in?
        @student = @room.students.build
    end

    def create

        if @student.save
         flash[:success] = "New student created."
        redirect_to current_user

        else

            render 'students/new'
        end
    end

    def show
    end

      private

    def student_params
      params.require(:student).permit(:name)
    end
end

Форма создания комнаты, rooms \ new.html.erb:

    <% provide(:title, 'Create a class') %>
    <h1>Create a class</h1>

    <%= form_with(model: @room, local: true) do |f| %>

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

          <%= f.label :number, "Class number" %>
          <%= f.number_field :number, class: 'form-control' %>

           <%= f.fields_for :students do |s| %>
            <%= s.label :name, "Student name" %>
            <%= s.text_field :name, class: 'form-control' %>
          <% end %>


      <%= f.submit "Create class", class: "btn btn-primary" %>
      <%= params.inspect %>
<% end %>

config \ rout.rb:

    Rails.application.routes.draw do



  get 'password_resets/new'

  get 'password_resets/edit'

  get 'sessions/new'



      root 'static_pages#home'
    get '/signup',        to: 'users#new'
    post '/signup',       to: 'users#create'
    get    '/login',      to: 'sessions#new'
    post   '/login',      to: 'sessions#create'
    delete '/logout',     to: 'sessions#destroy'
    get '/showall',       to: 'users#index'
    get '/createroom',    to: 'rooms#new'
    post '/createroom',   to: 'rooms#create'
    get 'createstudent',  to: 'students#new'
    get 'createstudent',  to: 'students#create'


    resources :users
    resources :account_activations, only: [:edit]
    resources :password_resets,     only: [:new, :create, :edit, :update]
    resources :rooms
    resources :students

end

и development.log:

Processing by RoomsController#new as 
  Rendering rooms/new.html.erb within layouts/application
  Rendered shared/_error_messages.html.erb (1.0ms)
  Rendered rooms/new.html.erb within layouts/application (388.0ms)
  Rendered layouts/_rails_default.html.erb (244.0ms)
  Rendered layouts/_shim.html.erb (1.0ms)
  Rendered layouts/_header.html.erb (1.0ms)
  Rendered layouts/_footer.html.erb (1.0ms)
Completed 200 OK in 2938ms (Views: 2513.1ms | ActiveRecord: 12.0ms)


Processing by RoomsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"henh7dclciYRcZE6xRFfdSHBPQuRmO03eXXEsmRkSSI25uqkMSo6WFwthixdEzDNSNjY5pPmcIYwi5nmFZirMg==", "room"=>{"number"=>"200", "students_attributes"=>{"0"=>{"name"=>"Roo"}}}, "commit"=>"Create class"}
  Rendering rooms/new.html.erb within layouts/application
  Rendered shared/_error_messages.html.erb (1.0ms)
  Rendered rooms/new.html.erb within layouts/application (35.0ms)
  Rendered layouts/_rails_default.html.erb (237.0ms)
  Rendered layouts/_shim.html.erb (0.0ms)
  Rendered layouts/_header.html.erb (1.0ms)
  Rendered layouts/_footer.html.erb (1.0ms)
Completed 200 OK in 3283ms (Views: 494.7ms | ActiveRecord: 3.0ms)

Я добавил: inverse_of per Сообщение об ошибке Rails 5:Дочерняя модель Родительская модель должна существовать , но это не имеет значения.Это ( rails 5.1: проверка вложенной формы ) не имеет отношения к делу, поскольку в нем задействован родитель с двумя разными детьми, а не родитель с ребенком, у которого также есть ребенок.

Заранее благодарен за любую помощь.

РЕДАКТИРОВАТЬ:

Я наконец понял, что сообщение об ошибке "Комната для студентов не может быть пустой" ссылается на то, что room_id пуст.Я удалил следующую строку из файла student.rb:

validates: room_id, присутствие: true

Я думал, что

own_to: room, необязательно: true

временно обойдёт метод validates, но я ошибся.

1 Ответ

0 голосов
/ 25 сентября 2018

Удаление

проверяет: room_id, необязательно: true

было решением.

...