Question regarding associations

Ok… So I’ve got my initial table structures setup and I was hoping I
could have associations help me out with something akin to
embedded/nested objects but without the direct nesting (unless there’s
another way to achieve that goal)…

So, I’ve got an Address class that looks like the following :

class CreateAddresses < ActiveRecord::Migration
belongs_to :user

def self.up
create_table :addresses do |t|
t.string :address
t.string :city
t.string :state
t.string :zip
t.string :email
t.string :phone

  t.timestamps
end

end

def self.down
drop_table :addresses
end
end

I’ve then got a user class that looks like the following :

class CreateUsers < ActiveRecord::Migration
has_one :address

def self.up
create_table :users do |t|
t.srting :name
t.boolean :isProfileSetup
t.datetime :lastLogin
t.string :password
t.string :securityQ
t.string :securityA
t.string :username

  t.timestamps
end

end

def self.down
drop_table :users
end
end

I was hoping I could do something like the following in the rails
console and have it work
but it does not:

=> @user=User.create
=>@[email protected]

Any ideas on whether I’m barking up the wrong tree with associations –
perhaps using
the wrong syntax or is it even possible with what I want to do? I feel
like they ought to work
but

Any ideas?? Thanks!

You don’t have a FK for user_id in your ADDRESSES table for starters,
and
you didn’t include your model files, so there’s no way of knowing
whether
you’ve defined the relationships there.

See:

On 28 July 2011 07:53, Rick & Nellie F. [email protected] wrote:

Ok… So I’ve got my initial table structures setup and I was hoping I could have
associations help me out with something akin to embedded/nested objects but
without the direct nesting (unless there’s another way to achieve that goal)…

So, I’ve got an Address class that looks like the following :

class CreateAddresses < ActiveRecord::Migration
belongs_to :user

The belongs_to definition should be in the model class not the
migration.

t.timestamps
class CreateUsers < ActiveRecord::Migration
has_one :address

Ditto for has_one

Colin

On Jul 28, 2:53pm, Rick & Nellie F. [email protected] wrote:

Thanks guys! I’ll play with this some more when I come home this evening…

One more question if I could… If I get the plumbing all plugged in as needed,
do I ned to do
anything in particular with the view for the address object to get it to show up
when adding or
editing a user record or will it get pulled in automagically? Just curious.
Thanks!

accepts_nested_attributes_for is your friend for this one.

Fred

Thanks guys! I’ll play with this some more when I come home this
evening…

One more question if I could… If I get the plumbing all plugged in as
needed, do I ned to do
anything in particular with the view for the address object to get it to
show up when adding or
editing a user record or will it get pulled in automagically? Just
curious. Thanks!

I’m still trying to figure this all out in my head!

Ok… Still working on this stuff… I’ve got the t.reference in the
migration for the address class and moved the belongs_to and has_one in
the model classes as indicated (I didn’t notice that!).

I noticed in the association-basics that I should be putting a
create_table function (if that’s what
it’s called) in the CreateUsers class for Migrations but I’m concerned
about doing that since I’ll be using the address class on more than just
the ‘users’ class – does it really belong there or ??
Perhaps I’m overthinking this… ??

Below are the two class definitions for both the model & migration :

class Address < ActiveRecord::Base
belongs_to :user
belongs_to :organization
belongs_to :supplier
end

class CreateAddresses < ActiveRecord::Migration

def self.up
create_table :addresses do |t|
t.string :address
t.string :city
t.string :state
t.string :zip
t.string :email
t.string :phone
t.references : users

  t.timestamps
end

end

def self.down
drop_table :addresses
end
end

=================================
class User < ActiveRecord::Base
enum_attr :accountType, %w(regular admin site_admin), :init=>:regular

has_one :name
has_one :address
has_one :organization

end

class CreateUsers < ActiveRecord::Migration

def self.up
create_table :users do |t|
t.boolean :acctLocked
t.integer :familyId
t.boolean :isProfileSetup
t.datetime :lastLogin
t.string :password
t.string :securityQ
t.string :securityA
t.string :username
t.enum :accountType

  t.timestamps
end

create_table :a

end

def self.down
drop_table :users
end
end

Are you not using generators for the initial creation of your model and
migration source files? I’m asking because I think I can count on one
hand
the number of times I’ve ever written out a create_table function
myself.
Your inputs from the command line should do all this for you along with
some of the work of setting up your model associations (e.g. the
belongs_to
call in your Address class definition) and save you some effort. If
you’re
using the generators properly, you may never have to touch the migration
files for simpler applications.

