2

我想我在acts-as-taggable-on 中发现了一个奇怪的错误。其他人可以重现此错误吗?从一个裸 Rails 3 项目开始:

~ [13:57:32]: cd Development/
~/Development [13:59:44]: rvm use 1.9.3
Using /Users/andywhite/.rvm/gems/ruby-1.9.3-p194
Running /Users/andywhite/.rvm/hooks/after_use
~/Development [13:59:54]: rails -v
Rails 3.2.8
~/Development [14:00:01]: rails new foo --skip-bundle
      create  
      create  README.rdoc
      create  Rakefile
      create  config.ru
      create  .gitignore
      create  Gemfile
      create  app
      (snip)
      create  vendor/assets/javascripts/.gitkeep
      create  vendor/assets/stylesheets
      create  vendor/assets/stylesheets/.gitkeep
      create  vendor/plugins
      create  vendor/plugins/.gitkeep
~/Development [14:00:21]: cd foo
~/Development/foo [14:01:26]: rvm --rvmrc --create 1.9.3@foo
~/Development/foo [14:02:38]: cd ..
~/Development [14:02:40]: cd -
/Users/andywhite/Development/foo
====================================================================================
= NOTICE                                                                           =
====================================================================================
= RVM has encountered a new or modified .rvmrc file in the current directory       =
= This is a shell script and therefore may contain any shell commands.             =
=                                                                                  =
= Examine the contents of this file carefully to be sure the contents are          =
= safe before trusting it! ( Choose v[iew] below to view the contents )            =
====================================================================================
Do you wish to trust this .rvmrc file? (/Users/andywhite/Development/foo/.rvmrc)
y[es], n[o], v[iew], c[ancel]> yes
~/Development/foo [14:02:44]: vi Gemfile 
~/Development/foo [14:08:18]: cat Gemfile 
source 'http://rubygems.org'

gem 'rails', '3.2.8'

# Bundle edge Rails instead:
# gem 'rails', :git => 'git://github.com/rails/rails.git'

gem 'sqlite3'


# Gems used only for assets and not required
# in production environments by default.
group :assets do
  gem 'sass-rails',   '~> 3.2.3'
  gem 'coffee-rails', '~> 3.2.1'

  # See https://github.com/sstephenson/execjs#readme for more supported runtimes
  # gem 'therubyracer', :platforms => :ruby

  gem 'uglifier', '>= 1.0.3'
end

gem 'jquery-rails'

# To use ActiveModel has_secure_password
# gem 'bcrypt-ruby', '~> 3.0.0'

# To use Jbuilder templates for JSON
# gem 'jbuilder'

# Use unicorn as the app server
# gem 'unicorn'

# Deploy with Capistrano
# gem 'capistrano'

# To use debugger
# gem 'debugger'
gem 'acts-as-taggable-on'
~/Development/foo [14:08:26]: bundle
Fetching gem metadata from http://rubygems.org/.........
Using rake (0.9.2.2) 
Installing i18n (0.6.1) 
Installing multi_json (1.3.6) 
Installing activesupport (3.2.8) 
Installing builder (3.0.3) 
Installing activemodel (3.2.8) 
Installing erubis (2.7.0) 
Installing journey (1.0.4) 
Installing rack (1.4.1) 
Installing rack-cache (1.2) 
Installing rack-test (0.6.2) 
Installing hike (1.2.1) 
Installing tilt (1.3.3) 
Installing sprockets (2.1.3) 
Installing actionpack (3.2.8) 
Installing mime-types (1.19) 
Installing polyglot (0.3.3) 
Installing treetop (1.4.10) 
Installing mail (2.4.4) 
Installing actionmailer (3.2.8) 
Installing arel (3.0.2) 
Installing tzinfo (0.3.33) 
Installing activerecord (3.2.8) 
Installing activeresource (3.2.8) 
Using bundler (1.2.0) 
Installing rack-ssl (1.3.2) 
Installing json (1.7.5) with native extensions 
Installing rdoc (3.12) 
Installing thor (0.16.0) 
Installing railties (3.2.8) 
Installing rails (3.2.8) 
Installing acts-as-taggable-on (2.3.3) 
Installing coffee-script-source (1.3.3) 
Installing execjs (1.4.0) 
Installing coffee-script (2.2.0) 
Installing coffee-rails (3.2.2) 
Installing jquery-rails (2.1.3) 
Installing sass (3.2.1) 
Installing sass-rails (3.2.5) 
Installing sqlite3 (1.3.6) with native extensions 
Installing uglifier (1.3.0) 
Your bundle is complete! Use `bundle show [gemname]` to see where a bundled gem is installed.
Post-install message from rdoc:
Depending on your version of ruby, you may need to install ruby rdoc/ri data:

