acts_as_taggable and foreign keys

Hi,

I've developed an application last year with rails 1.2.3 and it worked
fine on the web server till recently. Not sure what started the
problem but I am having trouble with acts_as_taggable gem (which I
know has been depreciated).

It was suggested to look into has_many_polymorphs but I ran into
problems with updating my database. The database has 3 tables
(:products, :tags, :products_tags) and uses foreign keys.
The application is based on "Beginning RoR e_commerce". Tags table has
2 columns: id and name.

So, I gave that up on that one and tried to find an easier solution.
Other things I looked at:
* I installed acts_as_taggable as plugin instead of a gem -- but I'm
just not sure what to change in the application in order to get it to
work
* I installed acts_as_taggable_on_steroids -- but again, I think I ran
into the same problem with the foreign keys. This is the error message
I get when I try "rake db:migrate"

[code]
Mysql::Error: Table 'tags' already exists: CREATE TABLE tags (`id`
int(11) DEFAULT NULL auto_increment PRIMARY KEY, `name` varchar(255)
DEFAULT NULL) ENGINE=InnoDB
[/code]

Would anyone have a solution on how to fix my problem?
Thanks in advance,
Elle

So, I gave that up on that one and tried to find an easier solution.
Other things I looked at:
* I installed acts_as_taggable as plugin instead of a gem -- but I'm
just not sure what to change in the application in order to get it to
work
* I installed acts_as_taggable_on_steroids -- but again, I think I ran
into the same problem with the foreign keys. This is the error message
I get when I try "rake db:migrate"

[code]
Mysql::Error: Table 'tags' already exists: CREATE TABLE tags (`id`
int(11) DEFAULT NULL auto_increment PRIMARY KEY, `name` varchar(255)
DEFAULT NULL) ENGINE=InnoDB
[/code]

I assume acts_as_taggable_on_steroids is trying to create a tags table
that you already have. I'd just blow away that migration (after
checking that the table it was trying to create matches the one you
already have.

Fred

Thanks Fred. I did just that. I also dropped my products_tags table
because as I understand the 'taggings' table created by the plugin
acts as the connector. Now, I don't care about losing that data in
this case, I can always enter it manually (and I am happy not to be
using a depreciated gem).... but I feel hopeless as I am not sure how
to make it work from now on.

What I've done so far is:
1. Installed plugin
2. Added db table: taggings. Already had tags with id and name column.
3. Added acts_as_taggable to my Product class

When I login as admin to try and tag the products manually, I get this
error message (when I have both acts_as_taggable and
acts_as_taggable_on_steroids plugins installed):

NoMethodError in ProductController#update
undefined method `tag_collection_name' for Product:Class

My update method includes the following:

def update
    @product = Product.find(params[:id])
    @product.tag(params[:tags], :separator => ',', :clear => true)

    if @product.update_attributes(params[:product])
      flash[:notice] = 'Product was successfully updated.'
      redirect_to :action => 'show', :id => @product
    else
      load_data
      render :action => 'edit'
    end
  end

private

    def load_data
      @categories = Category.find(:all)
      @tags = Tag.find(:all)
    end

I am just not sure how to make the connection between the tag and the
product.
Help. Please.

Elle

First off, you're probably asking for trouble by having both installed

Secondly, have you tried just looking at the examples in the
acts_as_taggable_on_steroids documentation ?

Fred

First off, you're probably asking for trouble by having both installed

Well, when I deleted acts_as_taggable, I got an error of:

Processing ProductController#update (for 127.0.0.1 at 2008-07-15
18:35:50) [POST]
  Parameters: {"commit"=>"Edit", "tags"=>"LS750", "product"=>{...},
"action"=>"update", "id"=>"1", "controller"=>"product"}
[...]
NoMethodError (undefined method `tag' for #<Product:0x26064fc>):

Secondly, have you tried just looking at the examples in the
acts_as_taggable_on_steroids documentation ?

Yes I have but I guess I'm just too new to easily know how to
implement it all :slight_smile:

Advice?

Thanks,
Elle

> First off, you're probably asking for trouble by having both installed

Well, when I deleted acts_as_taggable, I got an error of:

