又一个拔毛器。经过两天的斗争,我无法弄清楚这里出了什么问题。
基本上我有一个由模型触发的表单验证:
validates :user, :presence => true, :uniqueness => true
validates :email, :presence => true, :uniqueness => true, :on => :create
validates :passwordHash, :presence => true, :confirmation => true, :on => :create
非空用户在更新表单视图上工作:
= simple_form_for @user do |f|
= f.input :user
= f.input :locale
= f.input :localeLanguage, :label => 'Language', :as => :select, :collection => $language_array
= f.input :moderator
= f.input :email
= f.input :passwordHash, :label => 'Password'
但不在新用户上查看:
= simple_form_for @user do |f|
%table.table-condensed
%tr
%td
=f.input :user, :label => false, :placeholder => 'username'
%tr
%td
= f.input :passwordHash, :label => false, :placeholder => 'password'
%tr
%td
= f.input :email, :label => false, :placeholder => 'email'
%tr
%td
= f.submit "Create User", :class => 'btn btn-primary'
我可以看到这些视图之间的唯一区别是,第一个视图创建了会话,因为用户已经登录,而第二个视图没有。但据我所知,这不应该有所作为。当然,update
表单确实有一个实际的@user 对象,而在new
其中它是空的。但我看过 Ryan Bates 的新用户验证的 railscast,他也做了几乎相同的事情。
会发生什么是users#create
在提交带有空值的表单后调用的操作(这应该是不可能的)。当然我得到一个错误,因为它passwordHash
是空的。
我应该指出,我没有使用任何额外的 gem 来帮助密码确认(在 railscast 中,Bates 使用bcrypt
但我不能使用它,因为我们以不同的方式创建密码哈希,而且我认为这是密码确认魔法只要)。无论如何这不应该影响表单验证吗?
这里欢迎任何理论或想法,我快疯了。我将要编写一些糟糕的 javascript 来手动完成,这会很糟糕,可能需要我一个星期,我不做 javascript ;)
谢谢。
编辑
根据 Rachid 的要求,以下是new
和create
操作:
def new
@user = User.new
end
def create
#failsafe for failing form validation
unless params[:passwordHash].present?
redirect_to new_user_path, :notice => 'User or password cannot be blank'
else
password_and_salt = User.hash_password(params[:passwordHash])
hashed_password = password_and_salt[:password]
user_salt = password_and_salt[:salt]
@user = User.new(:user => params[:user], :passwordHash => hashed_password, :salt => user_salt)
if @user.save
session[:user_id] = @user.id
redirect_to session[:item_to_edit]
else
redirect_to new_user_path, :notice => "User already exists, please pick another one"
end
end
end
编辑 2
我已经create
根据第一个答案重写了该方法,但仍然出现错误:
def create
respond_to do |format|
if params[:passwordHash].present? && params[:user].present?
password_and_salt = User.hash_password(params[:passwordHash])
hashed_password = password_and_salt[:password]
user_salt = password_and_salt[:salt]
@user = User.new(:user => params[:user], :passwordHash => hashed_password, :salt => user_salt, :online_user => 1 )
if @user.save
session[:user_id] = @user.id
redirect_to session[:item_to_edit]
else
format.html { render :action => "new" }
format.json { render :json => @user.errors, :status => :unprocessable_entity }
end
else
format.html { render :action => "new" }
format.json { render :json => @user.errors, :status => :unprocessable_entity }
end
end
end
错误是undefined method 'model_name' for NilClass:Class
针对这一行的:
= simple_form_for @user do |f|
显然,@user = User.new
它并没有回到表格中。在这一点上,我对如何编写create
使其正常工作并显示错误消息的方法有点困惑。但我觉得我更接近了:)
@misha,这是update
控制器动作,它只是非常标准的脚手架:
def update
@user = User.find(params[:id])
respond_to do |format|
if @user.update_attributes(params[:user])
if session[:return_to]
format.html { redirect_to session[:return_to], :notice => 'User was successfully updated.' }
else
format.html { redirect_to users_path, :notice => 'User was successfully updated.' }
end
format.json { head :ok }
else
format.html { render :action => "edit" }
format.json { render :json => @user.errors, :status => :unprocessable_entity }
end
end
end