【问题标题】:Rails model/query for "profiles of people from contact list who are attending event"Rails 模型/查询“联系人列表中正在参加活动的人员的个人资料”
【发布时间】:2014-10-02 02:00:57
【问题描述】:

所以这涉及到很多关系。最终目标是在活动视图中显示当前用户的联系人列表中正在参加活动的人员。目前的模型布局是这样的:

# Table name: profiles
#  id                  :integer          not null, primary key
#  profileable_id      :integer
#  profileable_type    :string(255)
class Profile < ActiveRecord::Base
  belongs_to :profileable, polymorphic: true
  has_many :events, as: :eventable, dependent: :destroy
end

# Table name: events
#  id             :integer          not null, primary key
#  eventable_id   :integer
#  eventable_type :string(255)
class Event < ActiveRecord::Base
  belongs_to :eventable, polymorphic: true
  has_many :attendants, dependent: :destroy
end

# Table name: attendants
#  id                    :integer          not null, primary key
#  referrer_profile_id   :integer
#  event_id              :integer
#  responding_profile_id :integer
class Attendant < ActiveRecord::Base
  belongs_to :event
end

# Table name: contacts
#  id         :integer          not null, primary key
#  user_id    :integer
class Contact < ActiveRecord::Base
  belongs_to :user
  has_one :profile, as: :profileable, dependent: :destroy
end

显然,更多与关系相关的行会有所帮助,一些范围和有助于加入的东西(我相信)。

我想做的事情是这样的:

@attendants = Attendant.where(event_id: @event.id)
@contacts = Contacts.where(user_id: current_user.id)
@result = @attendents.select {|i| @contacts.any? {|c| i.responding_profile_id == c.profile.id } }

据我了解,这是效率最低的方法。如果你能帮助我正确的 joinsmergescope 和其他 has/belongs 关系线完成这个我将永远感激不尽!


这是关系模型图。 Profile 和 Event 是多态的。服务员是一个关系表。

我查询了一个将话务员和个人资料作为 JSON 的示例。也许这会有所帮助。

Contact.find(8).profile.as_json
  Contact Load (0.6ms)  SELECT  "contacts".* FROM "contacts"  WHERE "contacts"."id" = $1 LIMIT 1  [["id", 8]]
  Profile Load (0.3ms)  SELECT  "profiles".* FROM "profiles"  WHERE "profiles"."profileable_id" = $1 AND "profiles"."profileable_type" = $2 LIMIT 1  [["profileable_id", 8], ["profileable_type", "Contact"]]
 => {"id"=>11, "first_name"=>"Apple", "last_name"=>"Dumpling", "profileable_id"=>8, "profileable_type"=>"Contact", "created_at"=>Fri, 10 Oct 2014 02:21:20 UTC +00:00, "updated_at"=>Fri, 10 Oct 2014 02:21:20 UTC +00:00} 

Attendant.second.as_json
  Attendant Load (0.8ms)  SELECT  "attendants".* FROM "attendants"   ORDER BY "attendants"."id" ASC LIMIT 1 OFFSET 1
 => {"id"=>2, "confirmation"=>"attending", "referrer_profile_id"=>1, "responding_profile_id"=>8, "event_id"=>1, "created_at"=>Fri, 10 Oct 2014 17:46:44 UTC +00:00, "updated_at"=>Fri, 10 Oct 2014 17:46:44 UTC +00:00} 

【问题讨论】:

  • 这可以使用Attendant.where 和一些 SQL 轻松解决,但我无法掌握您的模型关系。您能否发布相关架构?
  • 您正在查看注释代码中的架构,我添加了一个可视图像。
  • 这个问题可能没有答案。联系人的个人资料 ID 与实际用户的个人资料 ID 不同,因为该信息是 dup'ed。我正在考虑在创建时将外部引用引用到联系人中,以正确引用包含配置文件的其他帐户的联系人。

标签: ruby-on-rails activerecord


【解决方案1】:

如果没有您的数据库,我无法对其进行测试,但是查看您的架构,这应该会返回参加给定活动的当前用户的每个联系人的个人资料。

 Profile.where('id 
   IN (SELECT attendants.responding_profile_id FROM attendants WHERE attendants.responding_profile_id 
   IN (SELECT profiles.id FROM profiles WHERE profiles.id 
   IN(SELECT contacts.profile_id FROM contacts WHERE contacts.user_id = ?)) 
   AND attendants.event_id = ?)', current_user.id, @event.id)

【讨论】:

  • PG::UndefinedTable: ERROR: missing FROM-clause entry for table "profile" 另外contacts.profile_id 应该是contacts.profile.id
【解决方案2】:

我不确定这是否正确,但查看您的架构是我想出的:

Profile.select(Arel.star).where(
  Profile.arel_table[:profileable_id].in(
    Event.select(Attendant.arel_table[:responding_profile_id]).where(
      Event.arel_table[:id].eq(@event.id).and(
        Attendant.arel_table[:responding_profile_id].in(
         Attendant.select(Attendant.arel_table[:responding_profile_id]).where(
            Contact.arel_table[:user_id].eq(current_user_id)
          ).joins(
            Attendant.arel_table.join(Contact.arel_table).on(
              Attendant.arel_table[:responding_profile_id].eq(Contact.arel_table[:id])
            ).join_sources
          ).ast
        )
      )
    ).ast
  )
)

这是供参考的SQL:

SELECT * from Profile 
    where Profile.profileable_id in 
        (select Attendant.responding_profile_id from Event 
            where Event.id = @event.id
            and Attendant.responding_profile_id in
                (select Attendant.responding_profile_id from Attendant inner join Contact 
                    on Attendant.responding_profile_id = Contact.id
                    where Contact.user_id = current_user_id
                )
        )

【讨论】:

  • 我可能在Attendant 中缺少关系定义。我目前得到PG::UndefinedTable: ERROR: missing FROM-clause entry for table "attendants"。我仍然非常感谢您的回答。希望我能从中学到什么。
  • 没问题。很高兴为您提供帮助!
【解决方案3】:

这个问题是配置文件是多态意味着它通过它的关联表选择它的父母。在我的问题中,我曾要求通过使用相同的 ID/类型为两个不同的父项找到相同的配置文件。这是不可能的,因为它不一样。 当前代码不起作用。为了解决这个问题,我在 original_profile_idContact 中添加了一个字段,该字段是在复制个人资料时写入的,以始终引用原始来源。现在突然之间,因为不可能而变得复杂的事情很容易解决。

【讨论】:

    猜你喜欢
    • 2018-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-12
    相关资源
    最近更新 更多