我可以使用AR对象作为哈希键,还是应该使用object_id

时间:2013-01-11 14:12:46

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

由于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]

1 个答案:

答案 0 :(得分:4)

我认为使用哈希是一种在你的情况下组织的好方法。但是,我建议不要使用用户或使用大对象作为散列键,因为它使得散列不可读,并且因为它实际上只是这个唯一对象,它的对象id可以用作键。

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

在您的情况下,这可能不是问题,因为您只需要迭代它。但是如果你想用这个哈希做其他事情,或者你有相同的活动记录数据的不同实例(这在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