<= 1.8.6 : unsupported
 = 1.8.7 : gem install rdoc-data; rdoc-data --install
 = 1.9.1 : gem install rdoc-data; rdoc-data --install
>= 1.9.2 : nothing to do! Yay!

~/Development/foo [14:08:58]: rails g model Post body
      invoke  active_record
      create    db/migrate/20120930130941_create_posts.rb
      create    app/models/post.rb
      invoke    test_unit
      create      test/unit/post_test.rb
      create      test/fixtures/posts.yml
~/Development/foo [14:09:41]: rails g  acts_as_taggable_on:migration
      create  db/migrate/20120930131032_acts_as_taggable_on_migration.rb
~/Development/foo [14:10:31]: rake db:migrate
==  CreatePosts: migrating ====================================================
-- create_table(:posts)
   -> 0.0014s
==  CreatePosts: migrated (0.0015s) ===========================================

==  ActsAsTaggableOnMigration: migrating ======================================
-- create_table(:tags)
   -> 0.0013s
-- create_table(:taggings)
   -> 0.0012s
-- add_index(:taggings, :tag_id)
   -> 0.0005s
-- add_index(:taggings, [:taggable_id, :taggable_type, :context])
   -> 0.0007s
==  ActsAsTaggableOnMigration: migrated (0.0043s) =============================

~/Development/foo [14:10:41]: vi app/models/post.rb 
~/Development/foo [14:11:32]: cat app/models/post.rb 
class Post < ActiveRecord::Base
  attr_accessible :body, :tag_list
  acts_as_taggable
end
~/Development/foo [14:11:42]: rails c
Loading development environment (Rails 3.2.8)
1.9.3-p194 :001 > p = Post.create :body => 'My hat blew off'
   (0.1ms)  begin transaction
  SQL (217.4ms)  INSERT INTO "posts" ("body", "created_at", "updated_at") VALUES (?, ?, ?)  [["body", "My hat blew off"], ["created_at", Sun, 30 Sep 2012 13:12:28 UTC +00:00], ["updated_at", Sun, 30 Sep 2012 13:12:28 UTC +00:00]]
   (2.8ms)  commit transaction
 => #<Post id: 1, body: "My hat blew off", created_at: "2012-09-30 13:12:28", updated_at: "2012-09-30 13:12:28"> 
1.9.3-p194 :002 > p.tag_list = "news, boring, hats"
  ActsAsTaggableOn::Tag Load (0.2ms)  SELECT "tags".* FROM "tags" INNER JOIN "taggings" ON "tags"."id" = "taggings"."tag_id" WHERE "taggings"."taggable_id" = 1 AND "taggings"."taggable_type" = 'Post' AND (taggings.context = 'tags' AND taggings.tagger_id IS NULL)
 => "news, boring, hats" 
