【问题标题】:Confusion over assocation and getting info from console对关联和从控制台获取信息的困惑
【发布时间】:2016-03-14 22:09:49
【问题描述】:

对尝试从 Rails 控制台获取信息感到困惑

我有以下型号:Article & Comment

对于Article,它是has_many :comments

对于Comment,它是belongs_to :article

让我们假设它们是关联的并且是功能性的。顺便说一句。

这是架构:

ActiveRecord::Schema.define(version: 20160312052519) do

  create_table "articles", force: :cascade do |t|
    t.string   "title"
    t.text     "text"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "comments", force: :cascade do |t|
    t.string   "commenter"
    t.text     "body"
    t.integer  "article_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  add_index "comments", ["article_id"], name: "index_comments_on_article_id"

end

这些是路线:

  resources :articles do 
    resources :comments 
  end

当我运行如下命令时:

Article.first.comments

Comment.first.article

Comment.first.article.title

Comment.first.article.text

Comment.first.commenter

Comment.first.body

它们都有效。

但是当我尝试在 Articles 上反向运行时,例如:

Article.first.comments.commenter

Article.first.comments.body

Article.all.comments

它们不起作用。为什么不?

编辑

这是我运行Article.first.comments.commenter时得到的结果

Article.first.comments.commenter
  Article Load (23.0ms)  SELECT  "articles".* FROM "articles"  ORDER BY "articles"."id" ASC LIMIT 1
NoMethodError:   Comment Load (0.4ms)  SELECT "comments".* FROM "comments" WHERE "comments"."article_id" = ?  [["article_id", 1]]
undefined method `commenter' for #<Comment::ActiveRecord_Associations_CollectionProxy:0x007fa32b7e3d00>
    from /Users/aa/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/activerecord-4.2.5/lib/active_record/relation/delegation.rb:136:in `method_missing'
    from /Users/aa/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/activerecord-4.2.5/lib/active_record/relation/delegation.rb:99:in `method_missing'
    from (irb):127
    from /Users/aa/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/railties-4.2.5/lib/rails/commands/console.rb:110:in `start'
    from /Users/aa/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/railties-4.2.5/lib/rails/commands/console.rb:9:in `start'
    from /Users/aa/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/railties-4.2.5/lib/rails/commands/commands_tasks.rb:68:in `console'
    from /Users/aa/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/railties-4.2.5/lib/rails/commands/commands_tasks.rb:39:in `run_command!'
    from /Users/aa/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/railties-4.2.5/lib/rails/commands.rb:17:in `<top (required)>'
    from /Users/aa/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/activesupport-4.2.5/lib/active_support/dependencies.rb:274:in `require'
    from /Users/aa/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/activesupport-4.2.5/lib/active_support/dependencies.rb:274:in `block in require'
    from /Users/aa/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/activesupport-4.2.5/lib/active_support/dependencies.rb:240:in `load_dependency'
    from /Users/aa/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/activesupport-4.2.5/lib/active_support/dependencies.rb:274:in `require'
    from /Users/aa/dropbox/beginningRails/guideblogagain/bin/rails:9:in `<top (required)>'
    from /Users/aa/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/activesupport-4.2.5/lib/active_support/dependencies.rb:268:in `load'
    from /Users/aa/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/activesupport-4.2.5/lib/active_support/dependencies.rb:268:in `block in load'
    from /Users/aa/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/activesupport-4.2.5/lib/active_support/dependencies.rb:240:in `load_dependency'
    from /Users/aa/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/activesupport-4.2.5/lib/active_support/dependencies.rb:268:in `load'
    from /Users/aa/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/spring-1.6.4/lib/spring/commands/rails.rb:6:in `call'
    from /Users/aa/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/spring-1.6.4/lib/spring/command_wrapper.rb:38:in `call'
    from /Users/aa/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/spring-1.6.4/lib/spring/application.rb:185:in `block in serve'
    from /Users/aa/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/spring-1.6.4/lib/spring/application.rb:156:in `fork'
    from /Users/aa/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/spring-1.6.4/lib/spring/application.rb:156:in `serve'
    from /Users/aa/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/spring-1.6.4/lib/spring/application.rb:131:in `block in run'
    from /Users/aa/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/spring-1.6.4/lib/spring/application.rb:125:in `loop'
    from /Users/aa/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/spring-1.6.4/lib/spring/application.rb:125:in `run'
    from /Users/aa/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/spring-1.6.4/lib/spring/application/boot.rb:18:in `<top (required)>'
    from /Users/aa/.rbenv/versions/2.1.4/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:55:in `require'
    from /Users/aa/.rbenv/versions/2.1.4/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:55:in `require'

