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