奇怪的是,大部分内容都是按照它编写的方式进行的,但是我不确定如何评估current_user
是否有徽章,(所有的关系都是正确的,我只是遇到了麻烦)我的类中的方法(应该部分地移动到lib或其他东西),无论如何,问题特别是1)检查当前用户是否有记录,2)如果没有创建相应的新记录。
如果有更简单或更好的方法,请分享。以下是我所拥有的:
# Recipe Controller
class RecipesController < ApplicationController
def create
# do something
if @recipe.save
current_user.check_if_badges_earned(current_user)
end
end
因此,它肯定看起来很混乱,我希望它只是check_if_badges_earned
而不必将current_user
传递给方法,但可能需要因为它可能不会始终是启动此方法的当前用户。
# User model
class User < ActiveRecord::Base
def check_if_badges_earned(user)
if user.recipes.count > 10
award_badge(1, user)
end
if user.recipes.count > 20
award_badge(2, user)
end
end
def award_badge(badge_id, user)
#see if user already has this badge, if not, give it to them!
unless user.badgings.any? { |b| b[:badge_id] == badge_id}
@badging = Badging.new(:badge_id => badge_id, :user_id => user)
@badging.save
end
end
end
因此,虽然第一种方法(check_if_badges_earned
)看起来很好,并且只在满足条件时才提供运行award_badge()
,但问题发生在award_badge()
方法本身的表达式{{ 1}}总是评估为真,所以即使用户已经拥有相同的徽章(通过badge_id),也会给予用户徽章,其次问题是它始终将unless user.badgings.any? { |b| b[:badge_id] == badge_id}
保存为1。
关于如何进行调试的任何想法都会很棒!
答案 0 :(得分:2)
无论您是否需要上述current_user
行为,award_badge
应该只是作用于self
的常规实例方法,而不是对传递的user
参数执行操作(相同)转到check_if_badges_earned
)。在award_badge
方法中,尝试find_or_create_by_...
而不是您目前拥有的逻辑。例如,试试这个:
class User < ActiveRecord::Base
# ...
def award_badge(badge_id)
badgings.find_or_create_by_badge_id(badge_id)
end
end
要访问模型类中的current_user
,我有时希望使用线程局部变量。它确实模糊了MVC的分离,但有时这种耦合在应用程序中是必需的。
在ApplicationController中,将current_user
存储在线程局部变量中:
class ApplicationController < ActionController::Base
before_filter :set_thread_locals
private
# Store thread-local variables so models can access them (Hackish, but useful)
def set_thread_locals
Thread.current[:current_user] = current_user
end
end
向ActiveRecord模型添加一个新的类方法以返回current_user
(您还可以扩展ActiveRecord :: Base以使其可用于所有模型):
class User < ActiveRecord::Base
def self.current_user
Thread.current[:current_user]
end
end
然后,您将能够使用User
访问self.class.current_user
模型的实例方法中的当前用户。
答案 1 :(得分:1)
首先需要做的是使这些方法成为类方法(自我调用),这样可以避免不必要地传递用户引用。
然后,在您的award_badge
方法中,您应该将徽章添加到用户的徽章列表中,例如:user.badgings << Badging.new(:badge_id => badge_id)