Saving Habtm with Extra Fields

Saving HABTM with extra fields?

HABTM is over-sold. A lot of the times it fails to meet the needs, such as when you have additional data to store. You'll be better off to do a hasMany/belongsTo relationship between the models.

Taken from the CakePHP Book:

What to do when HABTM becomes
complicated?

By default when saving a
HasAndBelongsToMany relationship, Cake
will delete all rows on the join table
before saving new ones. For example if
you have a Club that has 10 Children
associated. You then update the Club
with 2 children. The Club will only
have 2 Children, not 12.

Also note that if you want to add more
fields to the join (when it was
created or meta information) this is
possible with HABTM join tables, but
it is important to understand that you
have an easy option.

HasAndBelongsToMany between two models
is in reality shorthand for three
models associated through both a
hasMany and a belongsTo association.

In your case I would suggest making a LineItem model and joining everything that way:

  • Order hasMany LineItem
  • LineItem belongsTo Order, Product

How to save extra fields in Rails using has_and_belongs_to_many

Note the following is for Rails v2

    script/generate model Movie id:primary_key name:string
script/generate model Actor id:primary_key movie_id:integer celeb_id:integer cast_name:string cast_type:string
script/generate model Celeb id:primary_key name:string

model/movie.rb
class Movie < ActiveRecord::Base
has_many :actors
has_many :celebs, :through => :actors
end

model/celeb.rb
class Celeb < ActiveRecord::Base
has_many :actors
has_many :movies, :through => :actors
end

model/actor.rb
class Actor < ActiveRecord::Base
belongs_to :movie
belongs_to :celeb
end

Test the associations with the ruby rails console in the application folder

>script/console
>m = Movie.new
>m.name = "Do Androids Dream Of Electric Sheep"
>m.methods.sort #this will list the available methods

#Look for the methods 'actors' and 'celebs' - these
#are the accessor methods built from the provided models

>m.actors #lists the actors - this will be empty atm
>c = Celeb.new
>c.name = "Harrison Ford"
>m.celebs.push(c) #push Harrison Ford into the celebs for Blade Runner
>m.actors #Will be empty atm because the movie hasnt been saved yet
>m.save #should now save the Movie, Actor and Celeb rows to relevant tables
>m.actors #Will now contain the association for

#Movie(id : 1, name : "Do Androids..") - Actor(id : 1, movie_id : 1, celeb_id : 1) -
#Celeb(id : 1, name : "Harrision Ford")

>m = Movie.new #make a new movie
>m.name = "Star Wars"
>m.celebs.push(c) #associated the existing celeb with it
>m.save
>movies = Movie.all #should have the two movies saved now
>actors = Actor.all #should have 2 associations
>this_actor = Actor.first
>this_actor.cast_type = "ACTOR"
>this_actor.save

Then you'll probably want to check out Ryan Bates' Railcasts http://railscasts.com #47 (Two Many-to-Many), and #73, #74, #75 (Complex forms parts 1-3).

There's an updated version of the many-to-many form code on the webpage for #75.

Add extra field in Rails habtm joins

Instead of HABTM you'd use has_many and has_many :through.

class User < ActiveRecord::Base
has_many :memberships
has_many :team, through: :membership
end

class Membership < ActiveRecord::Base # This would be your old 'join table', now a full model
belongs_to :user
belongs_to :team
end

class Team < ActiveRecord::Base
has_many :memberships
has_many :users, through: :memberships
end

Cakephp save extra attribute in HABTM relation

Don't use HABTM

The simplest way to handle has-and-belongs-to-many relations with extra attributes is to obey this rule:

When a link table has more than 2 fields: make it a model

That means convert this relation:

Theme <-habtm-> Color

Into:

Theme <-hasmany- ThemeColor
ThemeColor -belongsTo-> Color
ThemeColor -belongsTo-> Theme

This gives you more control, and simpler code/logic. It's still possible to use a habtm relation when it suits you, and not when it doesn't.

The data structure when saving would then be:

array(
'Theme' => array(...),
'ThemeColor' => array(
array('color_id' => x, 'preview' => y),
...
)
)

There's more detailed notes on this in the documentation.

CakePHP: habtm with join table having an extra field

In your case, HABTM is not the correct association to use. You should be using the hasMany through association.

The fundamental change is that you need a third model based on your product_guest table.

Create these relationships:

  • Product hasMany ProductGuest
  • Guest hasMany ProductGuest
  • ProductGuest belongsTo Product
  • ProductGuest belongsTo Guest

CakePHP defining additional fields in HABTM/ManyToMany relationship?

if you want to have additional data in HABTM, use 2 hasMany relationships instead. So if A HABTM B, then set it up as: A hasMany A_B, B hasMany A_B, A_B belongsTo A, A_B belongsTo B. AFAIK, Cake support for HABTM is not very flexible.



Related Topics



Leave a reply



Submit