Problems with rspec, models and relationships in 2.0

I have a couple of problems which are kinda related, so I'll out them both here. I've been trying out rspec for the first time and I'm new to has_many :through relationships, so excuse me.

I want to relate a User to a WorldCity through a Locations relationship.

############file:models/user.rb class User < ActiveRecord::Base   has_many :locations   has_many :world_cities, :through => :locations end

############file:models/world_city.rb class WorldCity < ActiveRecord::Base   has_many :locations   has_many :users, :through => :locations end

############schema.rb ActiveRecord::Schema.define(:version => 3) do

  create_table "locations", :force => true do |t|     t.integer "user_id"     t.integer "world_city_id"     t.datetime "created_at"     t.datetime "updated_at"   end

  create_table "users", :force => true do |t|     t.string "username"     t.string "name"     t.integer "location_id"     t.datetime "created_at"     t.datetime "updated_at"   end

  create_table "world_cities", :force => true do |t|     t.string "name"     t.float "latitude"     t.float "longitude"     t.string "country"     t.string "region"     t.integer "location_id"     t.datetime "created_at"     t.datetime "updated_at"   end

end

###########user_spec.rb describe User do   fixtures :world_cities

  before(:each) do     @user = User.create( :name => "Bob Harris", :username => "bobharris" )   end

  it "has a user with username 'bobharris'" do     User.find_by_username("bobharris").should be_valid   end

  it "has a user with username 'bobharris with a related WorldCity'" do #########???   end

end

## Question ## I want the model to be able to assign a random WorldCity to a new user (not really important why here). Where should this be done and how do I test it in rspec? I'm sure if I had an example I could understand this, but can I change the user.rb to override the create method and add a location; does the rails framework let me assign a WordCity to a User and take care of the relationship (that would be nice).

I've tried everything I can think of but can't get my head around it.

Please help.

If you're going to use has_many :through then you also need a model for the join table (Location). You may have that but you didn't describe it above.

As for assigning to that join table, there are many ways you can do it depending on how early you need the association. Check into the before_xxx (create, validate, etc) ActiveRecord callbacks that allow you to hook into the object creation process without having to override the default functionality.

If you're going to use has_many :through then you also need a model for the join table (Location). You may have that but you didn't describe it above.

Yes I have:

class Location < ActiveRecord::Base   belongs_to :user   belongs_to :world_city end

As for assigning to that join table, there are many ways you can do it depending on how early you need the association. Check into the before_xxx (create, validate, etc) ActiveRecord callbacks that allow you to hook into the object creation process without having to override the default functionality.

Thanks, I will.

So assuming that the random mentioned below works, does that mean that I should be ding somethingg kime this in user.rb?

def before_create     wc = WorldCity.new.random     loc = Location.create( :world_city_id => wc.id, :user_id => @id)     @location_id = loc.id end

You don't need the location_id field in users and world_cities tables. locations has no id field. Nor is it needed.

The user record may need to be saved before you can create a location relationship. It has no id until it is saved

user = User.create(:name => "Fred Flintstone", :username => "fred") loc = randomCity() user.locations << loc user.save

HTH,   Jeffrey

Quoting Col Wilson <col.wilson.email@googlemail.com>:

Good catch Jeffrey. The location_id in both User and WorldCity is unnecessary.

For the assignment, I'd work along these lines (untested):

class User < ActiveRecord::Base   has_many :locations   has_many :world_cities, :through => :locations

  before_create :assign_random_city

  private   def assign_random_city     self.locations.create :world_city=>WorldCity.random   end end

Thanks all for you replies.