Может кто-нибудь скажет мне, что
send("#{Model.find...}")
есть и делает?
Может кто-нибудь скажет мне, что
send("#{Model.find...}")
есть и делает?
send
отправляет сообщение экземпляру объекта и его предкам в иерархии классов до тех пор, пока не будет реагировать какой-либо метод (поскольку его имя соответствует первому аргументу).
Практически говоря, эти строки эквивалентны:
1.send '+', 2
1.+(2)
1 + 2
Обратите внимание, что send
обходит проверки видимости, так что вы можете также вызвать частные методы (полезно для модульного тестирования).
Если перед отправкой действительно нет переменной, это означает, что используется глобальный объект:
send :to_s # "main"
send :class # Object
send - это метод ruby (без рельсов), позволяющий вызывать другой метод по имени.
Из документации
class Klass
def hello(*args)
"Hello " + args.join(' ')
end
end
k = Klass.new
k.send :hello, "gentle", "readers" #=> "Hello gentle readers"
Одна из наиболее полезных функций, которые, как мне кажется, с помощью метода .send заключается в том, что она может динамически вызывать метод. Это может сэкономить вам много набрав. Одним из самых популярных способов использования .send является динамическое назначение атрибутов. Например:
class Car
attr_accessor :make, :model, :year
end
Чтобы регулярно назначать атрибуты, нужно
c = Car.new
c.make="Honda"
c.model="CRV"
c.year="2014"
Или используя метод .send:
c.send("make=", "Honda")
c.send("model=", "CRV")
c.send("year=","2014")
Но все это можно заменить следующим:
Предполагая, что вашему Rails-приложению необходимо назначить атрибуты вашему классу автомобилей с пользовательского ввода, вы можете сделать
c = Car.new()
params.each do |key, value|
c.send("#{key}=", value)
end
Другой пример, аналогичный Антонио Jha fooobar.com/questions/98516/...
если вам нужно прочитать атрибуты для объекта.
Например, если у вас есть массив строк, если вы попытаетесь выполнить итерацию через них и вызвать их на свой объект, это не сработает.
atts = ['name', 'description']
@project = Project.first
atts.each do |a|
puts @project.a
end
# => NoMethodError: undefined method `a'
Однако вы можете send
строки для объекта:
atts = ['name', 'description']
@project = Project.first
atts.each do |a|
puts @project.send(a)
end
# => Vandalay Project
# => A very important project
send
- это еще один способ вызова метода.
Это лучше всего иллюстрируется на примере:
o = Object.new
o.send(:to_s) # => "#<Object:0x00005614d7a24fa3>"
# is equivalent to:
o.to_s # => "#<Object:0x00005614d7a24fa3>"
Отправляйте жизни в классе Object.
Преимущество этого подхода заключается в том, что вы можете передать метод, который вы хотите вызвать, в качестве параметра. Вот простой пример:
def dynamically_call_a_method(name)
o = Object.new
o.send name
end
dynamically_call_a_method(:to_s) # => "#<Object:0x00005614d7a24fa3>"
Вы можете передать метод, который хотите вызвать. В этом случае мы перешли в :to_s
. Это может быть очень удобно при выполнении метапрограммирования ruby, потому что это позволяет нам вызывать различные методы в соответствии с нашими различными требованиями.
Другой вариант использования для просмотров:
<%= link_to
send("first_part_of_path_#{some_dynamic_parameters}_end_path",
attr1, attr2), ....
%>
Разрешить. вам написать масштабируемое представление, которое работает со всеми видами объектов с:
render 'your_view_path', object: "my_object"