Rails 3单表自引用关联不起作用

时间:2012-03-14 18:15:50

标签: ruby-on-rails-3 activerecord associations

我需要一些帮助。

我正在尝试使用自引用关联制作一个帖子表。一篇文章可能有一些回复(也发布)。我只包括主要部分。我的帖子课程是:

# == Schema Information
#
# Table name: microposts
#
#  id          :integer         not null, primary key
#  content     :string(255)
#  user_id     :integer
#  created_at  :datetime
#  updated_at  :datetime
#  in_reply_to :integer
#

class Micropost < ActiveRecord::Base

  attr_accessible :content, :in_reply_to
  ...
  belongs_to :user
  # SOMETHING SHOULD BE WRONG HERE ?!?
  has_many :replies, :class_name => 'Micropost',
                     :inverse_of => :replied_post
  belongs_to :replied_post, :class_name => 'Micropost',
                            :foreign_key => "in_reply_to",
                            :inverse_of => :replies

  ...
end

显然,我还有一个拥有帖子的用户类。

class User < ActiveRecord::Base
  ...
  has_many :microposts, :dependent => :destroy
  ...
end

虽然我可以照常创建帖子及其回复,但我不能使用自我关联。例如,在下一个rails控制台会话中,我创建了一个帖子并从另一个用户那里回复它:

