使用Rails 5枚举PGarrays

我正在尝试将Rails的枚举用于PostgreSQL的数组列。

class Post < ActiveRecord::Base enum tags: { a: 0, b: 1, c: 2 }, array: true end 

但是上面的代码不起作用

有没有办法在数组列上使用枚举像arrtibute支持array: true

编辑

我想看到以下测试用例通过,但实际上它失败了。

 # frozen_string_literal: true begin require "bundler/inline" rescue LoadError => e $stderr.puts "Bundler version 1.10 or later is required. Please update your Bundler" raise e end gemfile(true) do source "https://rubygems.org" git_source(:github) { |repo| "https://github.com/#{repo}.git" } # Activate the gem you are reporting the issue against. gem "activerecord", "5.1.4" gem "pg" end require "active_record" require "minitest/autorun" require "logger" # Ensure backward compatibility with Minitest 4 Minitest::Test = MiniTest::Unit::TestCase unless defined?(Minitest::Test) # This connection will do for database-independent bug reports. ActiveRecord::Base.establish_connection(adapter: "postgresql", database: "test") ActiveRecord::Base.logger = Logger.new(STDOUT) ActiveRecord::Schema.define do create_table :products, force: true do |t| t.integer :type_delivery, default: [], array: true, limit: 8 end end class Product < ActiveRecord::Base enum type_delivery: { a: 1, b: 2, c: 3, d: 5 }, array: true end class BugTest < Minitest::Test def test_array_enum product = Product.create!(type_delivery: %w[abc]) assert_equal products.type_delivery, %w[abc] end end 

错误是:

 /usr/local/var/rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/activerecord-5.1.4/lib/active_record/enum.rb:172:in `block (2 levels) in enum': undefined method `each_with_index' for true:TrueClass (NoMethodError) from /usr/local/var/rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/activerecord-5.1.4/lib/active_record/enum.rb:171:in `module_eval' from /usr/local/var/rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/activerecord-5.1.4/lib/active_record/enum.rb:171:in `block in enum' from /usr/local/var/rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/activerecord-5.1.4/lib/active_record/enum.rb:154:in `each' from /usr/local/var/rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/activerecord-5.1.4/lib/active_record/enum.rb:154:in `enum' from guides/bug_report_templates/active_record_gem.rb:38:in `' from guides/bug_report_templates/active_record_gem.rb:37:in `' 

由于这个问题仍然没有答案,所以这是如何做到的:

首先,在enum方法上没有array: true选项,只需将其保留。

其次,添加自定义范围以检索与交付匹配的产品

 scope :with_delivery_type, ->(*delivery_types) do normalized = Array(delivery_types).flatten where('delivery_types @> ?', "{#{normalized.join(',')}}") end 

最后但同样重要的是,我建议使用字符串或Postgres枚举类型而不是整数列。 整数列是有问题的,因为对于其中一个,要读取它,需要编写记录的应用程序的源代码(插入时的版本),其次,不必要地删除或替换值。

Rails的enum api将属性映射到单个整数列。 如果需要,您可以创建自己的位掩码以支持多个属性( 通常使用用户角色 )。

认为您正在寻找的是属性api ,您甚至可以实现自定义ActiveRecord :: Type来处理validation。

Rails 5 ++

 rails generate migration AddTypeDeliveryToProducts type_delivery:integer class AddTypeDeliveryToProducts < ActiveRecord::Migration[5.1] def change add_column :products, :type_delivery, :integer, array:true, default: [], limit: 8 end end class Product < ApplicationRecord enum type_delivery: { a: 1, b: 2, c: 3, d: 4 } end