自定义rails has_many关联(通过pg数组)

时间:2012-12-19 12:43:24

标签: ruby-on-rails ruby ruby-on-rails-3

所以基本上我想知道是否有一些常用的方法来定义自己的关联类型。 一些细节:

我有一个模型conversations,它有一个PG数组列user_ids。 因此,要检索我需要运行的用户对话: select conversations.* from conversations where USER_ID = ANY(conversations.user_ids)

由于finder_sql及其朋友现在已被弃用,我真的想知道实现此伪has_many关联的最佳方法是什么?

目前我只使用以下方法:

 def conversations
   Conversation.where("#{id} = ANY (conversations.users)")
 end

所以基本上我正在考虑实施我自己的ActiveRecord::Associations::CollectionAssociation,并想知道是否有一些好的参考资料,或者你是否可以建议从哪里开始


4 个答案:

答案 0 :(得分:0)

怎么样:

Conversation.user.select{ |conversation| conversation.user_ids.include?(params[:id])

考虑到user_ids列已序列化并且当前用户ID由params [:id]

传递

主要方法是,如果你有一个数组,你可以用.include?(某事)方法检查它是否有'某事'。以这种方式思考,您可以使用select方法实际选择具有include方法在此数组中具有其ID的对象(在本例中为用户)。我清楚了吗?

告诉我它是否有用......

答案 1 :(得分:0)

我认为你基本上可以把方法代码放在一个关系中:

has_many :conversations, ->(user) { where("#{user.id} = ANY (conversations.users)") }
但是,它应该最终都是相同的。您的方法返回一个可以链接的关系。另一种选择可能是:

has_many :conversations, -> { where('users.id IN conversations.users') }

可能需要一些指导。你有什么理由不能添加新的联接表吗?理想的情况是将其迁移到conversations_users表。然后,您可以干净地加入表,并利用外键约束。

答案 2 :(得分:0)

您应该将其重新结构化为保存了session_id和user_id的参考表,然后可以使用Rails(https://guides.rubyonrails.org/association_basics.html#the-has-many-through-association)的最佳实践

如果您仍然希望保留此结构,我建议:

User.where(id: conversion.user_ids)(转换是“会话”表的一个实例)

答案 3 :(得分:0)

我建议规范化您的模型,使其具有另一个表来保持用户和对话之间的关系,例如,建立类似的模型

UsersConversation

与您的关系将会

class User < ApplicationRecord
  has_many :users_conversations, :dependent => :destroy
  has_many :conversations, :through => :users_conversations
end

class Conversation < ApplicationRecord
  has_many :users_conversations, :dependent => :destroy
  has_many :users, :through => :users_conversations
end     

那么您可以轻松地完成

#users for each specific conversation
@users = Conversation.find(1).users
#conversations for each specific user
@conversations = User.find(1).conversations

除非您希望保持相同的方式或数组,否则可以这样做

@users = User.where(:id => Conversation.find(1).user_ids)

如果将user_ids存储为[1,10,20]这样的数组 因此,它将正常工作并返回用户