我可以将ActiveRecord关系与Hstore中的字段一起使用吗?

时间:2016-04-18 21:51:07

标签: ruby-on-rails activerecord hstore sti

我可以使用hstore哈希中的字段通过活动记录belongs_to将模型绑定到另一个模型吗?我会详细说明:

我有一个User模型,它根据权限在其中一个字段上通过STI子类化到许多不同的其他User模型:

class User < ActiveRecord::Base
  self.inheritance_column = :role
  #other definitions and validations
end

这是一个这样的子模型,nightclub_boss模型,适用于我的应用程序的管理用户:

class NightclubBoss < User
  belongs_to :nightclub     #the boss record has a nightclub_id
  has_one :rp_boss          #rp_boss should have a nightclub_boss_id
  has_one :captain          #captain should have a nightclub_boss_id
end

这里的想法是使用以下信息扩展用户模型:

-User hierarchy (which user reports to who; get a list of who is under who as needed through the ORM)
-User origin (which user belongs to whatever other models are in the app)

所以我想出来的,为了避免使用稀疏的User表并避免制作大量的部分小型SQL表,就是在User模型上创建一个名为“hierarchy”的hstore字段,并将其映射到不同的属性上。应该填充的用户模型当且仅当有问题的用户需要存储层次结构信息时(即,在角色依赖的基础上; nightclub_boss不应具有与其他模型相同的层次结构信息在我的应用程序中):

class AddHstore < ActiveRecord::Migration
  def self.up
    enable_extension "hstore"
  end

  def self.down
    disable_extension "hstore"
  end
end

class AddHierarchyToUser < ActiveRecord::Migration
  def change
    add_column :users, :hierarchy, :hstore
    add_index :users, :hierarchy, using: :gin
  end
end

rake db:migrate

然后我将hstore_accesssor添加到我的模型中:

的Gemfile:

gem "hstore_accessor"

用户模型:

class User < ActiveRecord::Base
  self.inheritance_column = :role
  hstore_accessor :hierarchy, nightclub_id: :integer
  #other validations and definitions...
end

到目前为止一切都很好,用硬编码数据进行测试:

[1] pry(main)> NightclubBoss.find(99)
  NightclubBoss Load (1.3ms)  SELECT  "users".* FROM "users" WHERE "users"."role" IN ('NightclubBoss') AND "users"."id" = $1 LIMIT 1  [["id", 99]]
=> #<NightclubBoss:0x000000070bbb00
 id: 99,
 #...all other fields...
 role: "NightclubBoss",
 hierarchy: {"nightclub_id"=>"1"}>

[2] pry(main)> NightclubBoss.find(99).nightclub_id
  NightclubBoss Load (0.7ms)  SELECT  "users".* FROM "users" WHERE "users"."role" IN ('NightclubBoss') AND "users"."id" = $1 LIMIT 1  [["id", 99]]
=> 1

因此,当你打电话给“NightclubBoss.nightclub”时,你希望rails能够拉出相应的Nightclub.find(1)。好吧,它不会发生:

[3] pry(main)> NightclubBoss.find(99).nightclub
  NightclubBoss Load (0.7ms)  SELECT  "users".* FROM "users" WHERE "users"."role" IN ('NightclubBoss') AND "users"."id" = $1 LIMIT 1  [["id", 99]]
=> nil

我尝试了各种各样的事情来试图解决这个问题,但我还没有找到答案,是否有人可以提供帮助?

作为一种解决方法,我意识到我可以做到:

Nightclub.find(NightclubBoss.find(99).nightclub_id)

我得到的查询就好了。但我认为这可以改进,你希望能够做NightclubBoss.find(99).nightclub

我认为这可能是一个非常糟糕的做法。如果有更好的方法来模拟我需要的信息,请告诉我,我将非常感谢您的建议。谢谢!

1 个答案:

答案 0 :(得分:0)

我一夜之间发现Postgres有一个类似的数据类型叫做Jsonb,在你将哈希存储在关系数据库的字段中的意义上,它也与hstore类似。

显然目前无法通过ActiveRecord的限制来执行此匹配,该匹配仅限制与关系数据库字段的匹配:

PostgreSQL jsonb field in ActiveRecord belongs_to association

就个人而言,我对这个答案感到满意,所以如果没有人有更多信息,我会关闭这个帖子,当然我会修改我的架构。

想知道是否可以修补支持?