Ruby on rails 一个关系与多个模型[有趣的rails关系概念]

Ruby on rails 一个关系与多个模型[有趣的rails关系概念],ruby-on-rails,activerecord,orm,model,relationship,Ruby On Rails,Activerecord,Orm,Model,Relationship,我有一个应用程序,模型用户可以有多个“频道”。应用程序的频道部分必须易于扩展,每个频道都有自己的型号 我开始创建一个频道模型,其中属于用户关系与用户频道相反 我正在考虑使用类似的API: user = User.create(name: 'John') user.channels.create(name: 'google', account_id: '1234') # should create a GoogleChannel::Google Model user.channels.creat

我有一个应用程序,模型
用户
可以有多个“频道”。应用程序的频道部分必须易于扩展,每个频道都有自己的型号

我开始创建一个
频道
模型,其中
属于
用户
关系与
用户
频道
相反

我正在考虑使用类似的API:

user = User.create(name: 'John')

user.channels.create(name: 'google', account_id: '1234') # should create a GoogleChannel::Google Model
user.channels.create(name: 'facebook', account_name: 'qwerty') # should create a FacebookChannel::Facebook Model
我在玩弄一个
频道
模式,每个频道模式都有一个专门的模式,每个频道(谷歌、facebook等)都有一个
与该模式的关系

更新:


我正在使用带有rails的mongoid,我不确定这是否有效。它使用STI

第一种方法:单表继承

class User << ApplicationRecord
  has_many :channels
  delegate :google_channels, :facebook_channels, :twitter_channels, to: :channels
end

class Channel << ApplicationRecord
  belongs_to :user
  self.inheritance_column = :brand

  scope :google_channels,   -> { where(brand: 'Google')   } 
  scope :facebook_channels, -> { where(brand: 'Facebook') } 
  scope :twitter_channels,  -> { where(brand: 'Twitter') }

  def self.brands
    %w(Google Facebook Twitter)
  end 
end

class GoogleChannel << Channel; end
class FacebookChannel << Channel; end
class TwitterChannel << Channel; end
class用户{where(品牌:'Facebook')}
范围:twitter_频道,->{where(品牌:'twitter')}
def自助品牌
%w(谷歌Facebook推特)
结束
结束

我不确定这是否有效。它使用STI

第一种方法:单表继承

class User << ApplicationRecord
  has_many :channels
  delegate :google_channels, :facebook_channels, :twitter_channels, to: :channels
end

class Channel << ApplicationRecord
  belongs_to :user
  self.inheritance_column = :brand

  scope :google_channels,   -> { where(brand: 'Google')   } 
  scope :facebook_channels, -> { where(brand: 'Facebook') } 
  scope :twitter_channels,  -> { where(brand: 'Twitter') }

  def self.brands
    %w(Google Facebook Twitter)
  end 
end

class GoogleChannel << Channel; end
class FacebookChannel << Channel; end
class TwitterChannel << Channel; end
class用户{where(品牌:'Facebook')}
范围:twitter_频道,->{where(品牌:'twitter')}
def自助品牌
%w(谷歌Facebook推特)
结束
结束

类GoogleChannel我假设您想要创建STI,其中
User
有许多频道,因此在Rails 5中您可以尝试以下方法:

class User < ApplicationRecord
  has_many :user_channels
  has_many :channels, through: :user_channels
  has_many :facebook_channels, class_name: 'FacebookChannel', through: :user_channels
  has_many :google_channels, class_name: 'GoogleChannel', through: :user_channels
end

class UserChannel < ApplicationRecord
  # user_id
  # channel_id
  belongs_to :user
  belongs_to :channel
  belongs_to :facebook_channel, class_name: 'FacebookChannel', foreign_key: :channel_id, optional: true
  belongs_to :google_channel, class_name: 'GoogleChannel', foreign_key: :channel_id, optional: true
end

class Channel < ApplicationRecord
  # You need to have "type" column to be created for storing different chanels
  has_many :user_channels
  has_many :users, through: :user_channels
end

class FacebookChannel < Channel
  has_many :user_channels
  has_many :users, through: :user_channels
end

class GoogleChannel < Channel
  has_many :user_channels
  has_many :users, through: :user_channels
end
然后你可以做你想要的
当前用户.channels.facebook\u频道

channel\u type
列可以是字符串,也可以是整数(如果使用枚举)