1.9.3-p194 :003 > p.save
   (0.1ms)  begin transaction
   (0.6ms)  UPDATE "posts" SET "updated_at" = '2012-09-30 13:13:28.210803' WHERE "posts"."id" = 1
  ActsAsTaggableOn::Tag Load (0.1ms)  SELECT "tags".* FROM "tags" WHERE (lower(name) = 'news' OR lower(name) = 'boring' OR lower(name) = 'hats')
  ActsAsTaggableOn::Tag Exists (0.1ms)  SELECT 1 AS one FROM "tags" WHERE "tags"."name" = 'news' LIMIT 1
  SQL (0.2ms)  INSERT INTO "tags" ("name") VALUES (?)  [["name", "news"]]
  ActsAsTaggableOn::Tag Exists (0.1ms)  SELECT 1 AS one FROM "tags" WHERE "tags"."name" = 'boring' LIMIT 1
  SQL (0.0ms)  INSERT INTO "tags" ("name") VALUES (?)  [["name", "boring"]]
  ActsAsTaggableOn::Tag Exists (0.1ms)  SELECT 1 AS one FROM "tags" WHERE "tags"."name" = 'hats' LIMIT 1
  SQL (0.0ms)  INSERT INTO "tags" ("name") VALUES (?)  [["name", "hats"]]
  ActsAsTaggableOn::Tag Load (0.1ms)  SELECT "tags".* FROM "tags" INNER JOIN "taggings" ON "tags"."id" = "taggings"."tag_id" WHERE "taggings"."taggable_id" = 1 AND "taggings"."taggable_type" = 'Post' AND (taggings.context = 'tags' AND taggings.tagger_id IS NULL)
  ActsAsTaggableOn::Tagging Exists (0.2ms)  SELECT 1 AS one FROM "taggings" WHERE ("taggings"."tag_id" = 1 AND "taggings"."taggable_type" = 'Post' AND "taggings"."taggable_id" = 1 AND "taggings"."context" = 'tags' AND "taggings"."tagger_id" IS NULL AND "taggings"."tagger_type" IS NULL) LIMIT 1
  SQL (0.4ms)  INSERT INTO "taggings" ("context", "created_at", "tag_id", "taggable_id", "taggable_type", "tagger_id", "tagger_type") VALUES (?, ?, ?, ?, ?, ?, ?)  [["context", "tags"], ["created_at", Sun, 30 Sep 2012 13:13:28 UTC +00:00], ["tag_id", 1], ["taggable_id", 1], ["taggable_type", "Post"], ["tagger_id", nil], ["tagger_type", nil]]
  ActsAsTaggableOn::Tagging Exists (0.1ms)  SELECT 1 AS one FROM "taggings" WHERE ("taggings"."tag_id" = 2 AND "taggings"."taggable_type" = 'Post' AND "taggings"."taggable_id" = 1 AND "taggings"."context" = 'tags' AND "taggings"."tagger_id" IS NULL AND "taggings"."tagger_type" IS NULL) LIMIT 1
  SQL (0.1ms)  INSERT INTO "taggings" ("context", "created_at", "tag_id", "taggable_id", "taggable_type", "tagger_id", "tagger_type") VALUES (?, ?, ?, ?, ?, ?, ?)  [["context", "tags"], ["created_at", Sun, 30 Sep 2012 13:13:28 UTC +00:00], ["tag_id", 2], ["taggable_id", 1], ["taggable_type", "Post"], ["tagger_id", nil], ["tagger_type", nil]]
  ActsAsTaggableOn::Tagging Exists (0.1ms)  SELECT 1 AS one FROM "taggings" WHERE ("taggings"."tag_id" = 3 AND "taggings"."taggable_type" = 'Post' AND "taggings"."taggable_id" = 1 AND "taggings"."context" = 'tags' AND "taggings"."tagger_id" IS NULL AND "taggings"."tagger_type" IS NULL) LIMIT 1
  SQL (0.1ms)  INSERT INTO "taggings" ("context", "created_at", "tag_id", "taggable_id", "taggable_type", "tagger_id", "tagger_type") VALUES (?, ?, ?, ?, ?, ?, ?)  [["context", "tags"], ["created_at", Sun, 30 Sep 2012 13:13:28 UTC +00:00], ["tag_id", 3], ["taggable_id", 1], ["taggable_type", "Post"], ["tagger_id", nil], ["tagger_type", nil]]
   (1.9ms)  commit transaction
 => true 
1.9.3-p194 :004 > p.tag_list
 => ["news", "boring", "hats"] 
