Alguém pode me dizer o que
send("#{Model.find...}")
é e faz?
Alguém pode me dizer o que
send("#{Model.find...}")
é e faz?
Respostas:
send
envia uma mensagem para uma instância de objeto e seus ancestrais na hierarquia de classes até que algum método reaja (porque seu nome corresponde ao primeiro argumento).
Na prática, essas linhas são equivalentes:
1.send '+', 2
1.+(2)
1 + 2
Observe que send
ignora as verificações de visibilidade, para que você também possa chamar métodos privados (útil para teste de unidade).
Se não houver realmente nenhuma variável antes de enviar, isso significa que o objeto global é usado:
send :to_s # "main"
send :class # Object
send é um método ruby (sem rails) que permite invocar outro método pelo nome.
Da documentação
class Klass
def hello(*args)
"Hello " + args.join(' ')
end
end
k = Klass.new
k.send :hello, "gentle", "readers" #=> "Hello gentle readers"
Um dos recursos mais úteis que eu acho com o método .send é que ele pode chamar o método dinamicamente. Isso pode economizar muito tempo de digitação. Um dos usos mais populares do método .send é atribuir atributos dinamicamente. Por exemplo:
class Car
attr_accessor :make, :model, :year
end
Para atribuir atributos regularmente, seria necessário
c = Car.new
c.make="Honda"
c.model="CRV"
c.year="2014"
Ou usando o método .send:
c.send("make=", "Honda")
c.send("model=", "CRV")
c.send("year=","2014")
Mas tudo pode ser substituído pelo seguinte:
Assumindo que seu aplicativo Rails precisa atribuir atributos à classe do seu carro a partir da entrada do usuário, você pode fazer
c = Car.new()
params.each do |key, value|
c.send("#{key}=", value)
end
Outro exemplo, semelhante ao https://stackoverflow.com/a/26193804/1897857 de Antonio Jha
é se você precisa ler atributos em um objeto.
Por exemplo, se você tiver um array de strings, se tentar iterar por meio deles e chamá-los em seu objeto, não funcionará.
atts = ['name', 'description']
@project = Project.first
atts.each do |a|
puts @project.a
end
# => NoMethodError: undefined method `a'
No entanto, você pode send
inserir as strings no objeto:
atts = ['name', 'description']
@project = Project.first
atts.each do |a|
puts @project.send(a)
end
# => Vandalay Project
# => A very important project
define_method
: apidock.com/ruby/Module/define_method .
send
é outra maneira de chamar um método.
Isso é melhor ilustrado por um exemplo:
o = Object.new
o.send(:to_s) # => "#<Object:0x00005614d7a24fa3>"
# is equivalent to:
o.to_s # => "#<Object:0x00005614d7a24fa3>"
Envie vidas na classe Object .
O benefício dessa abordagem é que você pode passar o método que deseja chamar como um parâmetro. Aqui está um exemplo simples:
def dynamically_call_a_method(name)
o = Object.new
o.send name
end
dynamically_call_a_method(:to_s) # => "#<Object:0x00005614d7a24fa3>"
Você pode passar o método que deseja ser chamado. Neste caso, passamos :to_s
. Isso pode ser muito útil ao fazer a metaprogramação do Ruby, porque nos permite chamar diferentes métodos de acordo com nossos diferentes requisitos.
Outro caso de uso para visualizações:
<%= link_to
send("first_part_of_path_#{some_dynamic_parameters}_end_path",
attr1, attr2), ....
%>
Permitir . você deve escrever uma visão escalonável que trabalha com todos os tipos de objetos com:
render 'your_view_path', object: "my_object"