我想在我的模型中使用Devise的current_user
帮助器,因此我可以使用Shop
在Dress
模型中保存before_save
的货币。
这不起作用:
# Dress model
before_save :set_currency
def set_currency
self.currency = current_user.shop.currency
end
它在控制器中有效:
def create
@dress = current_user.shop.dresses.create(params[:dress])
@dress.update_column(:currency, current_user.shop.currency)
end
但似乎效率低下,因为它会在UPDATE
后执行COMMIT
。 StackOverflow上的其他用户表示current_user
不应该在模型中使用。有没有其他方法可以访问模型中的current_user
?
答案 0 :(得分:1)
一种方法是将用户作为参数传递给模型方法,而不是使用before_save回调
# Dress model
def set_currency(user)
self.currency = user.shop.currency
end
另一种方法是专门设置货币。由于货币是Dress'字段,您可以使用当前用户货币在表单上放置一个隐藏字段,并将其作为参数传递给您的创建操作,并将为您透明保存。
如何实施:
# At your Dress form, in your View
<%= f.hidden_field :currency, :value => @user.shop.currency %>
# At your controller
def create
@user = current_user
end
像这样,你不必做任何事情来保存货币。它将传递参数以创建Dress,您只需确保currency
是ActiveRecord字段。
通常,在特定时间向您的模型附加关于应用程序的状态的这种知识是不好的。如果你发现自己处于一种绝对确定需要这种行为的情况,那就停下来问问自己这是否真的有意义。
在这个例子中,我真的觉得(不知道你的应用程序,有)货币应该是表单中的隐藏字段,因为它是你的模型必须存在的东西,它实际上是一个字段,并且因此,使用模型的参数传递是有意义的。
祝你好运
答案 1 :(得分:1)
在控制器中使用.build而不是.create将值设置为Dress模型的货币属性。
def create
@dress = current_user.shop.dresses.build(params[:dress])
@dress.currency = current_user.shop.currency
if @dress.save
.....
else
.....
end
end
答案 2 :(得分:1)
我建议只处理在控制器中设置它们,但是......
如果您不介意稍微违反MVC,可以采用以下方法:
# application_controller.rb
before_filter :set_current
def set_current
User.current = current_user
end
# app/models/user.rb
cattr_accessor :current
# app/models/dress.rb
before_save :set_currency
def set_currency
self.currency = User.current.shop.currency
end