【问题标题】:Limiting a select_tag list to only objects that belong_to another object in rails将 select_tag 列表限制为仅属于 rails 中另一个对象的对象
【发布时间】:2015-05-03 16:05:13
【问题描述】:

我有一个属于一所学校的教室列表,而一所学校有_许多教室。我有属于学校并填写信息表格的用户。在此表单上,我有以下选择器:

引脚/_form.html.erb

    <div class="form-group">
     <%= label_tag(:classroom, "Select your classroom:") %>
     <%= select_tag "pin[code]", options_from_collection_for_select(Classroom.all, "code", "code", ) %>
   </div>

现在这个表格显示了数据库中列出的所有教室。我需要它来显示属于学校的教室。教室有一个名称和一个代码,代码将学生的表单提交与该教室联系起来。

我仍在学习 RoR,并且曾多次努力解决此类问题。

这是教室控制器

class ClassroomsController < ApplicationController
  before_action :set_classroom, only: [:show, :edit, :update, :destroy]
  after_action :verify_authorized
  respond_to :html
def home
  @classrooms = Classroom.all
  respond_with(@classrooms)
  authorize @classrooms
end 
 def index
   @classrooms = Classroom.all
   respond_with(@classrooms)
   authorize @classrooms
end

def show
  respond_with(@classroom)
end

def new
  @school = School.find(params[:school_id])
  @classroom = @school.classrooms.new
  @teachers = @school.teachers
  respond_with(@classroom)
  flash[:notice] = "Classroom created."
  authorize @classroom
end

 def edit
 end

def create
  @school = School.find(params[:school_id])
  @classroom = @school.classrooms.new(classroom_params)
  @classroom.save
  respond_with @school
  authorize @classroom
end

def update
  @classroom.update(classroom_params)
  respond_with([@school,@classroom])
end

def destroy
  @classroom.destroy
  redirect_to @school
  flash[:notice] = "You have succesfully deleted the classroom."
end

  private
    def set_classroom
     @classroom = Classroom.find(params[:id])
     @school = School.find(params[:school_id])
     authorize @classroom
   end

   def classroom_params
    params.require(:classroom).permit(:teacher_id, :name, :code)
  end
end

Pins_controller

 class PinsController < ApplicationController
 before_action :set_pin, only: [:show, :edit, :update, :destroy]
  respond_to :html

def show
   respond_with(@pin)
 end

def new
  @pin = Pin.new
  @emotions = Emotion.all 
  @causes = Cause.all
  @school = School.find(params[:school])
  @classrooms = @school.classrooms
  respond_with(@pin)
  authorize @pin
 end

 def edit
 end

def create
  code = params[:pin][:code]
  @classroom = Classroom.where('code LIKE ?', code).first
  unless @classroom
    flash[:error] = "Classroom code incorrect"
    @emotions = Emotion.all 
    @causes = Cause.all
    render :new
   else
    params[:pin][:classroom_id] = @classroom.id

    @pin = Pin.new(pin_params)
    @pin.save 
      params[:pin][:cause_ids].each do |cause_id| 
      @cause = Cause.find(cause_id)
      @pin.causes << @cause
    end
     params[:pin][:emotion_ids].each do |emotion_id| 
       @emotion = Emotion.find(emotion_id)
       @pin.emotions << @emotion
     end



   if @pin.save
      redirect_to signout_path and return 
   end 
    respond_with(@pin)
    authorize @pin
   end
end


def update
  @pin.update(pin_params)
  respond_with(@pin)
  authorize @pin
end

def destroy
  @pin.destroy
  respond_with(@pin)
  authorize @pin
end

private
  def set_pin
    @pin = Pin.find(params[:id])
    authorize @pin
  end

 def pin_params
   params.require(:pin).permit(:user_id, :question, :question1, :question2, 
    :question3, :question4, :question5, :classroom_id, :sad, 
    :happy, :mad, :brave, :embarrassed, :sorry, :frustrated, 
    :silly, :left_out, :excited, :hurt, :jealous, :confused, 
     :proud, :other)
  end

结束

School.rb 模型

 class School < ActiveRecord::Base
    has_many :users
    has_many :classrooms

    validates_uniqueness_of :code

   def classrooms
    self.users.classrooms
   end


  def students
    self.users.students
   end

  def teachers
    self.users.teachers
  end

   def admins
    self.users.admins
   end
end

用户模型

