将select_tag列表限制为仅限于属于rails中另一个对象的对象

时间:2022-10-05 10:22:13

I have a list of classrooms that belong_to a school and a school has_many classrooms. I have users who belong to a school and fill out a form of information. On this form I have the following selector:

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

Pins/_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>

Right now this form shows all the classrooms listed in the data base. I need it to show just the classrooms that belong to the school. Classrooms have a name and a code, the code is what ties the students form submission to that classroom.

此时此表单显示数据库中列出的所有教室。我需要它来展示属于学校的教室。教室有一个名称和一个代码,代码是将学生提交表格与课堂联系起来的。

I'm still learning RoR and have struggled to figure this type of problem one out on a couple of occasions.

我还在学习RoR,并且曾经几次努力解决这类问题。

Here's the Classroom Controller

这是课堂控制器

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

end

School.rb model

 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

User Model

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

classroom model

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 

I found a similar answer here: Rails only give records that "belong_to"

我在这里找到了类似的答案:Rails只给出“belongs_to”的记录

But it didn't help me understand how to limit the drop down list to only Classrooms of the current school.

但它并没有帮助我理解如何将下拉列表限制为当前学校的课堂。

Any ideas on how to handle his situation?

关于如何处理他的情况的任何想法?

1 个解决方案

#1


You already select the school in the controller, so just use it in the view, instead of doing a Classroom.all do a @school.classrooms

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

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


This part isn't an answer, but improvements and fixes to your code

First the User model can stay as it is

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

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

classroom class

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

   has_many :pins
   has_many :reflections
end 

school class

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

Now the controllers

现在是控制器

You need to clean up the duplications, so here's an example from ur pins#new action

你需要清理复制品,所以这里是你的针脚#new action的一个例子

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

I removed the common code to a separate method, and call it whenever i need, of course you can add or remove from that method according to your needs.

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

Anyways, I think you should read more about active record assocciations and the conventions in writing controller actions

无论如何,我认为你应该阅读更多关于活动记录关联和编写控制器动作的约定

#1


You already select the school in the controller, so just use it in the view, instead of doing a Classroom.all do a @school.classrooms

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

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


This part isn't an answer, but improvements and fixes to your code

First the User model can stay as it is

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

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

classroom class

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

   has_many :pins
   has_many :reflections
end 

school class

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

Now the controllers

现在是控制器

You need to clean up the duplications, so here's an example from ur pins#new action

你需要清理复制品,所以这里是你的针脚#new action的一个例子

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

I removed the common code to a separate method, and call it whenever i need, of course you can add or remove from that method according to your needs.

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

Anyways, I think you should read more about active record assocciations and the conventions in writing controller actions

无论如何,我认为你应该阅读更多关于活动记录关联和编写控制器动作的约定