【问题标题】:How do you access an object's (ActiveRecord::Relation) value by key in Ruby on Rails?如何在 Ruby on Rails 中通过键访问对象的 (ActiveRecord::Relation) 值?
【发布时间】:2015-01-31 05:01:42
【问题描述】:

tl;dr 如何获取对象的键对应的值?

我很困惑为什么

Atag.where(tag:'brand') 给了我一个我称之为对象的东西,因为没有更好的术语:#<ActiveRecord::Relation [#<Atag id: 1, tag: "brand", created_at: "2015-01-31 04:29:20", updated_at: "2015-01-31 04:29:20">]>

但我很难访问键的相应值:id。

Atag.where(tag:'brand').idAtag.where(tag:'brand')[:id]Atag.where(tag:'brand')(:id) 都会抛出错误,而在这种情况下,我只是试图返回整数 1。

我似乎无法用我的谷歌搜索技能(或缺乏技能)找到这个基本问题的简洁答案。

谢谢

【问题讨论】:

  • 啊,Atag.where(tag:'brand')[0].id 成功了
  • 我看到 'where' 方法返回了一个对象的对象,所以我需要指定我想要第一个对象。

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


【解决方案1】:

通过以下查询获取标签的 id = 'brand':

Atag.find_by(tag:'brand').id 

检查以下变化:

Atag.find(1) 
#gives you the object with the Atag id = 1

Atag.find(100) #let's say this record does not exist then you will 
get ActiveRecord::RecordNotFound exception. 

更好的选择:

Atag.where(id: 1) 
#this returns you a relation and it's true you are trying to access
 only a single object.

Hence, you just need to modify it to :
Atag.where(id: 1).first 
#Above one will give you an object of Atag not an association result.
# to verfiy you can execute, Atag.where(id: 1).first.class

Atag.where(id: 999).first
 # In this case if there is no record found with id = 999, then it'll 
return  nil which can be easily handled than an exception found 
while using find method.

使用动态查找器获得相同的风味。

Atag.find_by(id: 1) #gives the Atag with id 1 
Atag.find_by_id(1). # same as above.
Atag.find_by(id: 999) #if not found then simply returns nil. 
Atag.find_by(name: 'ruby') #return Atag object with name: 'ruby'
Atag.find_by_name('ruby') #same as above. 

【讨论】:

  • 这很有用,但与我所寻找的不同,因为我需要能够仅在知道键的情况下检索值。您的示例似乎假设知道检索对象的键和值。我通过 :tag 而不是 :id 检索对象的原因是因为我有 :tag 的值而不是 :id (这是我想要得到的)。几乎肯定有更好的方法来实现我正在尝试使用 Active Record 关联来实现的功能,但我现在只是从头开始实现,同时我会因取得进展而感到更加自在和受到启发。
  • 我不太喜欢阅读文档,除了最低限度的文档,但在不久的将来,如果我太卡住了,我会彻底阅读guides.rubyonrails.org/association_basics.html:P
  • @Laser,您是否要让所有 Atag 对象都具有共同的标签名称?就像你做的那样 Atag.where(tag: 'brand') ?那么你可以试试 Atag.find_by(tag: 'brand')
  • 啊,是的,这样干净多了!谢谢:)
  • 您能否编辑答案,使解决方案位于顶部 'Atag.find_by(tag:'brand').id' 或 'Atag.where(tag:'brand').first。身份证?
【解决方案2】:

来自Odin Project 的精彩文档。

要注意的关键是#find 返回实际记录,而#where 返回一个ActiveRecord::Relation,它基本上就像一个数组。

因此,如果您使用#where 查找单个记录,您仍然需要记住进入该“数组”并获取第一条记录,例如User.where(:email => "foo@bar.com")[0]User.where(:email => "foo@bar.com").first.

这让我一直很兴奋......

【讨论】:

    【解决方案3】:

    是的,看起来你想通了。作为参考,您可以使用Atag.where(tag:'brand').first 获取第一个结果,使用Atag.where(tag:'brand').to_a 获取所有匹配结果的数组。

    【讨论】:

      【解决方案4】:

      where 返回 ActiveRecord::Relation 的实例,可以将其视为具有记录作为其成员的 数组。即使结果是单一的,也应该像具有单个元素的数组成员一样访问它

      Atag.where(tag: 'brand')
      

      返回结果数组并访问id,我们应该首先从数组中获取记录,即

      Atag.where(tag: 'brand')[0].id
      

      为了获得所有匹配记录中的id,我们需要使用pluckwherepluck 返回一个被采摘的属性数组。

      Atag.where(tag: 'brand').pluck(:id)
      

      这将只从where 返回的集合中返回一个id 数组。

      find_by 方法查找匹配某些条件的第一条记录。由于find_by 返回记录(不是数组),我们可以这样做:

      Atag.find_by(tag: 'brand').id
      

      PS:没有人提到pluck,这就是我写这个答案的原因。希望对您有所帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-07-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-25
        • 2021-07-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多