use*_*003 1 activerecord ruby-on-rails models
我有一个网站,允许用户通过多种服务(LinkedIn、电子邮件、Twitter 等)登录。
我设置了以下结构来建模 aUser及其多重身份。基本上,一个用户可以有多个身份,但只能是给定类型的一个(例如不能有 2 个 Twitter 身份)。
我决定将其设置为多态关系,如下所示。基本上有一个中间表identities将一个条目映射User到多个*_identity表。
关联如下(仅显示LinkedInIdentity,但可以推断)
# /app/models/user.rb
class User < ActiveRecord::Base
has_many :identities
has_one :linkedin_identity, through: :identity, source: :identity, source_type: "LinkedinIdentity"
...
end
# /app/models/identity
class Identity < ActiveRecord::Base
belongs_to :user
belongs_to :identity, polymorphic: true
...
end
# /app/models/linkedin_identity.rb
class LinkedinIdentity < ActiveRecord::Base
has_one :identity, as: :identity
has_one :user, through: :identity
...
end
Run Code Online (Sandbox Code Playgroud)
我遇到的问题与User模型有关。由于它可以有多个身份,因此我使用has_many :identities. 但是,对于给定的身份类型(例如 LinkedIn),我使用了has_one :linkedin_identity ....
问题是该has_one语句是through: :identity,并且没有称为 的单一关联:identity。只有复数:identities
> User.first.linkedin_identity
ActiveRecord::HasManyThroughAssociationNotFoundError: Could not find the association :identity in model User
Run Code Online (Sandbox Code Playgroud)
有什么办法解决这个问题吗?
我会这样做 - 我已将 Identity 和其他人之间的关系名称更改为external_identity,因为说identity.identity只是令人困惑,特别是当您没有拿回 Identity 记录时。我还会对身份进行唯一性验证,这将防止为任何用户创建相同类型的第二个身份。
class User < ActiveRecord::Base
has_many :identities
has_one :linkedin_identity, through: :identity, source: :identity, source_type: "LinkedinIdentity"
end
# /app/models/identity
class Identity < ActiveRecord::Base
#fields: user_id, external_identity_id
belongs_to :user
belongs_to :external_identity, polymorphic: true
validates_uniqueness_of :external_identity_type, :scope => :user_id
...
end
# /app/models/linkedin_identity.rb
class LinkedinIdentity < ActiveRecord::Base
# Force the table name to be singular
self.table_name = "linkedin_identity"
has_one :identity
has_one :user, through: :identity
...
end
Run Code Online (Sandbox Code Playgroud)
编辑- 您始终可以只拥有一个 getter 和 setter 方法,而不是与 linkedin_identity 建立关联。
#User
def linkedin_identity
(identity = self.identities.where(external_identity_type: "LinkedinIdentity").includes(:external_identity)) && identity.external_identity
end
def linkedin_identity_id
(li = self.linkedin_identity) && li.id
end
def linkedin_identity=(linkedin_identity)
self.identities.build(external_identity: linkedin_identity)
end
def linkedin_identity_id=(li_id)
self.identities.build(external_identity_id: li_id)
end
Run Code Online (Sandbox Code Playgroud)
编辑2 - 重构上述内容以使其更加表单友好:您可以使用 linkedin_identity_id= 方法作为“虚拟属性”,例如,如果您有一个类似于 的表单字段"user[linkedin_identity_id]",带有 LinkedinIdentity 的 id,那么您可以@user.update_attributes(params[:user])在控制器中执行以下操作通常的方式。
| 归档时间: |
|
| 查看次数: |
858 次 |
| 最近记录: |