Хтось може сказати мені що
send("#{Model.find...}")
є і робить?
Хтось може сказати мені що
send("#{Model.find...}")
є і робить?
Відповіді:
send
надсилає повідомлення екземпляру об'єкта та його предкам в ієрархії класів, поки якийсь метод не зреагує (оскільки його ім'я відповідає першому аргументу).
Практично кажучи, ці рядки еквівалентні:
1.send '+', 2
1.+(2)
1 + 2
Зверніть увагу, що send
обходить перевірку видимості, щоб ви могли також викликати приватні методи (корисно для модульного тестування).
Якщо перед відправленням дійсно немає змінної, це означає, що використовується глобальний об'єкт:
send :to_s # "main"
send :class # Object
надіслати - це рубіновий (без рейок) метод, що дозволяє викликати інший метод за іменем.
З документації
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"