ActiveRelation需要嵌套的联接使用范围 [英] ActiveRelation that requires nested joins using scopes

查看:149
本文介绍了ActiveRelation需要嵌套的联接使用范围的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是新来的轨道。有一个爆炸。查询API,虽然是给我 有些麻烦。我一直在放大,做了很多的东西非常快, 但是这是第一次我花了几个小时试图弄明白。 它不喜欢什么,我以前用过的 - 常规的SQL,或休眠状态, 或什么的。

I am new to rails. Having a blast. The query API though is giving me some trouble. I've been zooming and doing a lot of stuff very quickly, but this is the first time I have spent hours trying to figure it out. It's not like anything I've used before - regular SQL, or Hibernate, or whatever.

该模型我已经是pretty的简单。

The model I have is pretty simple.

  • 系统PrivateMessage有许多收件人
  • 在收件人有一个接收器(哪一类用户的)
    • 在接收方也有场is_read'和'IS_DELETED
    • A PrivateMessage has many Recipients
    • A Recipient has a Receiver (which of class User)
      • recipient also has fields for 'is_read' and 'is_deleted'

      我的目标是建立一个查找所有未读,不会被删除查询 私人讯息​​给定用户。要做到这一点,我们需要加入 private_messages到收件人......然后'收件人'到 用户。

      My goal is to build a query that finds all the unread and not deleted private messages for a given user. To accomplish this, we need to join 'private_messages' to 'recipients'... and then 'recipients' to 'users'.

      下面是有关用户模型code:

      Here's the relevant User model code:

      has_many :sent_messages, :class_name => 'PrivateMessage', :foreign_key => 'sender_id'
      has_many :recipient_of_messages, :class_name => 'Recipient', :foreign_key => 'receiver_id'
      
      scope :by_id, lambda { |id| where(:id => id) } 
      

      我的收件人模式具有以下相关code:

      My Recipient model has the following relevant code:

      belongs_to :receiver, :class_name => 'User', :foreign_key => "receiver_id"
      belongs_to :private_message
      
      scope :unread, where(:is_read => false).where(:is_deleted => false)
      scope :by_receiver_id, lambda { |id| Recipient.joins(:receiver).merge(User.by_id(id)) }
      scope :unread_by_receiver_id, lambda { |id| unread.by_receiver_id(id) }
      

      当单独测试,该工程100%。

      When tested in isolation, this works 100%.

      然而,当我code中的私人信息查询,我遇到的问题。

      However, when I code the private message queries, I run into problems.

      belongs_to :sender, :class_name => 'User'
      has_many :recipients, :class_name => 'Recipient'
      
      scope :sorted, order("private_messages.created_at desc")
      scope :non_deleted, where(:is_deleted_by_sender => false)
      scope :non_deleted_by_sender_id, lambda { |id| sorted.non_deleted.joins(:sender).merge(User.by_id(id)) }
      
      # this scope does not work
      scope :non_deleted_by_receiver_id, lambda { |id| sorted.joins(:recipients).merge(Recipient.by_receiver_id(id)) }
      scope :newest, sorted.limit(3)
      
      # this scope does not work either
      scope :newest_unread_by_receiver_id, lambda { |id| newest.joins(:recipients).merge(Recipient.unread_by_receiver_id(id)) }
      

      当我尝试使用newest_unread_by_receiver_id'或'non_deleted_by_receiver_id',我得到了以下异常:

      When I try and use 'newest_unread_by_receiver_id' or 'non_deleted_by_receiver_id', I get the following exception:

      ActiveRecord::ConfigurationError: Association named 'receiver' was not found; perhaps you misspelled it?
      

      这没有多大意义的,我......因为如果名字被拼写 错了,为什么没有当我测试它隔离失败?

      This doesn't make much sense to me... because if the name was spelled wrong, why doesn't it fail when I test it isolation?

      有人能帮助我吗?这一个是我发疯。有时 就是这样,我只是想在完整SQL编程或休眠QL所以我只能用它做:(

      Can someone help me out please? This one is driving me nuts. At times like this, I just want to program in full sql or Hibernate QL so I could just be done with it :(

      如果我只是接近问题完全错误的,那么我会AP preciate它,如果你只是让我知道这一点。我在使用作用域和ActiveRelation是一路前进中的Rails 3.1的IM pression。

      If I'm just approaching the problem totally wrong, then I'd appreciate it if you just let me know that too. I am under the impression that using scopes and ActiveRelation was the way moving forward in Rails 3.1.

      感谢

      推荐答案

      我可能会用这样的事情。我不停的范围分隔清晰。

      I would probably use something like this. I kept scopes separate for clarity.

      模型(改名PrivateMessage - >和收件人 - > MessageCopy):

      Models (renamed PrivateMessage -> Message and Recipient -> MessageCopy):

      class User < ActiveRecord::Base
        has_many :sent_messages, :class_name => "Message", :foreign_key => :sender_id
        has_many :sent_message_copies, :through => :sent_messages, :source => :message_copies
        has_many :received_messages, :through => :received_message_copies, :source => :message
        has_many :received_message_copies, :class_name => "MessageCopy", :foreign_key => :recipient_id
      end
      
      class Message < ActiveRecord::Base
        belongs_to :sender, :class_name => "User"
        has_many :message_copies
        has_many :recipients, :through => :message_copies
      end
      
      class MessageCopy < ActiveRecord::Base
        belongs_to :message
        belongs_to :recipient, :class_name => "User"
        scope :unread, where(:read => false)
        scope :undeleted, where(:deleted => false)
        scope :sent_to, lambda { |recipient| where(:recipient_id => recipient.id) }
      end
      

      模式(迁移将采取太多的空间,在这里):

      Schema (migrations would have taken too much space here):

      ActiveRecord::Schema.define(:version => 20110503061008) do
        create_table "message_copies", :force => true do |t|
          t.boolean  "read",         :default => false
          t.boolean  "deleted",      :default => false
          t.integer  "message_id"
          t.integer  "recipient_id"
        end
        create_table "messages", :force => true do |t|
          t.string   "title"
          t.integer  "sender_id"
        end
        create_table "users", :force => true do |t|
          t.string   "name"
        end
      end
      

      - 修改

      --edit

      示例查询中使用联接返回的消息

      Message.joins(:message_copies).where(:message_copies => {:read => false, :deleted => false, :recipient_id => 3})
      

      信息范围重复使用于其他型号范围

      scope :non_deleted_by_recipient, lambda { |recipient|
        joins(:message_copies).merge(MessageCopy.unread.undeleted.sent_to(recipient))
      }
      

      - EDIT2

      --edit2

      这Railscast具有很好的例子的两个连接和范围:

      This Railscast has nice examples of both joins and scopes:

      这篇关于ActiveRelation需要嵌套的联接使用范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