我正在开发 Rails v2.3.2 应用。
我有一个带有验证的模型:
class Person < ActiveRecord::Base
validates_presence_of :name, :email
# Please notice this method
def pwd=(pwd)
encrypted_pwd = pwd + randn(127)
self.password = encrypted_pwd
end
end
注意:以上模型具有以下属性:name
,email
和password
(不是pwd
),其中password
不直接获取并存储到数据库,而是将用户输入pwd
值加密,然后将其存储为password
在数据库中。在数据库表中,列(属性)为password
。我使用def pwd=(pwd) ...
来实现这一目标。
我的控制器:
class PersonsController < ApplicationController
def create
@person = Person.new(params[:person])
if @person.save
redirect_to persons_path
else
render :action=> :new
end
end
def new
#empty
end
def index
@persons = Person.all
end
end
视图(views/persons/new.html.erb
):
<% form_for :person, @person, :url => persons_url, :html=>{:method=>:post} do |f| %>
<table>
<tr>
<td>Name:</td>
<td><%= f.text_field :name %></td>
</tr>
<tr>
<td>Email:</td>
<td><%= f.text_field :email %></td>
</tr>
<tr>
<td>password:</td>
<td><%= f.text_field :pwd %></td> <!--NOTE: here I use :pwd not :password-->
</tr>
</table>
<%= f.submit "Save"%>
<% end %>
有趣&amp;奇怪的是,如果在视图表单中,我将值输入到每个字段然后提交表单,我的新实例已成功创建。
但是,如果我离开name
并email
为空,仅输入password
字段(表单中的pwd
值),然后应用程序被破坏,并显示错误消息:
ActionView::TemplateError (undefined method `pwd' for #<Person:0xa0ec0e0>) on line #25 of app/views/persons/new.html.erb:
22: </tr>
23: <tr>
24: <td>password:</td>
25: <td><%= f.text_field :pwd %></td>
26: </tr>
27: </table>
我也试过 Rails控制台,我可以创建和保存对象:
Person.new(:name=>'John', :email=>'john@gmail.com', :pwd=>'test')
所以:
1。为什么我可以成功创建模型实例,如果所有字段都填写了表单中的值,但我得到了错误,当我离开name
和email
时空但输入密码(密码)字段的值?
2。为什么我没有收到抱怨name
和email
不应为空的错误消息?
答案 0 :(得分:2)
原因是您的模型缺少pwd
的属性读取器(getter)。
以下是发生的事情:
由于name
和email
是必需的(由validates_presence_of :name, :email
提供),当您不输入并提交表单时,会发生错误并再次呈现表单和视图想要填充pwd
字段,但由于您尚未定义,因此会收到以下错误消息:undefined method 'pwd' for #<Person:0xa0ec0e0>
。
因此,您可以将这样的getter添加到Person
类:
def pwd
"" # or whatever you like
end
你的表格应该再次运作。如果您希望模型在发生错误时记住未加密的密码,您可以改为:
def pwd=(pwd)
@pwd = pwd
encrypted_pwd = pwd + randn(127)
self.password = encrypted_pwd
end
def pwd
@pwd || ""
end
答案 1 :(得分:0)
要回答第二个问题,您没有收到验证错误,因为您没有在视图中检查它们。验证失败时,错误消息将添加到与您尝试保存的对象关联的错误哈希中。要选择性地显示它们,请在视图中添加与此类似的内容:
<% form_for :person, @person, :url => persons_url, :html=>{:method=>:post} do |f| %>
<% if @person.errors.any? %>
<ul id="errors">
<% @person.errors.full_messages.each do |error| %>
<li>
<%= error %>
</li>
<% end %>
</ul>
<% end %>
Rest of your form goes here...