class User < ActiveRecord::Base
  devise :timeoutable, :database_authenticatable, :registerable,
     :recoverable, :rememberable, :trackable, :validatable

   has_many :pins
   has_many :reflections
   has_many :classrooms, :foreign_key => :teacher_id
   belongs_to :school

  validates :name, presence: true
  validates :role, presence: true
 # validates :school, presence: true

   scope :students, -> { where(role: "student") }
   scope :teachers, -> { where(role: "teacher")}
   scope :teachers_and_admins, -> { where(:role => ["teacher", "admin"]) }
   scope :admins, -> { where(role: "admin" ) }
   scope :online, lambda{ where("updated_at > ?", 15.days.ago) }
  def online?
    updated_at > 15.days.ago
   end

  def admin?
     role == "admin"
   end 

   def teacher?
    role == "teacher"
  end

  def student?
   role == "user" || role == "student"
  end

 def superadmin?
   role == "superadmin"
 end

 def admin_of_school?(school)
   self.admin? && self.school == school
 end

 def teacher_of_school?(school)
   self.teacher? && self.school == school
 end

def admin_or_teacher_of_school?(school)
   self.admin_of_school?(school) || self.teacher_of_school?(school)
 end

end

课堂模式

class Classroom < ActiveRecord::Base

   belongs_to :school
   belongs_to :teacher, :class_name => "User"
   has_and_belongs_to_many :users

   has_many :pins
   has_many :reflections

   validates_presence_of :school
   validates_presence_of :teacher
   validates :code, :uniqueness => { :scope => :school_id }


end 

我在这里找到了类似的答案:Rails only give records that "belong_to"

但这并没有帮助我理解如何将下拉列表限制为仅当前学校的教室。

对如何处理他的情况有什么想法吗?

【问题讨论】:

  • 实际上你的pins控制器和教室控制器由于某种原因在问题中是一样的
  • 谢谢我的错误我已经更新了。

标签: ruby-on-rails associations


【解决方案1】:

您已经在控制器中选择了学校,所以只需在视图中使用它,而不是执行Classroom.all 执行@school.classrooms

<%= select_tag "pin[code]", 
  options_from_collection_for_select(@school.classrooms, "code", "code")
%>


这部分不是答案,而是对您的代码的改进和修复

首先用户模型可以保持原样

class User < ActiveRecord::Base
  #devise place holder

  # assocciations
  has_many :pins
  has_many :reflections
  has_many :classrooms, foreign_key: :teacher_id
  belongs_to :school

  #validations place holder

  #scopes
  scope :students, -> { where(role: "student") }
  scope :teachers, -> { where(role: "teacher")}
  scope :admins, -> { where(role: "admin" ) }
  scope :teachers_and_admins, -> { teachers.admins }
  scope :online, -> { where("updated_at > ?", 15.days.ago) }

  # some check methods
end

课堂课堂

class Classroom < ActiveRecord::Base
   belongs_to :school
   belongs_to :teacher, ->{ User.teachers }, class_name: 'User'

   has_many :pins
   has_many :reflections
end 

学校班级

class School < ActiveRecord::Base
  has_many :users
  has_many :admins, ->{ User.admins }, class: User
  has_many :students, ->{ User.students }, class: User
  has_many :teachers, ->{ User.teachers }, class: User
  has_many :classrooms
end

现在是控制器

您需要清理重复项,所以这里有一个来自您的 pins#new 操作的示例

def new
  @pin = Pin.new
  prepare_lookups
  respond_with(@pin)
  authorize @pin
end

def prepare_lookups
  @emotions = Emotion.all 
  @causes = Cause.all
  @school = School.find(params[:school])
  @classrooms = @school.classrooms
end

我将通用代码删除到单独的方法中,并在需要时调用它,当然您可以根据需要在该方法中添加或删除。

无论如何,我认为您应该阅读更多关于 active record assocciations 以及编写控制器操作的约定

【讨论】:

  • 这是有道理的,但是当我这样做时,我在 Pins#new 中遇到了 NoMethodError。
  • 教室领域有哪些?
  • 一个教室有一个名字和一个代码。我使用代码将 pin 与正确的教室相关联。然后老师可以去查看那个教室并查看所有学生的反应。
  • 试试options_from_collection_for_select(@school.classrooms, :id, :code)
  • 还是同样的错误。引脚中未定义的方法“教室”#new
猜你喜欢
  • 1970-01-01
  • 2013-02-02
  • 2013-08-14
  • 2015-09-03
  • 1970-01-01
  • 2015-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多