我有一个名为hardships的模型,它为投票赞成这种困难的用户提供了一个数组值(:approvals => []中的hardship_params)。
我正试图在索引页上创建一个hardships的列表,列出任何给定的current_user(使用devise)尚未批准的困难。
数组由用户id组成,因此如果第二个和第三个用户已经批准,@hardship.approvals的典型值将为["2", "3"]
从控制器调用这个的逻辑有问题。我看了很多类似this的帖子,但是无法找到一个适合Rails 5.2和Postgres的答案。
我在找这样的东西:

@need_approval = Hardship.where.not(approvals.include?(current_user.id.to_s))

但是,我知道这不起作用,因为approvals不是一个变量,语法也完全错误。有谁能帮我Rails提供信息,让它得到我需要的信息吗?
附加信息
这是我的hardships表:
  create_table "hardships", force: :cascade do |t|
    t.string "full_name"
    t.date "date"
    t.string "position"
    t.string "branch"
    t.string "email_non_toca"
    t.string "mobile"
    t.string "address"
    t.string "city"
    t.string "state"
    t.string "zip"
    t.string "bank_name"
    t.string "bank_phone"
    t.string "bank_address"
    t.date "start_date"
    t.boolean "accident", default: false
    t.boolean "catastrophe", default: false
    t.boolean "counseling", default: false
    t.boolean "family_emergency", default: false
    t.boolean "health", default: false
    t.boolean "memorial", default: false
    t.boolean "other_hardship", default: false
    t.string "other_hardship_description"
    t.decimal "requested_amount"
    t.text "hardship_description"
    t.decimal "self_fund"
    t.string "intent_signature"
    t.date "intent_signature_date"
    t.string "release_signature"
    t.date "release_signature_date"
    t.string "status", default: "Application Started"
    t.string "final_decision", default: "Not Decided"
    t.bigint "user_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.boolean "returned", default: false
    t.text "approvals", default: [], array: true
    t.text "rejections", default: [], array: true
    t.index ["user_id"], name: "index_hardships_on_user_id"
  end

最佳答案

如果我是你,我想我会想创建一个ApplicationAction模型。类似于:

# == Schema Information
#
# Table name: application_actions
#
#  id               :bigint           not null, primary key
#  user_id          :integer
#  application_type :string
#  application_id   :integer
#  action           :integer
#  created_at       :datetime         not null
#  updated_at       :datetime         not null
#

class ApplicationAction < ApplicationRecord
  belongs_to :user
  belongs_to :application, polymorphic: true

  enum action: {
    approved:             0,
    rejected:             1,
    requested_to_modify:  2
  }
end

然后,在User模型中,执行以下操作:
# == Schema Information
#
# Table name: users
#
#  id         :bigint           not null, primary key
#  created_at :datetime         not null
#  updated_at :datetime         not null
#

class User < ApplicationRecord
  has_many :application_actions

  %i(
    approved
    rejected
    requested_to_modify
  ).each do |action_sym|
    %w(
      hardship
      scholarship
      charity
    ).each do |application_type|

      # Create the associations:
      #   - hardship_applications
      #   - scholarship_applications
      #   - charity_applications
      has_many "#{application_type}_applications".to_sym,
        -> { distinct },
        through:      :application_actions,
        source:       :application,
        source_type:  application_type.camelize

      # Define the methods:
      #   - approved_application_actions
      #   - rejected_application_actions
      #   - requested_to_modify_application_actions
      define_method("#{action_sym}_application_actions") do
        application_actions.send(action_sym)
      end

      # Define the methods:
      #   - approved_hardship_applications
      #   - rejected_hardship_applications
      #   - requested_to_modify_hardship_applications
      #   - approved_scholarship_applications
      #   - rejected_scholarship_applications
      #   - requested_to_modify_scholarship_applications
      #   - approved_charity_applications
      #   - rejected_charity_applications
      #   - requested_to_modify_charity_applications
      define_method("#{action_sym}_#{application_type}_applications") do
        send("#{application_type}_applications").
          joins(:application_actions).
          where(
            application_actions: {
              action: ApplicationAction.actions[action_sym]
            }
          )
      end

      # Define the methods:
      #   - hardship_applications_not_approved
      #   - hardship_applications_not_rejected
      #   - hardship_applications_not_requested_to_modify
      #   - scholarship_applications_not_approved
      #   - scholarship_applications_not_rejected
      #   - scholarship_applications_not_requested_to_modify
      #   - charity_applications_not_approved
      #   - charity_applications_not_rejected
      #   - charity_applications_not_requested_to_modify
      define_method("#{application_type}_applications_not_#{action_sym}") do
        application_type.
          camelize.
          constantize.
          where.
          not(id: send("#{action_sym}_#{application_type}_applications"))
      end

    end
  end

