Can I tie a model to another through active record belongs_to using a field from an hstore hash? I'll elaborate:
I have a User model that gets subclassed via STI on one of its fields to many different other User models based on permissions:
class User < ActiveRecord::Base
self.inheritance_column = :role
#other definitions and validations
end
Here's one such submodel, the nightclub_boss model, meant for administrative users for my app:
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
The idea here is to expand the User model with info such as:
-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)
So what I came up with, to avoid having a sparse User table and also to avoid making lots of partial little SQL tables, is to create an hstore field on the User model called "hierarchy" and map it to different attributes on the User model which should get populated if and only if the User in question needs to store hierarchy information (that is, on a role-dependent-basis; nightclub_boss should not have the same hierarchy information as other models in my app):
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
Ran
rake db:migrate
And then I added hstore_accesssor to my model:
Gemfile:
gem "hstore_accessor"
User model:
class User < ActiveRecord::Base
self.inheritance_column = :role
hstore_accessor :hierarchy, nightclub_id: :integer
#other validations and definitions...
end
Everything is good so far, testing with hardcoded data:
[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
So you'd expect rails to pull the corresponding Nightclub.find(1) that's bound to this model when calling "NightclubBoss.nightclub", right? Well, it doesn't happen:
[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
I've tried all sorts of things to try to figure this out and I haven't found the answer yet, is there anyone who can help?
As a workaround I realize I can do:
Nightclub.find(NightclubBoss.find(99).nightclub_id)
And I get the query just fine. But I think this can be improved, you'd expect to be able to do NightclubBoss.find(99).nightclub
I think this may also be a very bad practice to follow. If there's a better way to model the kind of information that I need, please let me know, I'll appreciate your advice. Thanks!
I found overnight that Postgres has a similar data type called Jsonb, which also does a similar thing to hstore in the sense that you store a hash in a field in the relational database.
Apparently it is not currently possible due to a limitation in ActiveRecord to make this match. It constrains matches to relational database fields only:
PostgreSQL jsonb field in ActiveRecord belongs_to association
Personally, I'm satisfied with that answer so I'll close this thread if nobody has more info, and I'll modify my schema to not depend on hash fields.
Wonder if support could be patched?