Имя автоматической переменной Ruby on Rails (множественное и единственное число)

Я создаю приложение для рельсов, в котором есть несколько викторин с одинаковой структурой:

  • Имя, такое как @quiz_bf или @quiz_bs
  • new.html.erb и edit.html.erb просмотра для каждого теста
  • Частичный _quiz.html.erb, в котором хранятся фактические вопросы викторины для каждой викторины.
  • Модель и контроллер для каждой отдельной викторины
  • Два места (главная навигация и страница профиля пользователя) содержат ссылку на представление new (или на представление edit, если люди уже прошли тест, определяемый оператором erb if/else) каждого теста.

Мне удалось настроить первую викторину, но поскольку я новичок в Ruby, я совершил (ужасную) ошибку, установив имя переменной, оканчивающееся на -s (quiz_bs) для единственной версии викторины. Это нанесло ущерб соглашениям об именах в единственном и множественном числе в Ruby.

В настоящее время у меня есть код для моей второй викторины (quiz_bf), но я получаю сообщение об ошибке без метода, говорящее undefined method 'quiz_bfs' for #<User:0x007fb9a3247f98> в определении нового теста в моем контроллере.

Вот мой контроллер:

class QuizBfController < ApplicationController
before_action :require_sign_in

def show
  @quiz_bf = QuizBf.find(params[:id])
end

def new
  @quiz_bf = current_user.quiz_bfs || current_user.build_quiz_bfs
end

def create
  @quiz_bf = QuizBf.new

  @quiz_bf.bf01 = params[:quiz_bfs][:bf01]
  @quiz_bf.bf02 = params[:quiz_bfs][:bf02]
  @quiz_bf.bf03 = params[:quiz_bfs][:bf03]
  @quiz_bf.bf04 = params[:quiz_bfs][:bf04]
  @quiz_bf.bf05 = params[:quiz_bfs][:bf05]
  @quiz_bf.bf06 = params[:quiz_bfs][:bf06]
  @quiz_bf.bf07 = params[:quiz_bfs][:bf07]
  @quiz_bf.bf08 = params[:quiz_bfs][:bf08]
  @quiz_bf.bf09 = params[:quiz_bfs][:bf09]
  @quiz_bf.bf10 = params[:quiz_bfs][:bf10]

  @quiz_bf.user = current_user

  if @quiz_bf.save
    flash[:notice] = "Quiz results saved successfully."
    redirect_to user_path(current_user)
  else
    flash[:alert] = "Sorry, your quiz results failed to save."
    redirect_to welcome_index_path
  end
  end

  def edit
    @quiz_bf = QuizBf.find(params[:id])
  end

  def update
  @quiz_bf = QuizBf.find(params[:id])

  @quiz_bf.assign_attributes(quiz_bfs_params)

  if @quiz_bf.save
    flash[:notice] = "Post was updated successfully."
    redirect_to user_path(current_user)
    else
    flash.now[:alert] = "There was an error saving the post. Please try again."
    redirect_to welcome_index_path
    end
    end

    private
    def quiz_bfs_params
    params.require(:quiz_bfs).permit(:bf01, :bf02, :bf03, :bf04, :bf05, :bf06, :bf07, :bf08, :bf09, :bf10)
    end

    end

Вот моя модель (пользователь has_one :quiz_bf):

class QuizBf < ActiveRecord::Base
before_save :set_bfcode

def set_bfcode
  self.bfcode = "#{self.bf01}#{self.bf02}#{self.bf03}-#{self.bf04}#{self.bf05}#{self.bf06}-#{self.bf07}#{self.bf08}#{self.bf09}#{self.bf10}"
end

belongs_to :user
validates :user, presence: true
end

Вот моя пользовательская модель:

class User < ActiveRecord::Base
before_save { self.email = email.downcase }

validates :name, length: { minimum: 1, maximum: 100 }, presence: true
validates :password, presence: true, length: { minimum: 6 }, unless: :password_digest
validates :password, length: { minimum: 6 }, allow_blank: true
validates :email,
        presence: true,
        uniqueness: { case_sensitive: false },
        length: { minimum: 3, maximum: 254 }

has_secure_password

has_one :quiz_bs
has_one :quiz_bf

конец

Вот уместные части моей викторины:

<%= form_for @quiz_bf do |f| %>

...

<%= f.submit "Submit Answers" %>

Вот как я связываюсь из моего представления new:

<%= render partial: "quiz", locals: { url: quiz_bfs_path, method: :post } %>

И мой edit вид:

<%= render "quiz", url: quiz_bf_path(@quiz_bf), method: :put  %>

И (наконец) вот как я ссылаюсь на него из моего представления application:

          <% if current_user.quiz_bfs == nil? %>
             <%= link_to "Body Flexibility Quiz", quiz_bf_path %>
          <% else %>
             <%= link_to "Body Flexibility Quiz ✓", edit_quiz_bf_path(current_user.quiz_bfs) %>
          <% end %>

И мои пользователи show страница:

  <% if @user.quiz_bfs == nil %>
    <p><%= link_to "Test Your Body Flexibility", new_quiz_bf_path %></p>
  <% else %>
    <h3><%= @user.quiz_bfs.bfcode %></h3>
    <p><%= link_to "Retest Results", edit_quiz_bf_path(@user.quiz_bfs) %></p>
  <% end %>

