ohm
ohm copied to clipboard
Tagging example
In the tagging example, we can find posts having a certain tag with this:
Post.find(tag: 'tagging')
Now how would someone be able to get the posts matching a tag (pretty much reversed logic) ?
I'm assuming you would need a reference in the Tag
model to the Post model but I can't quite figure it in the Ohm way:
class Tag < Ohm::Model
counter :total
reference :posts, :Post
# How would you query Tag model after that to find the posts associated ?
Any chance it could be added to the example ?
Thanks a lot!
@scalp42 I don't use a Tag
model, so for me if I have a tag t
, I do Post.find(tag: t)
as you described. What kinds of features do you expect a Tag
model to provide? I see you want to have counters, for example, and a reference to Post
. Would it be polymorphic? What about new tags: are users allowed to create new tags or they are created by you beforehand? There are ways to implement all those features, but each approach is slightly different. Let me know.
I think I'm trying to figure the many-to-many relationship with Ohm in the case of Post having multiple Tag and Tag belonging to multiple Post if it make sense ?
Thanks a lot for the quick answers as always, greatly appreciated.
@scalp42 Looking back at this issue, did you find a way to do what you needed? If not, let me know and I'll work on an example.
Let's assume a vendor (Google
), having multiple users subscribed to its paying products (Youtube
, Music
, etc), the models would like like this:
class User < Ohm::Model
attribute :name
end
class Subscription < Ohm::Model
reference :user, :User
reference :product, :Product
end
class Product < Ohm::Model
attribute :name
reference :vendor, :Vendor
end
class Vendor < Ohm::Model
attribute :name
collection :products, :Product
end
Now let's create an user, a vendor and a product to match the description above:
user = User.create(name: '[email protected]')
vendor = Vendor.create(name: 'google')
product = Product.create(name: 'youtube', vendor: vendor)
Now we want to have our user John
subscribed to Youtube
:
Subscription.create(user: user, product: product)
Let's assume that we have dozen of users, vendors, products and subscriptions that go with it. We can query our "join table" to get the exact info we need:
# This would return all the users subscribed to the "youtube" product
Subscription.find(product_id: product.id).map(&:user)
# This would return all products that a particular user "John" is subscribed to:
Subscription.find(user_id: user.id).map(&:product)
# Which then could also returns all the vendors user "John" is subscribed to:
Subscription.find(user_id: user.id).map(&:product).map { |p| p.vendor.name }
=> ["google"]
Couple extras to help understand references relation:
Product.all.first
=> #<Product:0x007fa303991698 @_memo={}, @attributes={:type=>"youtube", :vendor_id=>"1"}, @id="1">
Subscription.find(user_id: user.id).first
=> #<Subscription:0x007fa3033a3bf0 @_memo={}, @attributes={:user_id=>"1", :product_id=>"1"}, @id="1">
Subscription.find(user_id: user.id).first.product
=> #<Product:0x007fa303307a48 @_memo={}, @attributes={:type=>"youtube", :vendor_id=>"1"}, @id="1">
Product.find(vendor_id: vendor.id).first
=> #<Product:0x007fa3032bea50 @_memo={}, @attributes={:type=>"youtube", :vendor_id=>"1"}, @id="1">
Product.find(vendor_id: vendor.id).first.vendor
=> #<Vendor:0x007fa3031b4d58 @_memo={}, @attributes={:name=>"google"}, @id="1">
Product.find(vendor_id: vendor.id).first.vendor.products.first
=> #<Product:0x007fa30357b1a8 @_memo={}, @attributes={:type=>"youtube", :vendor_id=>"1"}, @id="1">
Vendor.all.first
=> #<Vendor:0x007fa30190f1b8 @_memo={}, @attributes={:name=>"google"}, @id="1">
Vendor.all.first.products.first
=> #<Product:0x007fa303aa1b50 @_memo={}, @attributes={:type=>"youtube", :vendor_id=>"1"}, @id="1">
One thing to note is that when you write:
class Subscription < Ohm::Model
reference :user, :User
reference :product, :Product
end
The reference
actually creates an index that you can query with an id hence:
Subscription.find(product_id: product.id)
Hopefully it helps others @soveran, thanks again for the help and sorry for the delay!
@scalp42 That's excellent! Thanks!