Odd habtm behavior? or is it me?

Hello List,

I’m a bit spent on this problem, and my code might be whack. I seem to
be
encountering a problem where the primary key on a join table is not
being
resolved correctly. I will elaborate after some code bits. I am
creating
the join table using migrations, and relevant model code is this:

class Post < ActiveRecord::Base
has_and_belongs_to_many :records
has_and_belongs_to_many :categories
end

class Category < ActiveRecord::Base
has_and_belongs_to_many :posts

validates_uniqueness_of :name, :on => :create, :message => “must be
unique”

acts_as_tree :order => ‘name’

def before_validation
unless read_attribute(‘parent_id’)
write_attribute(‘parent_id’,0)
end
end

def validate
if read_attribute(‘parent_id’) == read_attribute(‘id’)
errors.add(‘parent_id’, ‘cannot be self’)
end
end

end # class Category


Categories are added via a controller which seems to be working
properly.
Posts are added with the ability to select one or more categories; (i
have
not added a validation for at least one category yet). The difficulty
that
I am having is with the PostsController’s save method (which is
programmed
to create/update).

class PostsController < ApplicationController

snip

def save

prepping @params[‘post’][‘categories’] which is an array of

legitimate
ids or nil
@params[‘post’][‘categories’] =
Category.find(@params[‘post’][‘categories’]
unless @params[‘post’][‘categories’].nil?

@post = @params[‘id’] ? Post.find(@params[‘id’]) : Post.new()
if @post.update_attributes(@params[‘post’])
# do redirect
else
# re-render form
end

end # def save


The odd behavior is the consistency in the following circumstances:

  1. if a Post does not have any categories assigned ( empty
    @params[‘post’][‘categories’] ) then a save is sucessful for both new
    and
    found Posts.

  2. if a new Post has a category then save is successful but the
    categories
    are not associated with the created object, but this sql is logged:
    INSERT INTO categories_posts (“post_id”, “id”, “category_id”) VALUES
    (0,1,1)

  • I have also tried: Post.create(@params[‘post’]).category_ids =
    @params[‘post’][‘categories’] # without the prep above and with
    attr_protected :categories
  1. if a Post created without categories is then updated with a category
    then
    2 things might happen:
    a) if the category was used in a step like 2, then this error is
    reported:
    Primary key must be unique: INSERT INTO categories_posts (“post_id”,
    “id”,
    “category_id”) VALUES (3, 1, 1)
    b) else, the category has not been used before and the save is
    succesful
    with this sql:
    INSERT INTO categories_posts (“post_id”, “id”, “category_id”) VALUES (3,
    2,

I think that exhausts the posibilities.

What’s bothering me the most is that the “id” column of categories_posts
is
not acting as I would like it to. How is the code causing this
behavior?
Is it something I’m doing wrong? This is my first attempt at habtm; I’m
tempted to try has_many :through … but … not … yet. I would like
to
understand this problem first.

  • travis

Travis Michel wrote:

Hello List,

I’m a bit spent on this problem, and my code might be whack. I seem to
be
encountering a problem where the primary key on a join table is not
being
resolved correctly. I will elaborate after some code bits. I am
creating
the join table using migrations, and relevant model code is this:

[SNIP]

I think that exhausts the posibilities.

What’s bothering me the most is that the “id” column of categories_posts
is
not acting as I would like it to. How is the code causing this
behavior?
Is it something I’m doing wrong? This is my first attempt at habtm; I’m
tempted to try has_many :through … but … not … yet. I would like
to
understand this problem first.

This behavior is not odd at all; in fact it’s expected. The problem is
that you have an id in your join table. habtm join tables are not
ActiveRecord models, so they don’t work with primary keys. A field named
id will get confused with the id field of the associated model. I think
a has_many :through association is what you want.

http://blog.hasmanythrough.com/articles/2006/04/20/many-to-many-dance-off


Josh S.
http://blog.hasmanythrough.com

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs