如何在模型中使用current_user?

时间:2012-12-18 12:01:54

标签: ruby-on-rails ruby-on-rails-3 devise

我想在我的模型中使用Devise的current_user帮助器,因此我可以使用ShopDress模型中保存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

3 个答案:

答案 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