2009-07-29 5 views
4

Imaginez que j'ai des objets ressources avec une méthode run, qui exécute le paramètre block sous le verrou détenu pour cette ressource. Par exemple, comme ceci:imbrication dynamique de blocs ruby ​​

r = Resource("/tmp/foo") 
r.run { ... } 

Comment puis-je écrire une méthode rubis qui prend un tableau des ressources et exécute son paramètre de bloc sous le verrou tenu pour toutes les ressources, comme:

def using_resources(*res, &block) 
    r[0].run do; r[1].run do; r[2].run do ... 

    yield; 

    end; end; end; ... 
end 

Est-il possible du tout?

Répondre

8

Il me semble que cela est mieux fait en utilisant récursion

Voici le code:

def using_resources(*res, &block) 

    first_resource = res.shift 

    if res.length > 0 
    first_resource.run do 
     using_resources(*res, &block) 
    end 
    else 
    first_resource.run do 
     block.call 
    end 
    end 

end 

et de l'utiliser comme ceci:

using_resources Resource.new('/tmp'), Resource.new('http://stackoverflow.com') do 
    do_some_processing 
end 

Vous ne dites « , qui prend un éventail de ressources. " Si vous avez un Array déjà et que vous devez l'utiliser, vous pouvez splat l'Array en dehors de l'appel:

using_resources *my_array do 
    do_some_processing 
end 

ou dans la définition de la méthode, ce qui vous permet d'appeler soit avec un Array ou une liste de Resource s:

def using_resources(*res, &block) 
    res = [*res] 
    # rest as above 
end 
6

vous pouvez aussi le faire en utilisant #inject:

def using_resources(*resources, &block) 
    (resources.inject(block){ |inner,resource| proc { resource.run(&inner) } })[] 
end 

Comme vous l'étape Thr Dans le tableau, vous enveloppez l'invocation de chaque Proc de la Proc précédente dans un nouveau Proc, et passez ensuite cela à la ressource suivante. Cela obtient les verrous dans l'ordre inverse (la dernière ressource donnée est le premier déverrouillé), mais cela pourrait changer en utilisant resources.reverse.inject ...

Questions connexes