【问题标题】:Retrieve records which have many-to-many association, using ruby and datamapper使用 ruby​​ 和 datamapper 检索具有多对多关联的记录
【发布时间】:2016-01-08 13:44:17
【问题描述】:

我正在学习 Sinatra,我已经阅读了 datamapper 文档并找到了这个 n 对 n 关系示例:

class Photo
    include DataMapper::Resource
    property :id, Serial
    has n, :taggings
    has n, :tags, :through => :taggings
end
class Tag
    include DataMapper::Resource
    property :id, Serial
    has n, :taggings
    has n, :photos, :through => :taggings
end
class Tagging
    include DataMapper::Resource
    belongs_to :tag,   :key => true
    belongs_to :photo, :key => true
end

我从上面的代码中了解到,一张照片可能有很多或零个标签,而一个标签可能有很多或零个照片。如何检索已加载与其关联的标签的照片列表。我知道 datamapper 使用惰性方法,因此它不会自动加载关联的类(在本例中为 photo.tag)。所以这个:

photos = Photo.all

将产生一个带有不带标签的 Photo 对象的数组。有没有办法自动检索它,还是我必须遍历数组并手动设置?

提前致谢!

【问题讨论】:

    标签: ruby sinatra datamapper


    【解决方案1】:

    我也有一个具有相似关系的数据库。 AuthorPostTag是主要型号,SubscribedtagTagging是通过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;,它将返回与所有照片关联的所有标签,这可能是您想要的,也可能不是。

    如果这些还不够,请随时提出更多问题。

    【讨论】:

      猜你喜欢
      • 2013-05-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-13
      • 1970-01-01
      • 2011-02-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多