Ruby on rails 模型方法取决于rails中的当前用户

Ruby on rails 模型方法取决于rails中的当前用户,ruby-on-rails,ruby,Ruby On Rails,Ruby,在我的rails应用程序中,我有一些用户可以付费的活动。我需要能够根据当前用户更改活动价格 *我知道已经有很多关于访问模型中的当前用户的主题,但这不是我想要的* 我有以下两个模型(非常简化)。签出是管理与事件相关的所有支付事务(我需要它在一个单独的模型中,就像在实际应用程序中一样,它与事件有多态性关联) class事件

在我的rails应用程序中,我有一些用户可以付费的活动。我需要能够根据当前用户更改活动价格

*我知道已经有很多关于访问模型中的当前用户的主题,但这不是我想要的*

我有以下两个模型(非常简化)。签出是管理与事件相关的所有支付事务(我需要它在一个单独的模型中,就像在实际应用程序中一样,它与事件有多态性关联)

class事件
显然,我可以定义
checkout\u price(user)
,但我必须在任何地方传递它(例如
事件。checkout\u price(当前用户)
checkout.total(当前用户)
checkout.free?(当前用户)


我知道从模型中访问
当前用户是一种不好的做法(我绝对不想这样做),但在我的情况下,有没有其他解决方案,而不是一直将
当前用户作为参数传递?

如果你不想传递当前用户,那么你必须传递签出和事件。方法只能在单个对象上调用。无论哪种方式,都必须传递另一个对象。

如果不想传递当前用户,则必须传递签出和事件。方法只能在单个对象上调用。无论哪种方式,您都必须传递另一个对象。

将用户设置为关联或实例变量比将其传递到不同对象的多个位置更好。仔细想想,每个签出都属于用户,不是吗

就像这样:

class Checkout < ActiveRecord::Base
  attr_accessible :event
  belongs_to :event
  belongs_to :user

  def total
    event.checkout_price(user)
  end

  def free?
    total == 0
  end
end
类签出

您只需确保在创建签出记录时设置了用户。

将用户设置为关联或实例变量比将其跨不同对象传递到多个位置更好。仔细想想,每个签出都属于用户,不是吗

就像这样:

class Checkout < ActiveRecord::Base
  attr_accessible :event
  belongs_to :event
  belongs_to :user

  def total
    event.checkout_price(user)
  end

  def free?
    total == 0
  end
end
类签出

您只需确保在创建签出记录时设置了用户。

这是一个好问题,我感谢您对不访问模型中当前用户的意见

实际上,事件模型应该考虑得更少。模型的主要工作是存储数据和处理与自身相关的数据。定价是您的业务逻辑,而不是事件模型的问题。一件事是有代价的。这就是全部。没有了

在定价方面你有很多事情要考虑。不仅是在用户是否是高级用户的情况下。如果你的应用程序中有一个6个月大的用户,可以享受一些折扣吗?在app的生日那天做些促销怎么样?就因为你喝醉了就大甩卖怎么样?如果您使用事件模型来处理它们,所有这些都将非常复杂。即使您现在不需要所有这些功能,最好留出一些扩展空间

那么在哪里应该考虑定价逻辑呢?显然,控制器也不是一个好地方。让我们试试服务对象

class PricingService

  def initialize(event, user)
    @user = user
    @event = event
    @price = event.price
  end

  def get_price
    # The place for your easily adding rules. Or use some meta programming.
    # say go through all instance methods starting with "pricing_"
    pricing_premium_user
    pricing_app_birthday
    pricing_old_event
    @price
  end

  def pricing_premium_user
    @price -= 10 if user.premium?
  end

  def pricing_app_birthday
    @price = @price*0.9 if Time.current.today == APP_BIRTHDAY
  end

  def pricing_old_event
    @price = @price*0.9 if event.created_at < (Time.current - 1.week)
  end

end

很好?

这是一个很好的问题,我感谢您对不访问模型中当前用户的意见

实际上,事件模型应该考虑得更少。模型的主要工作是存储数据和处理与自身相关的数据。定价是您的业务逻辑,而不是事件模型的问题。一件事是有代价的。这就是全部。没有了

在定价方面你有很多事情要考虑。不仅是在用户是否是高级用户的情况下。如果你的应用程序中有一个6个月大的用户,可以享受一些折扣吗?在app的生日那天做些促销怎么样?就因为你喝醉了就大甩卖怎么样?如果您使用事件模型来处理它们,所有这些都将非常复杂。即使您现在不需要所有这些功能,最好留出一些扩展空间

那么在哪里应该考虑定价逻辑呢?显然,控制器也不是一个好地方。让我们试试服务对象

class PricingService

  def initialize(event, user)
    @user = user
    @event = event
    @price = event.price
  end

  def get_price
    # The place for your easily adding rules. Or use some meta programming.
    # say go through all instance methods starting with "pricing_"
    pricing_premium_user
    pricing_app_birthday
    pricing_old_event
    @price
  end

  def pricing_premium_user
    @price -= 10 if user.premium?
  end

  def pricing_app_birthday
    @price = @price*0.9 if Time.current.today == APP_BIRTHDAY
  end

  def pricing_old_event
    @price = @price*0.9 if event.created_at < (Time.current - 1.week)
  end

end

很好?

实际上没有,每个事件只有一个
签出
,签出模型通过
收费
模型链接到
用户
模型。但是我不能依赖这个,因为它是在用户付费的情况下创建的,并且我使用之前的方法(例如,只是不显示带有相应价格的事件)啊,这对我来说有点违反直觉-如果你能解释一下你的域模型(类),可能会有所帮助,否则,它只是太抽象了,无法提出一些东西。。。可能值得考虑将签出和收费模型重构为签出,这会在用户收费时更改状态(收费);您可以在用户会话中保存签出id。但再一次,很难说,因为我根本不知道初始模型或完整域模型的原因…谢谢你们的帮助。我真的很喜欢Billy Chan建议的服务方式,我认为在这种情况下这是很有意义的。实际上不是,每个事件只有一个
结帐
,结帐模式通过
收费
模式链接到
用户
模式。但是我不能依赖这个,因为它是在用户付费时创建的,我使用之前的方法(例如,只是不显示带有相应价格的事件)啊,这对我来说有点违反直觉-也许会有帮助