我在实时应用程序中有两个现有数据模型,目前彼此之间没有任何关系。它们主要用于存储和快速查找,但现在我们看到需要加入它们:
# == Schema Information
#
# Table name: subscriptions
#
# id :integer not null, primary key
# app_id :string(255)
# user_id :string(255)
# effective_date :datetime
# expiration_date :datetime
# last_validated :datetime
# created_at :datetime not null
# updated_at :datetime not null
# active :boolean
# subscription_type :string(255)
#
class Subscription < ActiveRecord::Base
end
和
# == Schema Information
#
# Table name: apns_tokens
#
# id :integer not null, primary key
# app_id :string(255)
# user_id :string(255)
# apns_token :text
# created_at :datetime not null
# updated_at :datetime not null
#
class ApnsTokens < ActiveRecord::Base
end
我需要从apns_tokens模型中找到属于同一user_id的所有apns_token。我希望能够查询类似的内容:
subscription = Subscription.where("app_id = ? AND user_id = ?", params[:app_id], params[:user_id]).last
token = subscription.apns_token.apns_token
订阅和apns_tokens模型中的user_id都是唯一的。
1)是否可以创建一个has_one belongs_to关系,以及如何在apns_tokens模型中填充新的外键'subscription_id'?
2)这里有什么快速解决方法,如何在rails中编写一个sql语句来加入user_id?
编辑:快速修复有效,但在一个查询中必须有更好的方法吗?
subscribed_users = Subscription.where("active = ? and app_id = ?", true, app.app_id).collect { |u| u.user_id }
apns_tokens = ApnsTokens.where(user_id: subscribed_users).collect { |t| t.apns_token }
谢谢!
答案 0 :(得分:0)
如果我理解了这个问题,你有两个共享一个值的模型(在这种情况下是user_id),你想在它们之间创建一个关系。
也许您可以使用has_one
关系中的primary_key和foreign_key参数,这样您就可以使用除id
和relationship_id
之外的其他列:http://apidock.com/rails/ActiveRecord/Associations/ClassMethods/has_one
遵循API文档,您可以编写
class Subscription
has_one :apns_token, primary_key: :user_id, foreign_key: :user_id
end
class ApnsToken
has_one :subscription, primary_key: :user_id, foreign_key: :user_id
end
我想到的另一个解决方案是使用中间关系。
由于您有user_id
列,我猜您在Subscription和ApnsToken类中有belongs_to
个关系。
如果您在User类中有has one
个关系,则可以使用through
关系中的has_one
param来表示您通过用户关系订阅了apns_token。
class User
has_one :apns_token
has_one :subscription
end
class Subscription
belongs_to :user
has_one :apns_token, through: :user
end
class ApnsToken
belongs_to :user
has_one :subscription, through: :user
end
我还没有为此示例测试此代码,但这两种解决方案都可以正常工作:)