I am developing a Rails v2.3.2 app.
I have a Model with validations:
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
NOTE: The above model has attributes: name, email and password (not pwd), where password is not directly get and store to database, instead, the user input pwd value will be encrypted and then store as password in database. In database table, the column(attribute) is password. I use def pwd=(pwd) ... to achieve this.
My Controller:
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
The view (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 %>
The interesting & strange thing is , if in the view form, I input values to every field then submit the form, my new instance created successfully.
BUT, if I leave name and email empty, only input password field (which will be pwd value) in the form, then the application got broken, with the error message:
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>
I also tried from Rails console, I can create and save object like:
Person.new(:name=>'John', :email=>'john@gmail.com', :pwd=>'test')
So:
1. Why I can successfully create a model instance if all fields have been filled with values in the form, BUT I got that error when I leave name and email empty but input value to password(pwd) field?
2. Why I do not get error message which complains the name and email should not be empty?
The reason is your model is missing an attribute reader (getter) for
pwd.Here’s what’s happening:
As
nameandemailare required (courtesy ofvalidates_presence_of :name, :email), when you do not enter them and submit the form, an error occurs and the form is rendered again and the view wants to fill thepwdfield, but as you haven’t defined it, you get that error message:undefined method 'pwd' for #<Person:0xa0ec0e0>.So you can add a getter like this to your
Personclass:And your form should work again. If you want your model to remember the unencrypted password when an error occurs, you can have something like this instead: