<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Scott Blaine &#187; models</title>
	<atom:link href="http://scottblaine.com/tag/models/feed" rel="self" type="application/rss+xml" />
	<link>http://scottblaine.com</link>
	<description>Omaha web developer</description>
	<lastBuildDate>Wed, 12 Oct 2011 01:00:22 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>How to use additional one-to-one models with restful_authentication</title>
		<link>http://scottblaine.com/how-to-use-additional-one-to-one-models-with-restful_authentication</link>
		<comments>http://scottblaine.com/how-to-use-additional-one-to-one-models-with-restful_authentication#comments</comments>
		<pubDate>Sun, 09 Aug 2009 01:00:03 +0000</pubDate>
		<dc:creator>Scott</dc:creator>
				<category><![CDATA[development]]></category>
		<category><![CDATA[authentication]]></category>
		<category><![CDATA[models]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[restful_authentication]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://scottblaine.com/?p=345</guid>
		<description><![CDATA[Restful_authentication collects some basic information to get an account set up, like a username, email address, and password, which all gets stored in a User model. What if you have some additional information that you&#8217;d like to collect upon registration, and you don&#8217;t want to store it in the User model (addresses, for example)? Rails [...]]]></description>
			<content:encoded><![CDATA[<p>Restful_authentication collects some basic information to get an account set up, like a username, email address, and password, which all gets stored in a User model. What if you have some additional information that you&#8217;d like to collect upon registration, and you don&#8217;t want to store it in the User model (addresses, for example)? Rails 2.3 makes this easy.</p>
<p>Let&#8217;s get an example registration app set up:</p>
<pre>
rails registration
ruby script/plugin install http://svn.techno-weenie.net/projects/plugins/restful_authentication
ruby script/generate authenticated user sessions
</pre>
<p>Cool, now you have your registration app set up with a Users model, controller, and view. If you start up your server and head to http://localhost:3000/users/new/ you should see a very basic registration form. Let&#8217;s add our Address model. For the sake of brevity, I&#8217;m just going to create a field that references the User model and one field for a zip code, but you get the idea.</p>
<pre>
ruby script/generate model Address user:references zipcode:string
rake db:migrate
</pre>
<p>With our Address model in place, we need to let the User model know that it is linked to the Address model. Here&#8217;s what the User model looks like (\app\models\user.rb):</p>
<pre>
require 'digest/sha1'
class User &lt; ActiveRecord::Base
  # Virtual attribute for the unencrypted password
  attr_accessor :password

  validates_presence_of     :login, :email
  # lots more stuff that we're not going to worry about...
</pre>
<p>We&#8217;re going to add three things:</p>
<pre>
require 'digest/sha1'
class User &lt; ActiveRecord::Base
  has_one :address
  accepts_nested_attributes_for :address
  attr_accessible :address_attributes

  # Virtual attribute for the unencrypted password
  attr_accessor :password

  validates_presence_of     :login, :email
  # lots more stuff that we're not going to worry about...
</pre>
<p>We&#8217;ve told the User model that (1) it has one Address model, (2) that it should save data for Address automagically, and (3) that the address_attributes fields are permitted fields to receive data for (if you read through the code a bit further you&#8217;ll see another attr_accessible line, you could add address_attributes there too).</p>
<p>We need to make one change to the User controller (\controllers\users_controller.rb) to prevent an &#8220;Called id for nil&#8221; error later on. At line 6 you should have an empty new method. We&#8217;re going to create an instance variable for User:</p>
<pre>
  # render new.rhtml
  def new
    @user = User.new
  end
</pre>
<p>Let&#8217;s now take a look at the one User view that restful_auth created (\app\views\users\new.html.erb):</p>
<pre>
&lt;%= error_messages_for :user %&gt;
&lt;% form_for :user, :url =&gt; users_path do |f| -%&gt;
&lt;p&gt;&lt;label for=&quot;login&quot;&gt;Login&lt;/label&gt;&lt;br/&gt;
&lt;%= f.text_field :login %&gt;&lt;/p&gt;

&lt;p&gt;&lt;label for=&quot;email&quot;&gt;Email&lt;/label&gt;&lt;br/&gt;
&lt;%= f.text_field :email %&gt;&lt;/p&gt;

&lt;p&gt;&lt;label for=&quot;password&quot;&gt;Password&lt;/label&gt;&lt;br/&gt;
&lt;%= f.password_field :password %&gt;&lt;/p&gt;

&lt;p&gt;&lt;label for=&quot;password_confirmation&quot;&gt;Confirm Password&lt;/label&gt;&lt;br/&gt;
&lt;%= f.password_field :password_confirmation %&gt;&lt;/p&gt;

&lt;p&gt;&lt;%= submit_tag &#039;Sign up&#039; %&gt;&lt;/p&gt;
&lt;% end -%&gt;
</pre>
<p>First of all, we need to change the form_for :user to be form_for @user. Second, we get to add in our zipcode field:</p>
<pre>
&lt;%= error_messages_for :user %&gt;
&lt;% form_for @user, :url =&gt; users_path do |f| -%&gt;
&lt;p&gt;&lt;label for=&quot;login&quot;&gt;Login&lt;/label&gt;&lt;br/&gt;
&lt;%= f.text_field :login %&gt;&lt;/p&gt;

&lt;p&gt;&lt;label for=&quot;email&quot;&gt;Email&lt;/label&gt;&lt;br/&gt;
&lt;%= f.text_field :email %&gt;&lt;/p&gt;

&lt;p&gt;&lt;label for=&quot;password&quot;&gt;Password&lt;/label&gt;&lt;br/&gt;
&lt;%= f.password_field :password %&gt;&lt;/p&gt;

&lt;p&gt;&lt;label for=&quot;password_confirmation&quot;&gt;Confirm Password&lt;/label&gt;&lt;br/&gt;
&lt;%= f.password_field :password_confirmation %&gt;&lt;/p&gt;

&lt;% @user.build_address unless @user.address %&gt;
&lt;% f.fields_for :address do |a| %&gt;
  &lt;p&gt;
    &lt;%= a.label :zipcode %&gt;
    &lt;%= a.text_field :zipcode %&gt;
  &lt;/p&gt;
&lt;% end %&gt;

&lt;p&gt;&lt;%= submit_tag &#039;Sign up&#039; %&gt;&lt;/p&gt;
&lt;% end -%&gt;
</pre>
<p>Here&#8217;s where I ran into the two gotcha&#8217;s. If you don&#8217;t switch form_for :user to form_for @user when you submit the form you&#8217;ll get a very unpleasant error that looks like this:</p>
<pre>
ActiveRecord::AssociationTypeMismatch in UsersController#create
Address(#46729050) expected, got HashWithIndifferentAccess(#23561230)
</pre>
<p>Second, if you don&#8217;t add in line 15, @user.build_address unless @user.address, you&#8217;ll get the following error when you try to view the form:</p>
<pre>You have a nil object when you didn't expect it!</pre>
<p><a href="http://www.pixellatedvisions.com/2009/03/18/rails-2-3-nested-model-forms-and-nil-new-record">More info on why that error occurs here</a>.</p>
<p>Anyway, with the above steps you should now have a registration form that creates records for both User and Address. If you found this helpful, leave a comment and let me know!</p>
]]></content:encoded>
			<wfw:commentRss>http://scottblaine.com/how-to-use-additional-one-to-one-models-with-restful_authentication/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

