web-dev-qa-db-fra.com

hachage ['clé'] à hachage.key in Ruby

J'ai un hash

foo = {'bar'=>'baz'}

Je voudrais appeler foo.bar #=> 'baz'

Ma motivation réécrit une requête Activerecord dans une requête SQL brute (utilisant le modèle # Find_By_SQL). Cela renvoie un hachage avec les valeurs de clause Select en tant que touches. Cependant, mon code existant repose sur l'objet.Method STOT NOTION. Je voudrais faire une réécriture de code minimal. Merci.

Edit: Il semble que Lua a cette fonctionnalité:

point = { x = 10, y = 20 }   -- Create new table
print(point["x"])            -- Prints 10
print(point.x)               -- Has exactly the same meaning as line above
45
user94154
>> require 'ostruct'
=> []
>> foo = {'bar'=>'baz'}
=> {"bar"=>"baz"}
>> foo_obj = OpenStruct.new foo
=> #<OpenStruct bar="baz">
>> foo_obj.bar
=> "baz"
>>
81
Hooopo

Ce que vous cherchez est appelé OpenStruct . Cela fait partie de la bibliothèque standard.

35
Avdi

Une bonne solution:

class Hash
  def method_missing(method, *opts)
    m = method.to_s
    if self.has_key?(m)
      return self[m]
    elsif self.has_key?(m.to_sym)
      return self[m.to_sym]
    end
    super
  end
end

Remarque: cette implémentation n'a qu'un bug connu:

x = { 'test' => 'aValue', :test => 'bar'}
x.test # => 'aValue'

Si vous préférez des recherches de symboles plutôt que des recherches de chaîne, alors échangez les deux "si" condition

22
Gabor Garami

Plutôt que de copier toutes les choses hors du hachage, vous pouvez simplement ajouter un comportement au hasch pour faire des recherches.

Si vous ajoutez cette définition, vous étendez hachage pour gérer toutes les méthodes inconnues telles que les recherches de hachage:

class Hash
  def method_missing(n)
    self[n.to_s]
  end
end

Gardez à l'esprit que cela signifie que vous ne verrez jamais des erreurs si vous appelez la mauvaise méthode sur HASH - vous obtiendrez tout ce que la recherche de hachage correspondante reviendrait.

Vous pouvez réduire considérablement les problèmes de débogage que cela peut causer par uniquement la mise sur un hachage spécifique - ou autant de halés que vous avez besoin:

a={'foo'=>5, 'goo'=>6}
def a.method_missing(n)
   self[n.to_s]
end

L'autre observation est que lorsque method_missing est appelé par le système, cela vous donne un argument Symbol. Mon code le convertit en un String. Si vos clés de hachage ne sont pas des chaînes, ce code ne retournera jamais ces valeurs - si vous touchez des symboles au lieu de cordes, remplacez simplement n pour n.to_s dessus.

6
Dafydd Rees

Il y a quelques pierres précieuses pour cela. Il y a mon joyau récent, hash_dot , et quelques autres pierres précieuses avec des noms similaires que j'ai découverts, alors que j'ai publié le mien sur des rubisgèvres, y compris dot_hash .

Hashdot permet la syntaxe de notation DOT, tout en adressant toujours les préoccupations concernant les nométreurs adressées par @AVDI. Il est plus rapide et plus traversable qu'un objet créé avec openStruct.

require 'hash_dot'
a = {b: {c: {d: 1}}}.to_dot
a.b.c.d => 1

require 'open_struct'
os = OpenStruct.new(a)
os.b => {c: {d: 1}}
os.b.c.d => NoMethodError

Il maintient également le comportement attendu lorsque les non-méthodes sont appelées.

a.non_method => NoMethodError

N'hésitez pas à soumettre des améliorations ou des bugs à Hashdot.

5
steel