问题描述
幕后故事
我目前正在将我的Ruby on rails应用程序更改为多数据库配置。切换的主要原因是将我的成员(用户)和个人资料表放在一个单独的数据库中,该数据库可以从另一个RoR应用程序访问;因此,除了使用OAuth和DoorKeeper之外,我还可以拥有单点登录功能。这是一个耗时很长的项目,有很多疯狂的障碍。最终,今晚一切似乎都很正常,直到我运行了规范测试,而我今天做的一项工作就是扔旗子。
以下是该问题的相应代码,为简洁起见进行了简化。
任何帮助都将不胜感激。谢谢。
模型
app/Models/Members_record.rb
class MembersRecord < ApplicationRecord
self.abstract_class = true
connects_to database: { writing: :members, reading: :members }
end
应用程序/型号/成员.rb
class Member < MembersRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable,
:validatable, :confirmable
has_one :member_map, dependent: :destroy
has_one :profile, dependent: :destroy
has_one :site_profile, dependent: :destroy
has_many :approved_group_members, -> { approved }, class_name: "GroupMember"
has_many :groups, through: :approved_group_members, class_name: "Group", source: :group
app/Models/group.rb
class Group < ApplicationRecord
belongs_to :owner, class_name: 'Member'
belongs_to :organization, optional: true
has_many :group_members, dependent: :destroy
# Many of the lines below no longer work with Multiple DBs, as we can not INNER JOIN across DBs.
# They have been commented out and methods built in their place.
has_many :approved_group_members, -> { approved }, class_name: "GroupMember"
# has_many :members, through: :approved_group_members, class_name: "Member", source: :member
def members
Member.where(id: self.approved_group_members.pluck(:member_id))
end
has_many :invited_group_members, -> { invited }, class_name: "GroupMember"
# has_many :invited_members, through: :invited_group_members, class_name: "Member", source: :member
def invited_members
Member.where(id: self.invited_group_members.pluck(:member_id))
end
APP/MODIES/GROUP_MEMBER.rb
class GroupMember < ApplicationRecord
belongs_to :group
belongs_to :member
enum status: { approved: 0, invited: 1, pending_approval: 2, banned: 3}
end
解决办法
现在,查看上面的代码,您应该会看到组模型中一些有问题的变通方法。原始代码已被注释掉,其下有解决方法。以下就是该代码:# Many of the lines below no longer work with Multiple DBs, as we can not INNER JOIN across DBs.
# They have been commented out and methods built in their place.
has_many :approved_group_members, -> { approved }, class_name: "GroupMember"
# has_many :members, through: :approved_group_members, class_name: "Member", source: :member
def members
Member.where(id: self.approved_group_members.pluck(:member_id))
end
has_many :invited_group_members, -> { invited }, class_name: "GroupMember"
# has_many :invited_members, through: :invited_group_members, class_name: "Member", source: :member
def invited_members
Member.where(id: self.invited_group_members.pluck(:member_id))
end
这些解决办法的原因是,一旦has_many
类引用了不同数据库上的数据,has_many
关系就不能与类Member
一起使用。正在构建的SQL查询失败。因此,我改为创建了一个方法,并在Member
模型上调用了where
。这给了我正在寻找的成员名单。我不得不在9次不同的情况下这样做。现在我遇到的问题
在我的100多个不同位置的代码中,我将一个成员或其他对象添加到一个给定的列表中,比如使用这种代码的"受邀成员"。(此代码特别在我的一个规范中,现在失败)it 'will set the GroupMember to approved if the group is invite only and member was invited' do
group_invitation
group.invited_members << member
expect { service.call! }.to change{GroupMember.count}.by(0)
expect(service.success?).to be_truthy
expect(service.success_message).to eq("You have successfully joined this group.")
expect(service.error).to eq("")
end
第二行显示group.invited_members << member
,然后我收到一个错误,指出:
NoMethodError (undefined method `<<' for #<ActiveRecord::Relation []>):
我的问题
我完全理解这个错误是什么意思,但我不知道如何纠正它。有没有其他解决方法可以让<<
保留?我非常希望只更改9次不同的变通方法,而不是重写100多个不同的实例,其中<<
用于将成员或任何对象添加到被引用的列表中。
如果您需要进一步的详细信息,请告诉我。再次感谢您!
推荐答案
这在rails 7及更高版本上受本机支持。(请参阅https://edgeguides.rubyonrails.org/active_record_multiple_databases.html#handling-associations-with-joins-across-databases、https://github.blog/2021-07-12-adding-support-cross-cluster-associations-rails-7/和https://github.com/rails/rails/pull/41937)
如果您真的需要这个,我可能会建议您迁移到Rails Master,并使用原生方法:
has_many :members,
through: :approved_group_members,
class_name: "Member",
source: :member,
disable_joins: true
这篇关于Rails NoMethodError(#<;ActiveRecord::Relation[]>;的未定义方法`<;<;';):的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!