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,