rake db:seed with has_many through (m:n with seperate table)

My model consists of users and tasks (m:n), the relation is stored in a seperate table sharedtabs (that contains some extra fields). Between tabs and tasks there is a 1:n relation.

I have trouble writing my seed.rb:

works: (1) tab = Tab.create(:name => ‘Admin’, :category => 0) tab.tasks.create(:name => ‘Admin_Tab1_Private Task 1’)

works: (2) User.create(:email => ‘foo’, :password => ‘bar’) Tab.create(:name => ‘Admin’, :category => 0) Sharedtab.create(:user_id => 1, :tab_id => 1, :owner => true)

works: (3) @user = User.create(:email => ‘foo’, :password => ‘bar’) tab = @user.tabs.build(:name => ‘test’, :category => 0) sharedtab = tab.sharedtabs.build sharedtab.user = @user tab.save

sharedtab.save # seems to work without it

I believe, that (1) is correct…if not, kindly tell me. (2) works, though I think I should not have to set the foreign keys manually. I have a very bad feeling about (3). While working, it is ugly and looks weird. Do you have any tips for me?

Database-Schema (removed some fields for more clarity)

create_table “sharedtabs”, :id => false, :force => true do |t| t.integer “user_id”, :null => false t.integer “tab_id”, :null => false t.boolean “owner”, :default => false, :null => false end

add_index “sharedtabs”, [“tab_id”], :name => “index_sharedtabs_on_tab_id” add_index “sharedtabs”, [“user_id”], :name => “index_sharedtabs_on_user_id”

create_table “tabs”, :force => true do |t| t.string “name”, :default => “New Tab”, :null => false t.integer “category”, :default => 0, :null => false end

create_table “tasks”, :force => true do |t| t.integer “tab_id”, :null => false t.string “name”, :default => “New Task”, :null => false end

add_index “tasks”, [“tab_id”], :name => “index_tasks_on_tab_id”

create_table “users”, :force => true do |t| t.string “email”, :default => “”, :null => false end

Models

class Sharedtab < ActiveRecord::Base

attr_accessible :tab_id, :owner, :permissions, :position, :customname, :customcategory

belongs_to :user
belongs_to :tab

validates :user_id, :presence => true validates :tab_id, :presence => true end

class User < ActiveRecord::Base

attr_accessible :name, :email

has_many :sharedtabs, :dependent => :destroy has_many :tabs, :through => :sharedtabs, :dependent => :destroy end

class Tab < ActiveRecord::Base

attr_accessible :name, :category

has_many :tasks, :dependent => :destroy

has_many :sharedtabs, :dependent => :destroy has_many :users, :through => :sharedtabs end

class Task < ActiveRecord::Base

attr_accessible :name

belongs_to :tab

default_scope :order => ‘tasks.created_at DESC’ end

bourne wrote in post #971468:

My model consists of users and tasks (m:n), the relation is stored in a seperate table sharedtabs (that contains some extra fields). Between tabs and tasks there is a 1:n relation.

I have trouble writing my seed.rb:

works: (1) tab = Tab.create(:name => 'Admin', :category => 0) tab.tasks.create(:name => 'Admin_Tab1_Private Task 1')

works: (2) User.create(:email => 'foo', :password => 'bar') Tab.create(:name => 'Admin', :category => 0) Sharedtab.create(:user_id => 1, :tab_id => 1, :owner => true)

works: (3) @user = User.create(:email => 'foo', :password => 'bar') tab = @user.tabs.build(:name => 'test', :category => 0) sharedtab = tab.sharedtabs.build sharedtab.user = @user tab.save # sharedtab.save # seems to work without it

I believe, that (1) is correct....if not, kindly tell me. (2) works, though I think I should not have to set the foreign keys manually.

Right. You should just be able to do Sharedtab.create :user => @user, :tab => @tab...or @user.sharedtabs.create(:tab => @tab)...you get the idea.

And it really should be SharedTab.

I have a very bad feeling about (3). While working, it is ugly and looks weird. Do you have any tips for me?

Use .create instead of the combination of .build, assign, .save.

What do you think is ugly here?

Best,

Right. You should just be able to do Sharedtab.create :user => @user,

:tab => @tab…or @user.sharedtabs.create(:tab => @tab)…you get the

idea.

Thank you so much!

And it really should be SharedTab.

I noticed your comment in the last thread and will definitely change

that. Mine is Sharedtab, you propose SharedTab / Shared_Tab. What is

Rails convention for that, what about User_Tab? (remark: Sharedtab

has additional fields as owner, position, …).

All the best for 2011!

bourne wrote in post #971508:

Right. You should just be able to do Sharedtab.create :user => @user, :tab => @tab...or @user.sharedtabs.create(:tab => @tab)...you get the idea.

Thank you so much!

And it really should be SharedTab.

I noticed your comment in the last thread and will definitely change that. Mine is Sharedtab, you propose SharedTab / Shared_Tab.

SharedTab / shared_tab. Never Shared_Tab.

What is

Rails convention for that, what about User_Tab? (remark: Sharedtab has additional fields as owner, position, ...).

Rails convention expects to have underscore_case for everything except class names, which are in CamelCase. The autoloader would expect to find class UserTab in app/models/user_tab.rb . I think User_Tab would be expected in user__tab.rb (note the extra underscore), but don't bother.

You can load classes with explicit require statements if you want to, but why defeat the autoloader?

All the best for 2011!

Best,