Processing ProductController#update (for 127.0.0.1 at 2008-07-15
18:35:50) [POST]
Parameters: {"commit"=>"Edit", "tags"=>"LS750", "product"=>{...},
"action"=>"update", "id"=>"1", "controller"=>"product"}
[...]
NoMethodError (undefined method `tag' for #<Product:0x26064fc>):

> Secondly, have you tried just looking at the examples in the
> acts_as_taggable_on_steroids documentation ?

Yes I have but I guess I'm just too new to easily know how to
implement it all :slight_smile:

Well accordeing to those docs tag doesn't exists: all those examples
show manipulation of tag_list (tag_list.add, tag_list.remove etc...)

Fred

I don't have tag_list method. I haven't used it with the gem. My tag
controller has:

def list
   @page_title = 'Listing tags'
   @tags = Tag.find(:all)
   @tag_pages, @tags = paginate :tags, :order => :name, :per_page =>
10
  end
  def show
    # tag = params[:id]
    @tag = Tag.find(params[:id])
    @page_title = "Products tagged with '#{tag}'"
    @products = Product.find_tagged_with(:any => tag, :separator =>
',')
  end

and Tag class has:

has_and_belongs_to_many :products

Any suggestions to how I could fix this?

Thanks,
Elle

If you look at acts_as_taggable_with_steroids, it adds that method to
your models (when you call acts_as_taggable).
I think you're getting confused because you think
acts_as_taggable_with_steroids is a drop in replacement for
acts_as_taggable which it would appear it isn't.
The examples in its documentation look pretty straightforward, I
suggest you forget what you know about acts_as_taggable and look at
those instead.

Fred

I agree the examples do look straightforward. But as usual, I still
have questions:
I started the console and did the following:

p = Product.find(:first)

=>#<Product:0x2285ad0 @attributes=...

p.tag_list.add("tagnamehere")

=> ["tagnamehere"]

p

=>#<Product:0x2285ad0 @tag_list=["tagnamehere"], @tags=[], ...

Now, I don't understand what is the difference between @tag_list and
@tags.

I've also looked at http://taggable.rubyforge.org/ and tried to use:
p.tag --> error: NoMethodError: undefined method `tag_model' for
Product:Class
p.tag_with --> error: NoMethodError: undefined method `tag_with' for
#<Product:0x2285ad0>
p.tag.add --> ArgumentError: wrong number of arguments (0 for 1)
        from (irb):7:in `tag'
        from (irb):7

Elle

One more question. When I am still in console, I added a tag to
p.tag_list, then when I want to save the product (p.save) I get the
following error:

NoMethodError: undefined method `find_or_create_with_like_by_name' for
Tag:Class
        from ./script/../config/../config/../vendor/rails/activerecord/
lib/active_record/base.rb:1235:in `method_missing'
        from ./script/../config/../config/../vendor/plugins/
acts_as_taggable_on_steroids/lib/acts_as_taggable.rb:182:in
`save_tags'
        from ./script/../config/../config/../vendor/plugins/
acts_as_taggable_on_steroids/lib/acts_as_taggable.rb:181:in `each'
        from ./script/../config/../config/../vendor/plugins/
acts_as_taggable_on_steroids/lib/acts_as_taggable.rb:181:in
`save_tags'
        ...

Would anyone know why I get this error?

Thanks,
Elle

I agree the examples do look straightforward. But as usual, I still
have questions:
I started the console and did the following:

p = Product.find(:first)

=>#<Product:0x2285ad0 @attributes=...

p.tag_list.add("tagnamehere")

=> ["tagnamehere"]

p

=>#<Product:0x2285ad0 @tag_list=["tagnamehere"], @tags=[], ...

Now, I don't understand what is the difference between @tag_list and
@tags.

internal implemenation details

I've also looked at http://taggable.rubyforge.org/ and tried to use:
p.tag --> error: NoMethodError: undefined method `tag_model' for
Product:Class
p.tag_with --> error: NoMethodError: undefined method `tag_with' for
#<Product:0x2285ad0>
p.tag.add --> ArgumentError: wrong number of arguments (0 for 1)
       from (irb):7:in `tag'
       from (irb):7

I think you will definitely confuse things by chopping and changing
between multiple tagging libraries all with slightly different
semantics (and which could easily conflict when used simultaneously)

Fred

One more question. When I am still in console, I added a tag to
p.tag_list, then when I want to save the product (p.save) I get the
following error:

That implies that you've got your own tag model in app/models which is
taking precedence over the one bundled in the plugin.

Fred

Thanks Fred. That helped. I looked at a couple tutorials and none
mentioned having a tag model (or the original plugin).
One tutorial that was very helpful was:
http://dagobart.wordpress.com/2008/06/19/for-purpose-of-reference-enable-tagging-in-a-rails-model/
Removing my tag model let's me save the product :slight_smile:

When I go to view product, I can see my assigned tag. But I still have
questions/problems:

Q1. I've been having problems trying to update a product. My
product_controller.rb#update has:
@product.tag(params[:tags], :separator => ',', :clear => true)

When I try to update a product I get this error:
NoMethodError in ProductController#update
undefined method `tag' for #<Product:0x23e6dd4>

Q2. To display the tags and links to show tags I use a helper method
in application_helper.rb:
def display_tags(product)
    product.tags.collect{|tag| link_to tag.name, :controller => '/
tag', :action => 'show', :id => tag.name }.join(", ") if product.tags
end

My tag_controller.rb#show is:
def show
    @tag = Tag.find(params[:id])
    @page_title = "Products tagged with '#{tag}'"
    @products = Product.find_tagged_with(:any => tag, :separator =>
',')
  end

But when I try to view all other products with the same tag I get an
error:
NameError in TagController#show
undefined local variable or method `tag' for #<TagController:
0x2514c4c>

Should I even have a tag controller?
The plugin docs use Product.find_tagged_with('tag'). How could I use
that?

Thanks again so much,
Elle

Thanks Fred. That helped. I looked at a couple tutorials and none
mentioned having a tag model (or the original plugin).
One tutorial that was very helpful was:
http://dagobart.wordpress.com/2008/06/19/for-purpose-of-reference-enable-tagging-in-a-rails-model/
Removing my tag model let's me save the product :slight_smile:

When I go to view product, I can see my assigned tag. But I still have
questions/problems:

Q1. I've been having problems trying to update a product. My
product_controller.rb#update has:
@product.tag(params[:tags], :separator => ',', :clear => true)

When I try to update a product I get this error:
NoMethodError in ProductController#update
undefined method `tag' for #<Product:0x23e6dd4>

according to the plugin docs you should be using tag_list (ie
tag_list=, tag_list.add etc...

Q2. To display the tags and links to show tags I use a helper method
in application_helper.rb:
def display_tags(product)
   product.tags.collect{|tag| link_to tag.name, :controller => '/
tag', :action => 'show', :id => tag.name }.join(", ") if product.tags
end

My tag_controller.rb#show is:
def show
   @tag = Tag.find(params[:id])
   @page_title = "Products tagged with '#{tag}'"
   @products = Product.find_tagged_with(:any => tag, :separator =>
',')
end

But when I try to view all other products with the same tag I get an
error:

You've just got a syntax error there - it should be @tag not tag

NameError in TagController#show
undefined local variable or method `tag' for #<TagController:
0x2514c4c>

Should I even have a tag controller?
The plugin docs use Product.find_tagged_with('tag'). How could I use
that?

Product.find_tagged_with @tag
should work (assuming @tag contains a tag)

I'd encourage you to look closely at the docs, all i've done here is
repeat them to you

Fred

Sorry to be a bother and thank you so much for your help Fred. Almost
all is fixed. Got one last problem/question.

On every product page, there is a section for recommended products --
which really are products tagged with similar tags.
In my catalog_controller.rb#show I have:
    @tag = Tag.find(params[:id])
    @tagged_related = Product.find_tagged_with (@tag, :match_all =>
true)

But instead of picking on the tag's id, it gets the product's id. This
causes two problems:
1. It doesn't really show related products
2. If the id it gets doesn't exists in the tags table, i get an error.
I'm just not sure how to pick up the tag id instead.

Thanks,
Elle

If problem is that params[:id] is a product id then surely the problem
is just with whatever bit of code produces the link to this page?

Fred