1.9.3-p194 :005 > Post.tag_counts
  ActsAsTaggableOn::Tag Load (0.4ms)  SELECT tags.*, taggings.tags_count AS count FROM "tags" JOIN (SELECT taggings.tag_id, COUNT(taggings.tag_id) AS tags_count FROM "taggings" INNER JOIN posts ON posts.id = taggings.taggable_id WHERE (taggings.taggable_type = 'Post' AND taggings.context = 'tags') AND (taggings.taggable_id IN(SELECT posts.id FROM "posts" )) GROUP BY taggings.tag_id HAVING COUNT(taggings.tag_id) > 0) AS taggings ON taggings.tag_id = tags.id
ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: taggings.tag_id: SELECT tags.*, taggings.tags_count AS count FROM "tags" JOIN (SELECT taggings.tag_id, COUNT(taggings.tag_id) AS tags_count FROM "taggings" INNER JOIN posts ON posts.id = taggings.taggable_id WHERE (taggings.taggable_type = 'Post' AND taggings.context = 'tags') AND (taggings.taggable_id IN(SELECT posts.id FROM "posts" )) GROUP BY taggings.tag_id HAVING COUNT(taggings.tag_id) > 0) AS taggings ON taggings.tag_id = tags.id
  from /Users/andywhite/.rvm/gems/ruby-1.9.3-p194@foo/gems/sqlite3-1.3.6/lib/sqlite3/database.rb:91:in `initialize'
  from /Users/andywhite/.rvm/gems/ruby-1.9.3-p194@foo/gems/sqlite3-1.3.6/lib/sqlite3/database.rb:91:in `new'
  from /Users/andywhite/.rvm/gems/ruby-1.9.3-p194@foo/gems/sqlite3-1.3.6/lib/sqlite3/database.rb:91:in `prepare'
  from /Users/andywhite/.rvm/gems/ruby-1.9.3-p194@foo/gems/activerecord-3.2.8/lib/active_record/connection_adapters/sqlite_adapter.rb:246:in `block in exec_query'
  from /Users/andywhite/.rvm/gems/ruby-1.9.3-p194@foo/gems/activerecord-3.2.8/lib/active_record/connection_adapters/abstract_adapter.rb:280:in `block in log'
  from /Users/andywhite/.rvm/gems/ruby-1.9.3-p194@foo/gems/activesupport-3.2.8/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
  from /Users/andywhite/.rvm/gems/ruby-1.9.3-p194@foo/gems/activerecord-3.2.8/lib/active_record/connection_adapters/abstract_adapter.rb:275:in `log'
  from /Users/andywhite/.rvm/gems/ruby-1.9.3-p194@foo/gems/activerecord-3.2.8/lib/active_record/connection_adapters/sqlite_adapter.rb:242:in `exec_query'
  from /Users/andywhite/.rvm/gems/ruby-1.9.3-p194@foo/gems/activerecord-3.2.8/lib/active_record/connection_adapters/sqlite_adapter.rb:467:in `select'
  from /Users/andywhite/.rvm/gems/ruby-1.9.3-p194@foo/gems/activerecord-3.2.8/lib/active_record/connection_adapters/abstract/database_statements.rb:18:in `select_all'
  from /Users/andywhite/.rvm/gems/ruby-1.9.3-p194@foo/gems/activerecord-3.2.8/lib/active_record/connection_adapters/abstract/query_cache.rb:63:in `select_all'
  from /Users/andywhite/.rvm/gems/ruby-1.9.3-p194@foo/gems/activerecord-3.2.8/lib/active_record/querying.rb:38:in `block in find_by_sql'
  from /Users/andywhite/.rvm/gems/ruby-1.9.3-p194@foo/gems/activerecord-3.2.8/lib/active_record/explain.rb:40:in `logging_query_plan'
  from /Users/andywhite/.rvm/gems/ruby-1.9.3-p194@foo/gems/activerecord-3.2.8/lib/active_record/querying.rb:37:in `find_by_sql'
  from /Users/andywhite/.rvm/gems/ruby-1.9.3-p194@foo/gems/activerecord-3.2.8/lib/active_record/relation.rb:171:in `exec_queries'
  from /Users/andywhite/.rvm/gems/ruby-1.9.3-p194@foo/gems/activerecord-3.2.8/lib/active_record/relation.rb:160:in `block in to_a'
  from /Users/andywhite/.rvm/gems/ruby-1.9.3-p194@foo/gems/activerecord-3.2.8/lib/active_record/explain.rb:33:in `logging_query_plan'
  from /Users/andywhite/.rvm/gems/ruby-1.9.3-p194@foo/gems/activerecord-3.2.8/lib/active_record/relation.rb:159:in `to_a'
  from /Users/andywhite/.rvm/gems/ruby-1.9.3-p194@foo/gems/activerecord-3.2.8/lib/active_record/relation.rb:498:in `inspect'
  from /Users/andywhite/.rvm/gems/ruby-1.9.3-p194@foo/gems/railties-3.2.8/lib/rails/commands/console.rb:47:in `start'
  from /Users/andywhite/.rvm/gems/ruby-1.9.3-p194@foo/gems/railties-3.2.8/lib/rails/commands/console.rb:8:in `start'
  from /Users/andywhite/.rvm/gems/ruby-1.9.3-p194@foo/gems/railties-3.2.8/lib/rails/commands.rb:41:in `<top (required)>'
  from script/rails:6:in `require'
  from script/rails:6:in `<main>'1.9.3-p194 :006 > 
1.9.3-p194 :007 >   exit

因此,我们似乎缺少 *taggings.tag_id* 列。因此,让我们进入 sqlite3 进行调查:

~/Development/foo [14:14:39]: sqlite3 db/development.sqlite3 
SQLite version 3.7.14 2012-09-03 15:42:36
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> .headers on
sqlite> select * from taggings;
id|tag_id|taggable_id|taggable_type|tagger_id|tagger_type|context|created_at
1|1|1|Post|||tags|2012-09-30 13:13:28.357091
2|2|1|Post|||tags|2012-09-30 13:13:28.360285
3|3|1|Post|||tags|2012-09-30 13:13:28.362351
sqlite> .schema taggings
CREATE TABLE "taggings" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "tag_id" integer, "taggable_id" integer, "taggable_type" varchar(255), "tagger_id" integer, "tagger_type" varchar(255), "context" varchar(128), "created_at" datetime);
CREATE INDEX "index_taggings_on_tag_id" ON "taggings" ("tag_id");
CREATE INDEX "index_taggings_on_taggable_id_and_taggable_type_and_context" ON "taggings" ("taggable_id", "taggable_type", "context");
sqlite> 

嗯。所以专栏那里!?让我们剪切并粘贴有问题的 SQL,看看我们得到相同的缺失列错误:

sqlite> SELECT tags.*, taggings.tags_count AS count FROM "tags" JOIN (SELECT taggings.tag_id, COUNT(taggings.tag_id) AS tags_count FROM "taggings" INNER JOIN posts ON posts.id = taggings.taggable_id WHERE (taggings.taggable_type = 'Post' AND taggings.context = 'tags') AND (taggings.taggable_id IN(SELECT posts.id FROM "posts" )) GROUP BY taggings.tag_id HAVING COUNT(taggings.tag_id) > 0) AS taggings ON taggings.tag_id = tags.id;
id|name|count
1|news|1
2|boring|1
3|hats|1
sqlite> .exit
~/Development/foo [14:17:25]: 

什么……?有谁知道这里发生了什么。我错过了一些非常明显的事情吗?

更新(当天晚些时候):我找到了一个解决方法。覆盖 Posts 中的 *tag_counts* 类方法:

def self.tag_counts
  ActsAsTaggableOn::Tag.select("tags.*, count(taggings.tag_id) as count").
    joins(:taggings).group("taggings.tag_id")
end

感谢 Ryan Bates 和他出色的Railscasts 插曲作为此方法的起点。仍然有兴趣看看其他人是否可以重现该错误。

4

1 回答 1

0

我也有同样的错误。在我的 ubuntu 开发环境中运行良好,但在 centos 的生产环境中,我也收到了缺少 taggings.tag_id 错误。

相同版本的 ruby​​、rails 等。

于 2012-10-07T05:54:33.693 回答