【问题标题】:Elegant Advanced Rails Queries优雅的高级 Rails 查询
【发布时间】:2011-03-24 11:02:01
【问题描述】:

我无法理解更高级的 Rails 查询方法。在本例中,我有三个表:Users、Friendships 和 Events。

我在每个模型中都设置如下

用户-> :has_many => :friendships, :has_many => :items

友谊-> :belongs_to => :user

事件-> belongs_to => :user

友谊只是两列:“user_id”和“friend_id”,因此每个新友谊都会创建两个新行。

这是我用来查找“属于 current_user 的朋友的前四个事件,其 start_date 晚于现在”的查询。

find_by_sql(["SELECT DISTINCT e.id
              FROM events e
              WHERE e.start_date > ?
              AND e.user_id IN(
              SELECT f.user_id
              FROM friendships f
              WHERE f.friend_id = ?)
              LIMIT 0,4", Time.zone.now,current_user.id])

在 Rails 中做这种事情的真正优雅的方法是什么?我感觉这也太低效了……

【问题讨论】:

    标签: mysql ruby-on-rails


    【解决方案1】:

    您应该可以使用:join:conditions

    time_range = (Time.now.midnight - 4.days)..Time.now.midnight
    Event.all :joins => :friendships, :conditions => 
       {'start_date' => time_range, 'friendships.friend_id' => current_user.id}, :limit => 4
    

    我还没有真正完成很多这样的复杂查询,但我从这里的示例中拼凑起来:http://guides.rubyonrails.org/active_record_querying.html

    编辑: 您可能需要添加到事件:

    has_many :friends, :through => :friendships
    

    Edit2:看起来你必须实际使用嵌套连接:

    Event.all :joins => {:user => :friendships }, :conditions => {'start_date' => time_range, 'friendships.friend_id' => current_user.id }
    

    这是我使用的模型代码:

    class User < ActiveRecord::Base
      has_many :events, :foreign_key => "user_id"
      has_many :friendships
      has_many :friends, :through => :friendships, :source => :user, :uniq => true
    end
    
    class Event < ActiveRecord::Base
      belongs_to :user
      has_many :friendships, :through => :user
    end
    
    class Friendship < ActiveRecord::Base
      belongs_to :user
    end
    

    并且,如果可能有帮助的话,一些示例输出:

    >> Event.all :joins => {:user => :friendships }, :conditions => {'happens_on' => time_range, 'friendships.user_id' => 1 }
    Event.all :joins => {:user => :friendships }, :conditions => {'happens_on' => time_range, 'friendships.user_id' => 1 }
    => [#<Event id: 1, happens_on: "2010-08-06 00:42:37", title: "Jims party", description: "Happy Birthday", created_at: "2010-08-03 00:42:37", updated_at: "2010-08-03 00:42:37", user_id: 1>]
    >> jim = User.find(1)
    jim = User.find(1)
    => #<User id: 1, name: "Jim", bio: "Loves Rails", age: 30, created_at: "2010-08-03 00:30:51", updated_at: "2010-08-03 00:30:51">
    >> crystal = User.find(2)
    crystal = User.find(2)
    => #<User id: 2, name: "Crystal", bio: "Loves writing", age: 26, created_at: "2010-08-03 00:31:14", updated_at: "2010-08-03 00:31:14">
    >> jim.events
    jim.events
    => [#<Event id: 1, happens_on: "2010-08-06 00:42:37", title: "Jims party", description: "Happy Birthday", created_at: "2010-08-03 00:42:37", updated_at: "2010-08-03 00:42:37", user_id: 1>]
    >> event1 = jim.events[0]
    event1 = jim.events[0]
    => #<Event id: 1, happens_on: "2010-08-06 00:42:37", title: "Jims party", description: "Happy Birthday", created_at: "2010-08-03 00:42:37", updated_at: "2010-08-03 00:42:37", user_id: 1>
    >> event1.user
    event1.user
    => #<User id: 1, name: "Jim", bio: "Loves Rails", age: 30, created_at: "2010-08-03 00:30:51", updated_at: "2010-08-03 00:30:51">
    >> event1.friendships
    event1.friendships
    => [#<Friendship user_id: 1, friend_id: nil, created_at: "2010-08-03 00:57:31", updated_at: "2010-08-03 00:57:31">]
    >> 
    

    【讨论】:

    • 您也可以根据自己的情况将:select =&gt; "DISTINCT(id)" 添加到Event.all 选项中
    • 是的,我收到“未找到名为‘friendship’的协会;也许你拼错了?”有什么解决办法吗?
    • 杰克:我用一些代码更新了我的答案,其中包含对与您指定的模型相似的模型的有效查询。
    猜你喜欢
    • 2015-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-08
    • 2012-02-08
    相关资源
    最近更新 更多