【问题讨论】:

  • 它们到底是如何不起作用的?你有nil 还是例外?
  • @maximf,编辑了我上面的帖子以显示它产生的错误。
  • 你能显示评论类吗?它需要一个belongs_to :commenter

标签: ruby-on-rails ruby ruby-on-rails-4 associations


【解决方案1】:

Article.first.comments 是一个ActiveRecord_Associations_CollectionProxy 对象,类似于数组。如果您想为每条评论获取评论者,您可以使用map

Article.first.comments.map(&:commenter)

或者你可以获得第一条评论的评论者:

Article.first.comments.first.commenter

同样的事情:

Article.first.comments.body # Won't work

Article.first.comments.map(&:body) # Returns an array (each comment's body)

Article.all.comments # Won't work

Article.all.map(&:comments) # Returns an array (each article's comments)

【讨论】:

  • 嘿,谢谢你的回答。我可以根据您提供的答案提出后续问题吗? Article.first.comments.map(&amp;:commenter)(&amp;:commenter) 是一个过程,对吗?它是如何调用评论者的块的?对不起,如果我没有正确地表达这个问题。
  • @user27307254534534534543675765 是的,是的。给你:stackoverflow.com/a/1217114/999223
【解决方案2】:

当您运行工作示例Article.first.comments 时,请查看实际返回值。你看到了什么?返回的是一个对象数组,对吧?所以说Article.first 有10 个Comments。当您运行查询时,ActiveRecord 将返回一个包含 10 个Comment 对象的数组。

现在让我们看一下您的一个无效示例。

说,Article.first.comments.commenter。我们再次从Article.first 开始,我们知道它会返回我们数据库中的第一个Article 对象。

但下一步是考虑Article.first.comments

我们已经说服自己这是Comment 对象的数组,对吧?这就是问题所在——commenter 是单个Comment 对象的属性。

但是您没有单个 Comment 对象 - 您有一个 Comment 对象数组,并且 commenter 未在数组上定义。

Article.first.comments.body 的问题是一样的。这有意义吗?

您可以在控制台中执行以下操作:

Article.first.comments.each do |comment|  
  puts comment.commenter  
end 

然后您可以获得所有评论者/正文值。

使用这种思路,我认为您将能够说服自己对Article.all.comments 的问题,但如果不是,请随时发表评论,我们可以讨论一下。

Here are the docs 用于 Active Record 关系,供参考。干杯!

【讨论】:

  • 感谢您的深思熟虑的回答,让我考虑一下。我现在明白了,正如bodycommenter 那样,它们是我在一个数组上询问的单个项目,这当然是行不通的。但我确实有一个关于Article.all.comments 的问题。为什么这不起作用?我的意思是Article.all 有效,对吧?而comments 本身并不是一个单一的属性,所以...?
  • Article.all 视为数组(尽管不是)。您正在尝试在集合上调用方法 comments,它对其成员一无所知:他们是否有 comments 方法。您需要在集合的成员上调用comments,例如遍历它们并使用map
  • @queserasera,我赞成你的回答。非常感谢。
  • @user27307254534534534543675765 谢谢!我很高兴你能够取得进步!我不知道该扔给你多少,但 maximf 做到了。干杯:)
  • @queserasera,不用担心。 =)
猜你喜欢
  • 2011-08-18
  • 1970-01-01
  • 1970-01-01
  • 2017-10-10
  • 2013-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-21
相关资源
最近更新 更多