【问题标题】:Rails where with multiple conditionsRails 有多种条件
【发布时间】:2018-03-23 12:08:44
【问题描述】:

在我的应用程序中,我使用枚举定义了多个用户角色:

enum role: { staff: 0, clinician: 1, admin: 2 }

教职员工每个人都属于一所大学:

员工关注:

require 'active_support/concern'

module StaffUser
  extend ActiveSupport::Concern

  included do
    belongs_to :university
    has_many :patients
    has_many :referral_requests
    validates :university_id, presence: true, if: :staff?
  end

大学模式

class University < ApplicationRecord
  has_many :staffs, -> { where role: :staff}, class_name: "User"
  has_many :clinicians, through: :lists
  has_many :whitelists
  belongs_to :market

  validates :market_id, presence: true
end

我在患者/新视图上有一个员工医生的下拉选择菜单,我想在其中显示与当前用户属于同一大学的员工用户列表,但我似乎无法让它工作.目前,下拉列表仅包含提示文本。我做错了什么?

患者/新观点:

<%= form_for(@patient) do |f| %>
  <%= render 'shared/error_messages', object: f.object %>
  <div class="checkbox">

    <h1>Tell us about your patient</h1>


    <h2>Insurance</h2>
    <% Insurance.all.each do |insurance| %>
      <%= check_box_tag "patient[insurance_ids][]", insurance.id, @patient.insurance_ids.include?(insurance.id), id: dom_id(insurance) %>
      <%= label_tag dom_id(insurance), insurance.name %><br>
    <% end %>

    <h2>Presenting Concerns</h2>
    <% Concern.all.each do |concern| %>
      <%= check_box_tag "patient[concern_ids][]", concern.id, @patient.concern_ids.include?(concern.id), id: dom_id(concern) %>
      <%= label_tag dom_id(concern), concern.name %><br>
    <% end %>

    <h2>Staff Doctor</h2>  

       <%= select_tag "patient[staff_doctor_id]", options_from_collection_for_select(User.where("role = ? AND university_id = ?", "staff", @user.university_id), "id", "name"), prompt: "Select this patient's therapist" %>

  </div>

  <%= f.submit "Submit", class: "btn btn-primary" %>
<% end %

患者控制者:

class PatientsController < ApplicationController
    before_action :require_login

def new
    @user = current_user
    @patient = current_user.patients.build
end

def index
    authorize Patient
    @patients = policy_scope(Patient)
end

def show
    @patient = Patient.find(params[:id])
end

def edit
    @patient = Patient.find(params[:id])
end

def update
    @patients = Patient.all
    @patient = Patient.find(params[:id])
    if @patient.update_attributes(patient_params)
        flash[:success] = "Patient Updated!"
        render 'patients/index'
    else
        render "edit"
    end
end


def create
    @patient = current_user.patients.build(patient_params)
    if @patient.save
        flash[:success] = "Patient Created!"
        redirect_to new_referral_request_path(patient_id: @patient.id)
    else
        Rails.logger.info(@patient.errors.inspect)
        render 'patients/new'
end
end


private

def patient_params
    params.require(:patient).permit(:age, :staff_doctor_id, :user_id, insurance_ids: [], gender_ids: [], concern_ids: [], race_ids: [])

end
end

【问题讨论】:

  • 当你在控制台中运行User.where("role = ? AND university_id = ?", "staff", @user.university_id),给定相同的@user,你会得到什么?顺便说一句,如果您使用 Rails4,则需要在查询中使用 0 而不是“staff”,因为该字段是整数类型,尽管我相信字符串值现在在 Rails5 中有效。你的用户有#name 方法吗?
  • @EJ2015 我认为 Rails 5 不会自动修复参数化查询以使用枚举映射。不过,where(role: :staff) 可以工作。

标签: ruby-on-rails activerecord where


【解决方案1】:

ActiveRecord 中的作用域是可链接的:

User.staff.where(university: @user.university)

链接.where 或范围会创建 AND 子句。所以必须满足所有条件。

使用ActiveRecord::Enum 为每个枚举状态创建范围。所以这相当于:

User.where(role: :staff, university: @user.university)

使用ActiveRecord::Enum 时,您需要记住数据库存储的是整数,而不是字符串:

User.where('role = 0') # staff
User.where('role = ?', User.statuses[:staff])

但是对于这个查询不需要使用 SQL 字符串。

using the rails collection helpers 是创建选择和复选框的更好方法:

<%= form_for(@patient) do |f| %>
  <%= render 'shared/error_messages', object: f.object %>
  <div class="checkbox">
    <h1>Tell us about your patient</h1>
    <h2>Insurance</h2>
    <%= f.collection_check_boxes(:insurance_ids, Insurance.all, :id, :name) %>

    <h2>Presenting Concerns</h2>
    <%= f.collection_check_boxes(:concern_ids, Concern.all, :id, :name) %>

    <h2>Staff Doctor</h2>  
    <%= f.collection_select(:staff_doctor_id, User.staff.where(university: @user.university), :id, :name, prompt: "Select this patient's therapist") %>
  </div>
  <%= f.submit "Submit", class: "btn btn-primary" %>
<% end %>

这不仅代码少了很多,而且将输入绑定到表单构建器可确保它们在验证失败时“保持值”。

【讨论】:

  • 还要确保从 patient_params 方法中删除 user_id。
  • 谢谢麦克斯!我正在深入研究是否能找出原因,但是由于某种原因,将表单更改为使用 rails 集合助手会混淆所有复选框。
  • 当我强制在模型中验证 staff_doctor_id 并尝试提交表单而不选择它时,在 where 语句中的 patients#create for university 中出现未定义的方法错误...为什么会这样?
  • 使用 css 让复选框以您想要的方式出现。您的 User 类是否包含 StaffUser 模块?
  • 谢谢 Max - 确实如此
猜你喜欢
  • 2023-04-04
  • 1970-01-01
  • 2015-06-19
  • 2014-09-24
  • 2018-07-15
  • 1970-01-01
  • 2021-07-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多