我有两个模型:Users和PaymentMethods,这个模型之间的关联是:
class User < ApplicationRecord
has_many :payment_methods, dependent: :destroy
end
class PaymentMethod < ApplicationRecord
belongs_to :user, optional: true
end
我想在每个用户中循环并查看PaymentMethod的一个名为'period_end_date'的属性。所以我这样做:
@users = User.all
@users.each do |u|
u.payment_methods.last.period_end_date
end
我收到此错误=&gt; NoMethodError:User :: ActiveRecord_Relation的未定义方法`payment_methods'
显示错误是因为我有2个测试用户,在第一个用户中,属性'period_end_date'中仍然没有数据且关联存在,但是为空,在第二个用户中属性中有数据,如果我比如,u.payment_methods.last.period_end_date我得=>&gt; 2018年6月13日星期三(仅限第二位用户)
我想在我的循环中仅过滤在PaymentMethod属性中具有数据的用户来摆脱=&gt; NoMethodError:User :: ActiveRecord_Relation的未定义方法`payment_methods'
我是怎么做到的?
感谢
答案 0 :(得分:1)
我想在我的循环中仅过滤在PaymentMethod属性中具有数据的用户来摆脱=&gt; NoMethodError:未定义的方法`payment_methods&#39; for User :: ActiveRecord_Relation
实际问题似乎是您没有付款方式的用户(请参阅我对您的问题的评论)。
您有一些选择,具体取决于 您将如何使用结果。
1)当您从数据库中查询用户时,您可以在没有付款方式的情况下过滤掉用户:
@users = User.joins :payment_methods
2)如果@users
必须包含没有付款方式的用户,则可以在循环播放时跳过它们:
@users.map do |user|
next unless user.payment_methods.any?
user.payment_methods.last.period_end_date
end
3)在致电payment_methods
之前,您可以通过检查.last
来保护。
User.all.map do |user|
user.payment_methods.last.period_end_date if user.payment_methods.any?
end
4)您可以向用户添加period_end_date
方法
class User < ApplicationRecord
def period_end_date
payment_methods.limit(1).pluck :period_end_date
end
end
5)通过使用辅助方法
扩展#4,将#4推入关联class User < ApplicationRecord
has_many :payment_methods, class_name: 'PaymentMethod' do
def last_period_end_date
last.period_end_date if any?
end
end
end
你可以像这样打电话
User.all.map do |user|
user.payment_methods.last_period_end_date
end
如果您真的仅关注PaymentMethod
而没有period_end_date
,请尝试以下方法:
6)当您从数据库中查询用户时,您仍然可以过滤用户
@users = User.joins(:payment_methods).where.not(payment_methods: { period_end_date: nil })
7)通过将where.not
条件推送到PaymentMethod
类的范围,可以简化这一点:
class PaymentMethod < ApplicationRecord
scope :period_ends, -> { where.not period_end_date: nil }
end
并合并
@users = User.joins(:payment_methods).merge PaymentMethod.period_ends
payment_methods.last
没有指定订单,您应该设置一个(作为此链的一部分,当您指定关联或使用默认范围时),否则订单最多你的数据库可能不确定。
链.includes(:payment_methods)
急切加载付款方式并避免n + 1次查询
听起来像是period_end_date
可能是无效数据。考虑添加验证/数据库约束以防止这种情况发生