--- 
<b>
1.9.2-p290 :014 > usr1=User.find(1)

  User Load (0.6ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1  [["id", 1]]
 => #<User id: 1, name: "Marcel Massana", email: "xaxaupua@gmail.com", created_at: "2012-03-13 00:07:12", updated_at: "2012-03-13 00:07:13", encrypted_password: "339f5f93bbbd7d9b4fdc58a89aa74797c23ccd5acb154e3987a...", salt: "849c6fbeb17e1a4a7e3ef3153d8c41f4ff3ca5435915f87f985...", admin: true> 

1.9.2-p290 :020 >   usr2=User.find(2)

  User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1  [["id", 2]]
 => #<User id: 2, name: "Pep Massana", email: "fitxia@gmail.com", created_at: "2012-03-13 00:07:13", updated_at: "2012-03-13 00:07:13", encrypted_password: "00707453381192a4cc7a5714df15da0fa4c2ffa944460bc33d2...", salt: "5af002dc3fad187dac26acee522d44d19d6a2daafcec7fb412e...", admin: true> 

1.9.2-p290 :021 > usr1.microposts.create(:content=>"Hi Pep")

  SQL (0.7ms)  INSERT INTO "microposts" ("content", "created_at", "in_reply_to", "updated_at", "user_id") VALUES (?, ?, ?, ?, ?)  [["content", "Hi Pep"], ["created_at", Wed, 14 Mar 2012 18:08:45 UTC +00:00], ["in_reply_to", nil], ["updated_at", Wed, 14 Mar 2012 18:08:45 UTC +00:00], ["user_id", 1]]
 => #<Micropost id: 104, content: "Hi Pep", user_id: 1, created_at: "2012-03-14 18:08:45", updated_at: "2012-03-14 18:08:45", in_reply_to: nil> 

1.9.2-p290 :022 > mp1=Micropost.find(104)

  Micropost Load (0.2ms)  SELECT "microposts".* FROM "microposts" WHERE "microposts"."id" = ? ORDER BY microposts.created_at DESC LIMIT 1  [["id", 104]]
 => #<Micropost id: 104, content: "Hi Pep", user_id: 1, created_at: "2012-03-14 18:08:45", updated_at: "2012-03-14 18:08:45", in_reply_to: nil> 

1.9.2-p290 :023 > mp2 = usr2.microposts.create(content: "good to see you Marcel", in_reply_to: 104)

  SQL (0.8ms)  INSERT INTO "microposts" ("content", "created_at", "in_reply_to", "updated_at", "user_id") VALUES (?, ?, ?, ?, ?)  [["content", "good to see you Marcel"], ["created_at", Wed, 14 Mar 2012 18:11:24 UTC +00:00], ["in_reply_to", 104], ["updated_at", Wed, 14 Mar 2012 18:11:24 UTC +00:00], ["user_id", 2]]
 => #<Micropost id: 105, content: "good to see you Marcel", user_id: 2, created_at: "2012-03-14 18:11:24", updated_at: "2012-03-14 18:11:24", in_reply_to: 104> 
</b>

--- 

然后我尝试使用Post自我关联,但其中一个不起作用:Post#replied_post似乎有效,但Post#reply不会:

--- 
<b>
1.9.2-p290 :024 > mp2.replied_post

  Micropost Load (0.3ms)  SELECT "microposts".* FROM "microposts" WHERE "microposts"."id" = 104 ORDER BY microposts.created_at DESC LIMIT 1

<Micropost id: 104, content: "Hi Pep", user_id: 1, created_at: "2012-03-14 18:08:45", updated_at: "2012-03-14 18:08:45", in_reply_to: nil> 

1.9.2-p290 :025 > mp1.replies

  Micropost Load (0.2ms)  SELECT "microposts".* FROM "microposts" WHERE "microposts"."micropost_id" = 104 ORDER BY microposts.created_at DESC
SQLite3::SQLException: no such column: microposts.micropost_id: SELECT "microposts".* FROM "microposts"  WHERE "microposts"."micropost_id" = 104 ORDER BY microposts.created_at DESC
ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: microposts.micropost_id: SELECT "microposts".* FROM "microposts"  WHERE "microposts"."micropost_id" = 104 ORDER BY microposts.created_at DESC
    from /home/marcel/.rvm/gems/ruby-1.9.2-p290/gems/sqlite3-1.3.5/lib/sqlite3/database.rb:91:in `initialize'
    from /home/marcel/.rvm/gems/ruby-1.9.2-p290/gems/sqlite3-1.3.5/lib/sqlite3/database.rb:91:in `new'
    from /home/marcel/.rvm/gems/ruby-1.9.2-p290/gems/sqlite3-1.3.5/lib/sqlite3/database.rb:91:in `prepare'
...
</b>

--- 

任何提示?我的关联定义有什么问题?我已经阅读了文档,似乎很明确。

TIA

PS:我的配置

About your application's environment
Ruby version              1.9.2 (i686-linux)
RubyGems version          1.8.10
Rack version              1.3
Rails version             3.1.3
JavaScript Runtime        therubyracer (V8)
Active Record version     3.1.3
Action Pack version       3.1.3
Active Resource version   3.1.3
Action Mailer version     3.1.3
Active Support version    3.1.3
Middleware                ActionDispatch::Static, Rack::Lock, #<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x9c4d494>, Rack::Runtime, Rack::MethodOverride, Rails::Rack::Logger, ActionDispatch::ShowExceptions, ActionDispatch::RemoteIp, Rack::Sendfile, ActionDispatch::Reloader, ActionDispatch::Callbacks, ActiveRecord::ConnectionAdapters::ConnectionManagement, ActiveRecord::QueryCache, ActionDispatch::Cookies, ActionDispatch::Session::CookieStore, ActionDispatch::Flash, ActionDispatch::ParamsParser, ActionDispatch::Head, Rack::ConditionalGet, Rack::ETag, ActionDispatch::BestStandardsSupport
Application root          /home/marcel/Dropbox/DESENVOLUPAMENT/Rails3Examples/ror_tutorial
Environment               development
Database adapter          sqlite3
Database schema version   20120313233558

1 个答案:

答案 0 :(得分:1)

我重新检查整个想法,发现我必须在:foreign_key => "in_reply_to"声明中添加has_many

has_many :replies, :class_name => 'Micropost',
                   :foreign_key => "in_reply_to",
                   :inverse_of => :replied_post
belongs_to :replied_post, :class_name => 'Micropost',
                          :foreign_key => "in_reply_to",
                          :inverse_of => :replies