我也有一个具有相似关系的数据库。 Author、Post、Tag是主要型号,Subscribedtag和Tagging是通过has n, :through构建的。
class Author
include DataMapper::Resource
property :id, Serial
property :email, String, :unique => true
property :password, String
property :first_name, String
property :last_name, String
property :bio, Text
property :phone, String, :unique => true
property :twitter, String, :unique => true
property :facebook, String, :unique => true
property :show_phone, Boolean, :default => false
property :show_facebook, Boolean, :default => false
property :show_twitter, Boolean, :default => false
property :is_admin, Boolean, :default => false
property :this_login, DateTime
property :last_login, DateTime
property :session_lasting, Integer, :default => 0
has n, :posts
has n, :subscribedtags
has n, :tags, :through => :subscribedtags
end
class Post
include DataMapper::Resource
property :id, Serial
property :title, String, :required => true
property :body, Text, :required => true
property :is_blog_post, Boolean, :default => true
property :viewed, Integer, :default => 0
property :featured, Boolean, :default => false
property :created_at, DateTime
property :updated_at, DateTime
belongs_to :author
belongs_to :category
has n, :comments
has n, :taggings
has n, :tags, :through => :taggings
validates_length_of :title, :min => 3
validates_length_of :body, :min => 20
validates_format_of :title, :with => /\w/
#some other methods
end
class Tag
include DataMapper::Resource
property :id, Serial
property :name, String, :unique => true
has n, :taggings
has n, :posts, :through => :taggings
has n, :subscribedtags
has n, :authors, :through => :subscribedtags
validates_length_of :name, :min => 1
validates_format_of :name, :with => /\w/
# some other methods
end
class Tagging
include DataMapper::Resource
belongs_to :tag, :key => true
belongs_to :post, :key => true
end
class Subscribedtag
include DataMapper::Resource
belongs_to :tag, :key => true
belongs_to :author, :key => true
end
您定义模型的方式允许您像这样编写查询。
2.2.0 :016 > kant = Tag.get(25) # getting tag instance with id 25 and assign it to variable named kant
=> #<Tag @id=25 @name="İmmanuil Kant">
2.2.0 :017 > kant.posts
=> #returns post instances which has this tag.
2.2.0 :018 > kant.posts.count # count of posts with this tag.
=> 2
2.2.0 :021 > kant.posts.first.author.first_name
=> "Ziya" # check my author class and first_name attribute.
假设我想检索没有帖子的标签实例。
一个简单的红宝石命令。
2.2.0 :024 > Tag.each {|tnp| puts tnp.name if tnp.posts.count == 0}
Latın
Python
Ruby
Sosializm
Hegel
或者根据帖子检索标签。
2.2.0 :034 > p = Post.get(9)
=> #<Post @id=9 @title="Why we use Lorem Ipsum" @body=<not loaded> @is_blog_post=false @viewed=0 @featured=false @created_at=#<DateTime: 2015-08-02T23:14:04+05:00 ((2457237j,65644s,0n),+18000s,2299161j)> @updated_at=#<DateTime: 2015-08-02T23:14:04+05:00 ((2457237j,65644s,0n),+18000s,2299161j)> @author_id=1 @category_id=1>
2.2.0 :035 > p.tags
=> [#<Tag @id=19 @name="Bundesliqa">]
检索没有标签的帖子。
2.2.0 :043 > Post.each {|pnt| puts pnt.id if pnt.tags.count.zero?}
8 #post with id has no tags
2.2.0 :044 > Post.get(8).tags.count
=> 0
您还可以通过其他属性进行查询。
2.2.0 :046 > Tag.first(:name => "Lorem").id
=> 30
遍历结果
2.2.0 :050 > Tag.first(:name => "Lorem").posts.each {|lorempost| puts lorempost.title} # printing post titles which are tagged with lorem.
Get'em all
qwerty
我还通过Subscribedtags模型将作者与标签相关联,我可以很容易地检查哪个作者订阅了哪个标签,反之亦然。
2.2.0 :055 > z = Author.get(1)
=> # returns details of author instance
2.2.0 :056 > z.tags
=> [#, #, #, #]
或通过订阅标签查询
2.2.0 :057 > z.subscribedtags
=> [#<Subscribedtag @tag_id=2 @author_id=1>, #<Subscribedtag @tag_id=4 @author_id=1>, #<Subscribedtag @tag_id=25 @author_id=1>, #<Subscribedtag @tag_id=30 @author_id=1>]
您还可以定义自己的函数来使用查询。我已经定义了一个 subscribed_tags 方法,它返回一个订阅标签名称的数组。
2.2.0 :058 > z.subscribed_tags
=> ["Həyat", "Məstan", "İmmanuil Kant", "Lorem"]
如果我想检索一个随机作者的 first_name 属性,该作者订阅了名为“Lorem”的标签,
2.2.0 :062 > Tag.first(:name => "Lorem").authors.sample.first_name
=> "Ziya"
作为第二个问题的答案,是的,大多数时候你必须迭代。
因为Photos.all 返回照片对象实例的集合。并且这个实例单独具有标签属性,而不是由 Photo 实例组成的数组。
如果您调用p = Photo.all; print p.tags;,它将返回与所有照片关联的所有标签,这可能是您想要的,也可能不是。
如果这些还不够,请随时提出更多问题。