end

在您的Hardship模型中,执行以下操作:
# == Schema Information
#
# Table name: hardships
#
#  id               :bigint           not null, primary key
#  application_type :integer          default(NULL)
#  created_at       :datetime         not null
#  updated_at       :datetime         not null
#

class Hardship < ApplicationRecord
  has_many :application_actions, as: :application

  enum application_type: {
    accident:           0,
    catastrophe:        1,
    counseling:         2,
    family_emergency:   3,
    health:             4,
    memorial:           5,
    other_hardship:     6
  }
end

然后,如果我通过快速的RSpec测试:
require 'rails_helper'

RSpec.describe 'Hardship Applications' do
  before(:each) do
    @user_1               = User.create!
    @user_2               = User.create!
    @hardship_1           = Hardship.create!
    @user_1.
      application_actions.
      create!(application: @hardship_1).
      approved!
    @user_2.
      application_actions.
      create!(application: @hardship_1).
      rejected!
  end
  it "user_1 approved_hardship_applications to include hardship_1" do
    expect(@user_1.approved_hardship_applications).to include(@hardship_1)
  end
  it "user_1 hardship_applications_not_approved NOT to include hardship_1" do
    expect(@user_1.hardship_applications_not_approved).not_to include(@hardship_1)
  end
  it "user_1 rejected_hardship_applications NOT to include hardship_1" do
    expect(@user_1.rejected_hardship_applications).not_to include(@hardship_1)
  end
  it "user_2 approved_hardship_applications NOT to include hardship_1" do
    expect(@user_2.approved_hardship_applications).not_to include(@hardship_1)
  end
  it "user_2 hardship_applications_not_approved to include hardship_1" do
    expect(@user_2.hardship_applications_not_approved).to include(@hardship_1)
  end
  it "user_2 rejected_hardship_applications to include hardship_1" do
    expect(@user_2.rejected_hardship_applications).to include(@hardship_1)
  end
end

我得到。。。
Hardship Applications
  user_1 approved_hardship_applications to include hardship_1
  user_1 hardship_applications_not_approved NOT to include hardship_1
  user_1 rejected_hardship_applications NOT to include hardship_1
  user_2 approved_hardship_applications NOT to include hardship_1
  user_2 hardship_applications_not_approved to include hardship_1
  user_2 rejected_hardship_applications to include hardship_1

Finished in 0.13431 seconds (files took 0.90021 seconds to load)
6 examples, 0 failures

所以,你可以:
@need_approval = current_user.hardship_applications_not_approved

而不是:
@need_approval = Hardship.where.not(approvals.include?(current_user.id.to_s))

您还将注意到,在Hardship模型中,我将所有应用程序类型都设置为enum。这将减少空字段(假设Hardship应用程序只能是一种应用程序类型)。
似乎还有其他减少冗余的机会。例如,您可以创建PhysicalAddressPhoneNumberEmailAddress模型,并将它们与每种类型的应用程序相关联。您还可以将应用程序status创建为enum并将其默认为application_started。与final_decision相同。

10-08 00:37