password_field_tag inside form_for block ( ruby on rails )



我的问题是通过在更新属性之前确认用户的密码来设置用于更新用户"配置文件"的视图和控制器。正如你们以前可能见过的一百万次一样,用户会转到/users/:id/edit,在文本字段中输入一封新电子邮件,在密码字段中输入当前密码,然后单击提交按钮最终更新用户的电子邮件。如果输入的密码不正确,则会再次呈现编辑模板,否则会使用新电子邮件更新用户记录并重定向到:show(或适用于应用程序的任何内容)。在更新操作中,我认为坚持使用update_attributes方法是有意义的。然而,当前的密码值最终会让我们失望

不过,我真正想问的是,我的方法是否有什么问题。我最终在form_for块中为:current_password字段添加了一个对password_field_tag的调用,以便用params[:user]调用update_attributes,而不会让attr_accessible生气。但后来我在已经这样做的网站上查找了一些表单(例如hulu和destroyalsoftware),它们似乎接受了用户哈希中的:current_password值(假设它们是用rails构建的)。在twitter的设置页面上,他们似乎在param中的一个单独的散列中检索到了这一点(因此params[:current_password]而不是params[:user][:current_pass word])。

在form_for中使用password_field_tag错误吗?这些其他网站是如何做到这一点的?我唯一能想到的是,他们要么从params散列中删除:current_password,要么单独分配每个属性。

以下是我基本上得到的结果:

# /app/models/user.rb
class User < Activerecord::Base
  attr_accessible :email, # ...
  # ...
end
# /app/views/users/edit.html.erb
<%= form_for @user do |f| %>
  # this is stored in params[:user][:email]
  <%= f.label :email, 'Your new email' %>
  <%= f.text_field :email, type: :email %>
  # this is stored in params[:current_password]
  <%= label_tag :current_password, 'Re-enter your password to update your email' %>
  <%= password_field_tag :current_password %>
  <%= f.submit 'Save changes' %>
<% end %>
# /app/controllers/users_controller.rb
# ...
def update
  @user = User.find(params[:id])
  if @user.authenticate(params[:current_password])
    if @user.update_attributes(params[:user])
      sign_in @user
      flash[:success] = 'Sweet!'
      redirect_to @user
    else
      render :edit
    end
  else
    flash.now[:error] = 'Incorrect password'
    render :edit
  end

否则,这是我想到的另一种方式

# /app/views/users/edit.html.erb
<%= form_for @user do |f| %>
  # this is stored in params[:user][:email]
  <%= f.label :email, 'Your new email' %>
  <%= f.text_field :email, type: :email %>
  # this is stored in params[:user][:current_password]
  <%= f.label :current_password, 'Re-enter your password to update your email' %>
  <%= f.password_field :current_password %>
  <%= f.submit 'Save changes' %>
<% end %>
# /app/controllers/users_controller.rb
# ...
def update
  @user = User.find(params[:id])
  if @user.authenticate(params[:user][:current_password])
    params[:user].delete(:current_password) # <-- this makes me feel a bit uneasy
    if @user.update_attributes(params[:user])
      sign_in @user
      flash[:success] = 'Sweet!'
      redirect_to @user
    else
      render :edit
    end
  else
    flash.now[:error] = 'Incorrect password'
    render :edit
  end

或者,我应该在控制器中执行此操作吗?:

def update
  @user = User.find(params[:id])
  if @user.authenticate(params[:user][:current_password])
    @user.email = params[:user][:email]
    if @user.save
      # ...

欢迎提出任何建议。

附言-此外,你会如何重构更新操作?我尝试了一个before_filter来使用:current_password进行身份验证,并在#update中只保留#update_attributes部分,但它有点乱。不过,这篇文章已经足够长了,所以如果我下周还不能弄清楚的话,也许我会把它作为一个单独的问题发布。

我最近做了类似的事情,只是使用了一个虚拟属性来处理current_password。然后,您可以将:current_password属性添加到attr_accessible中,并使其保持愉快。

相关内容

  • 没有找到相关文章

最新更新