此外,如果您创建
visit
列(例如“布尔”),您可以执行
current\u user.channels.where(visit:true)
或创建
scope:visit\u true,->{where(visit:true)}
并执行类似
current\u user.channels.visit\u true


你说呢?

我假设你想创建一个STI,其中
用户
有很多频道,所以在Rails 5中你可以尝试以下方法:

class User < ApplicationRecord
  has_many :user_channels
  has_many :channels, through: :user_channels
  has_many :facebook_channels, class_name: 'FacebookChannel', through: :user_channels
  has_many :google_channels, class_name: 'GoogleChannel', through: :user_channels
end

class UserChannel < ApplicationRecord
  # user_id
  # channel_id
  belongs_to :user
  belongs_to :channel
  belongs_to :facebook_channel, class_name: 'FacebookChannel', foreign_key: :channel_id, optional: true
  belongs_to :google_channel, class_name: 'GoogleChannel', foreign_key: :channel_id, optional: true
end

class Channel < ApplicationRecord
  # You need to have "type" column to be created for storing different chanels
  has_many :user_channels
  has_many :users, through: :user_channels
end

class FacebookChannel < Channel
  has_many :user_channels
  has_many :users, through: :user_channels
end

class GoogleChannel < Channel
  has_many :user_channels
  has_many :users, through: :user_channels
end
然后你可以做你想要的
当前用户.channels.facebook\u频道

channel\u type
列可以是字符串,也可以是整数(如果使用枚举)

此外,如果您创建
visit
列(例如“布尔”),您可以执行
current\u user.channels.where(visit:true)
或创建
scope:visit\u true,->{where(visit:true)}
并执行类似
current\u user.channels.visit\u true



你说什么?

好像你在说STI或多态性?好像你在说STI或多态性?嗯。。。很有趣。我今天就试试是的,就是这样。每个品牌的模型(不同的表格)对我正在构建的应用程序最有意义。我希望我能得到像
user.channel.model.visit
这样的API,并在频道模型上运行
visit
方法(例如:
GoogleChannel::Google
),而不指定我想要的频道类型(
user.channels.Google\u channels
),但我不确定它是否有效(需要做一些修改)谢谢你,巴勃罗,但我认为我想要的是某种“魔力”。不知道是否有可能用我的方式来做。嗯。。。很有趣。我今天就试试是的,就是这样。每个品牌的模型(不同的表格)对我正在构建的应用程序最有意义。我希望我能得到像
user.channel.model.visit
这样的API,并在频道模型上运行
visit
方法(例如:
GoogleChannel::Google
),而不指定我想要的频道类型(
user.channels.Google\u channels
),但我不确定它是否有效(需要做一些修改)谢谢你,巴勃罗,但我认为我想要的是某种“魔力”。我不知道是否有可能用我的方式来做。嗯,更多的是多表关系。我希望有更多关于当前用户.channel.model的api,但不知道这是什么类型的模型。所以我不必猜测/找出它是谷歌频道还是facebook频道。顺便说一句,我使用的是mongoid,所以没有任何
为我提供了很多关系:|@adrianthedev,请看我上面的更新。是的@matiss。我就是这么做的。这不是rails/AR/relationships的方式,但对我来说可以。现在我有了这个桥接模型
通道
,每个通道都有不同的模型(因此我不会使
通道
模型过载)。我遗憾的是没有关系问题。除非我将
url
(或查询时可能需要的任何其他属性)属性存储到
频道
模型中,否则我无法在不知道它是哪种频道的情况下执行
当前用户.channels.where(url:'google.com')
。谢谢你的回答!嗯,更多的是多表关系。我希望有更多关于当前用户.channel.model的api,但不知道这是什么类型的模型。所以我不必猜测/找出它是谷歌频道还是facebook频道。顺便说一句,我使用的是mongoid,所以没有任何
为我提供了很多关系:|@adrianthedev,请看我上面的更新。是的@matiss。我就是这么做的。这不是rails/AR/relationships的方式,但对我来说可以。现在我有了这个桥接模型
通道
,每个通道都有不同的模型(因此我不会使
通道
模型过载)。我遗憾的是没有关系问题。除非我将
url
(或查询时可能需要的任何其他属性)属性存储到
频道
模型中(可能会过载),否则我无法在不知道它是哪种频道的情况下执行
当前用户.channels.where(url:'google.com')
class Channel < ApplicationRecord
  scope :facebook_channels, -> { where(channel_type: "facebook") }
end