Я знаю, что этот код успешно работал для quiz_bs, но, как вы можете видеть в моих рейк-маршрутах (показанных ниже), проблема с моим идиотским именем переменной во множественном и единственном числе затрудняла понимание того, что на самом деле было названо как. Может ли кто-нибудь с более опытными рубиновыми глазами, чем у меня, показать мне, что мне нужно изменить?

        quiz_bs GET    /quiz_bs(.:format)             quiz_bs#index
                POST   /quiz_bs(.:format)             quiz_bs#create
     new_quiz_b GET    /quiz_bs/new(.:format)         quiz_bs#new
    edit_quiz_b GET    /quiz_bs/:id/edit(.:format)    quiz_bs#edit
         quiz_b GET    /quiz_bs/:id(.:format)         quiz_bs#show
                PATCH  /quiz_bs/:id(.:format)         quiz_bs#update
                PUT    /quiz_bs/:id(.:format)         quiz_bs#update
                DELETE /quiz_bs/:id(.:format)         quiz_bs#destroy
  quiz_bf_index GET    /quiz_bf(.:format)             quiz_bf#index
                POST   /quiz_bf(.:format)             quiz_bf#create
    new_quiz_bf GET    /quiz_bf/new(.:format)         quiz_bf#new
   edit_quiz_bf GET    /quiz_bf/:id/edit(.:format)    quiz_bf#edit
        quiz_bf GET    /quiz_bf/:id(.:format)         quiz_bf#show
                PATCH  /quiz_bf/:id(.:format)         quiz_bf#update
                PUT    /quiz_bf/:id(.:format)         quiz_bf#update
                DELETE /quiz_bf/:id(.:format)         quiz_bf#destroy

person Liz    schedule 29.04.2016    source источник
comment
Можете ли вы опубликовать свою пользовательскую модель?   -  person Pavan    schedule 29.04.2016
comment
Здесь есть большие проблемы. У вас не должно быть десятков таких полей с одинаковыми именами и разными номерами, все ваши @quiz_bf.bf01 переменные не должны быть настроены таким образом. Вы должны либо хранить их как связанные записи, либо просто сериализовать массив, чтобы вы могли просто зацикливаться на полях.   -  person meagar    schedule 29.04.2016
comment
Есть ли у вашей модели User has_many :quiz_bfs ? Если нет, то @user.quiz_bfs будет неопределенным.   -  person SteveTurczyn    schedule 29.04.2016
comment
Я только что добавил модель пользователя в редактирование. Это has_one :quiz_bf.   -  person Liz    schedule 29.04.2016
comment
Почему вы используете quiz_bfs, когда ваша модель устанавливает только ассоциации quiz_bs и quiz_bf?   -  person Frederick Cheung    schedule 29.04.2016
comment
@FrederickCheung Вы правы. Я удалил файл quiz_bfs. Сообщение об ошибке изменилось на ошибку генерации URL, говорящую No route matches {:action=>"edit", :controller=>"quiz_bf", :id=>nil} missing required keys: [:id] в этой строке: <%= link_to "Body Flexibility Quiz ✓", edit_quiz_bf_path(current_user.quiz_bf) %>   -  person Liz    schedule 29.04.2016


Ответы (1)


Неопределенная ошибка метода

Проблема с неопределенным методом, вероятно, связана с вызовом во множественном числе (quiz_bfs), который предполагает, что у вас есть ассоциация has_many, в то время как ваша модель определяет только ассоциацию has_one:

has_one :quiz_bs
has_one :quiz_bf

Либо а) использование quiz_bfs является опечаткой и должно быть quiz_bf, б) has_one неверно, либо в) вам вообще не нужен вызов current_user.quiz_bfs, чтобы присвоить значение @quiz_bf. Трудно сказать, не зная подробностей, но похоже, что вы можете просто удалить current_user.quiz_bfs.

Бонус на маршрутах

Хотя это был не этот вопрос, в частности, вы упомянули о боли, связанной с тем, что ресурс, оканчивающийся на «s», рассматривается как множественное число. Если вы еще не видели его, вы можете назвать свои quiz_bs маршруты соответствующим образом. Для этого вы можете использовать эту форму в вашем файле config/routes.rb:

resources :quiz_bs, as: :quiz_bs

Это должно дать вам нужные имена помощников маршрута. Подробнее об этом можно прочитать в разделе Переопределение именованных помощников документа Маршрутизация Rails снаружи внутрь.

Вы также можете назвать свой контроллер QuizBsController, и для этого вы можете использовать переопределение controller: в определении маршрута ресурсов. Попробуйте это и посмотрите, даст ли он вам правильный контроллер:

resources :quiz_bs, controller: 'quiz_bs'

Вы всегда можете комбинировать оба метода маршрута и использовать что-то вроде этого:

resources :quiz_bs, controller: 'quiz_bs', as: :quiz_bs

Ознакомьтесь с разделом Указание используемого контроллера в Rails Routing from the Outside In для получения дополнительной информации и сведений об использовании.

person Michael Gaskill    schedule 08.05.2016