【问题标题】:Can I use AR object as hash key or should I use object_id instead我可以使用 AR 对象作为哈希键还是应该使用 object_id
【发布时间】:2013-01-11 14:12:45
【问题描述】:

因为 Ruby 非常棒,所以可以使用任何对象作为键

document = Document.find 1
o = Hash.new
o[1] = true
o[:coool] = 'it is'
o[document] = true
# an it works

o[document]
#=> true

但仅仅因为它是可能的并不意味着是好的做法

但是我有一种情况,在我的控制器中我需要设置类似的东西,所以我可以在视图中循环遍历它

#controller
@users_with_things = Hash.new
Things.accessible_by(some_curent_user_logic).each do |thing|
  @user_with_things[thing.user] ||= Array.new
  @user_with_things[thing.user] <<  thing.id
end 

#view
- @users_with_things.each do |user, thing_ids|
  %input{type: :checkbox, name: "blank[user_#{user.id}]", value: 1, class: "select_groups", :'data-resource-ids' => "[#{thing_ids.join(',')}]", :'data-user-type' => user.type }

之所以要这样做,是因为我不想从我的角度调用User.find_by_id(想让它变得干净)

#controller
@users_with_things = Hash.new
Things.accessible_by(some_curent_user_logic).each do |thing|
  @user_with_things[thing.user.id] ||= Array.new
  @user_with_things[thing.user.id] <<  thing.id
end 

#view
- @users_with_things.each do |user_id, thing_ids|
  - user = User.find user_id
  %input{type: :checkbox, name: "blank[user_#{user.id}]", value: 1, class: "select_groups", :'data-resource-ids' => "[#{thing_ids.join(',')}]", :'data-user-type' => user.type }

所以我的第一个问题是:在这种情况下可以使用 ActiveRecord 对象作为哈希键吗

我可以想象几种可能出错的场景(会话、模型中的对象更改等),但这只是为了在视图中呈现

另类!

所以这是一种方法,另一种可能是这样

#controller
@users_with_things = Hash.new
Things.accessible_by(some_curent_user_logic).each do |thing|
  @user_with_things[thing.user.object_id] ||= Array.new
  @user_with_things[thing.user.object_id] <<  thing.id
end 

#view
- @users_with_things.each do |user_object_id, thing_ids|
  - user = ObjectSpace._id2ref(user_object_id)  #this will find user object from object_id
  %input{type: :checkbox, name: "blank[user_#{user.id}]", value: 1, class: "select_groups", :'data-resource-ids' => "[#{thing_ids.join(',')}]"", :'data-user-type' => user.type }    

...更重要的是,铁杆。但是,如果由于某种原因 hash[ARobject] = :something 会因某种原因创建大内存集群,那就是这样了

问题 2:这样做是个好主意吗?


要完整,还有另一种选择,那就是

# ...
@user_with_thing[ [thing.user.id, thing.user.type] ] << thing_id
# ...

所以基本上数组对象将是关键

@user_with_thing[ [1, 'Admin'] ] 
#=> [1,2,3]

【问题讨论】:

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


    【解决方案1】:

    我认为使用哈希是根据您的情况进行组织的好方法。但是,我建议不要使用用户或将对象大作为散列键,因为它会使您的散列不可读,而且实际上只有具有对象 ID 的唯一对象可以用作键。

    o = Object.new
    h = { o => 'something' }
    h[Object.new] #=> nil
    

    在您的情况下,这可能不是问题,因为您只需要迭代它。但是,如果您想用该哈希做其他事情,或者您有相同 Active Record 数据的不同实例(这在 Rails 应用程序中很常见,除非您真正注意什么何时加载)。除此之外,我认为最好遵守广泛使用的约定,使用简单对象(字符串、符号)作为哈希键,以使您的代码具有可读性和可维护性。

    也许最好保留一个二维哈希,如下所示:

    @users_with_things = Things.accessible_by(some_curent_user_logic).inject({}) do |a, thing|
      user_id = thing.user.id
      a[user_id] ||= { :user => thing.user, :things => [] }
      a[user_id][:thing] << thing
      a
    end
    

    然后你可以像这样在你的视图中迭代@users_with_things

    @users_with_things.each do |user_id, values|
      # values[:user] is the user, values[:things] the array of things
    

    【讨论】:

    • hmmm,你的例子实际上是个好主意(+1 & ✔),我也同意我的解决方案是“危险的”,如果我做的更多,我不会在逻辑上使用它只是迭代:)
    猜你喜欢
    • 2016-10-04
    • 1970-01-01
    • 1970-01-01
    • 2011-03-29
    • 2021-07-19
    • 2011-08-01
    • 2016-04-10
    • 2010-11-03
    • 1970-01-01
    相关资源
    最近更新 更多