Кто-нибудь, пожалуйста, скажите мне, что
send("#{Model.find...}")
есть и делает?
Кто-нибудь, пожалуйста, скажите мне, что
send("#{Model.find...}")
есть и делает?
Ответы:
send
отправляет сообщение экземпляру объекта и его предкам в иерархии классов до тех пор, пока какой-либо метод не отреагирует (поскольку его имя совпадает с первым аргументом).
На практике эти строки эквивалентны:
1.send '+', 2
1.+(2)
1 + 2
Обратите внимание, что send
проверка видимости обходится, поэтому вы также можете вызывать частные методы (полезно для модульного тестирования).
Если перед отправкой действительно нет переменной, это означает, что используется глобальный объект:
send :to_s # "main"
send :class # Object
send - это рубиновый (без рельсов) метод, позволяющий вызывать другой метод по имени.
Из документации
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
Другой пример, похожий на https://stackoverflow.com/a/26193804/1897857 Антонио Джа
если вам нужно прочитать атрибуты объекта.
Например, если у вас есть массив строк, если вы попытаетесь перебрать их и вызвать их на своем объекте, это не сработает.
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
define_method
: apidock.com/ruby/Module/define_method .
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"