rails g scaffold user acctLocked:boolean familyId:integer
isProfileSetup:boolean …
rails g model address user:references address:string city:string …

For more info:

One other small thing: you’re writing your variable names using camel
case
(lowerCaseWithCapitalsIndicatingWordBoundaries) whereas the more widely
recognized Ruby convention is to use all_lower_case_with_underscores. I
left your variable names as-is in the sample code above, but if it’s
code
that anyone else will ever see or work on, you might consider changing
it.

If you want to do revisions on existing tables (adding columns, changing
data types, etc.) you can use migrations for that as well. Experiment
on
the command line with patterns like:

rails g migration add_columns_to_addresses column_1:string
column_2:integer

rails g migration remove_columns_from_addresses column_1:string
column_2:integer …

The generator will try to figure out what you’re attempting to do if you
give it some basic instructions and if what you want to do isn’t too
complicated.

Thanks for the reply Chris…

I’ll switch away from Camelcase… I use that at work all day long (C++)
so I’m used to looking at
it.

I initially used the generator but when revising tables it didn’t want
to run anymore complaining
some of the files were already there – which is why I resorted to
hand-edits. I’ll do some more
reading on what you suggested… Thx!

– Rick

Thanks! I just realized I’ve got the “destroy” feature at my disposal
and that I’ve got a LOT of
reading ahead of me!

I’m thinking I’ll just blow things away and recreate until I find what
I’m looking for and it works
as expected. That might be easiest to ensure that the migrations don’t
bite me since this is just
the VERY early stages of an application…

– Rick

Chris –

one more question if you don’t mind too much! So, I blew away
everything and started over this
time using just the command line tools w/o fiddling around (at least
outside of adding the enum
pieces – which seem on the surface like they might plug into the
generator)… Below are the commands I use and works (sort-of) when using
the web-interface to http://localhost:3000/users/new

However, I don’t believe it’s creating the associations correctly – the
“has_one” is incorrect as it’s
kicked out when issuing the initial migrate to setup the database… Do
I need to put the has_one
in by hand or is my syntax messed up? I was looking over the api-docs
and thought i had it right
but perhaps not. Below are the commands I issued :

  1. rails new test
  2. rails generate scaffold user address:has_one acct_locked:boolean
    family_id:integer is_profile_setup:boolean last_login:datetime
    password:string security_question:string security_answer:string
    username:string type:string
  3. rails generate model address user:references street:string
    city:string state:string zip:string email:string phone:string
  4. bundle exec rake db:migrate

I get this on step #4 above :
rake aborted!
An error has occurred, this and all later migrations canceled:

undefined method has_one' for #<ActiveRecord::ConnectionAdapters::TableDefinition:0x007fd88525e148> /Users/nrf/.rvm/gems/ree-1.8.7-2011.03/gems/activerecord-3.0.9/lib/active_record/connection_adapters/abstract/schema_definitions.rb:326:in method_missing’

Ugg…

One of my favorite phrases on this mailing list: “Yeah, what Fred said.”
Migrations store information about your database, models store
information
about your classes, even though the differences right now might not be
completely clear. Associations require a foreign key to map to (e.g. as
denoted by “references” or actually creating an integer column with an
appropriate name) on one of your tables, and the bidirectional
relationships
should be set up in your models (e.g. subclasses of ActiveRecord::Base).

Another small protip if I can offer it: never name anything “test” as
you’ve
done with your application. It’s not a reserved word, there’s no
specific
restriction against it, but I’ve had any number of situations where
things
started behaving strangely as a result of naming some thing in my
application using a term that already has a meaning.

On Fri, Jul 29, 2011 at 10:20 AM, Frederick C. <

On Jul 29, 9:06am, Rick & Nellie F. [email protected] wrote:

  1. rails new test
  2. rails generate scaffold user address:has_one acct_locked:boolean
    family_id:integer is_profile_setup:boolean last_login:datetime password:string
    security_question:string security_answer:string username:string type:string
  3. rails generate model address user:references street:string city:string
    state:string zip:string email:string phone:string
  4. bundle exec rake db:migrate

has_one doesn’t belong in your migration/scaffold stuff. Add it to the
model later on. (belongs_to/references is the exception to this,
because user belongs_to :blah actually requires adding a column to the
users table whereas user has_one :blah doesn’t)

Fred