Я нашел обходной путь для этого, но я не уверен, почему он работает таким образом:
Мне пришлось добавить удаленную команду с прослушивателем tabchange на tabView.
<p:remoteCommand name="onTabChangeProcess" process="tView, @this"/>
<p:tabView activeIndex="#{deleteMe.activeIndex}" id="tView" onTabChange="onTabChangeProcess()">
<p:ajax event="tabChange" listener="#{deleteMe.onTabChange}" update="tView" process="tView"/>
Это заставило форму работать как ожидалось.
Блоки являются основной частью Ruby. Они разделяются либо do | arg0, arg1 | ... конец
или {| arg0, arg1, arg2 | ...}
.
Они позволяют указать обратный вызов для передачи методу.
Этот обратный вызов может быть вызван двумя способами - либо путем захвата
это, указав последний аргумент с префиксом &
, или
используя ключевое слово yield
:
irb> def meth_captures(arg, &block)
block.call( arg, 0 ) + block.call( arg.reverse , 1 )
end
#=> nil
irb> meth_captures('pony') do |word, num|
puts "in callback! word = #{word.inspect}, num = #{num.inspect}"
word + num.to_s
end
in callback! word = "pony" num = 0
in callback! word = "ynop" num = 1
#=> "pony0ynop1"
irb> def meth_yields(arg)
yield(arg, 0) + yield(arg.upcase, 1)
end
#=> nil
irb> meth_yields('frog') do |word, num|
puts "in callback! word = #{word.inspect}, num = #{num.inspect}"
word + num.to_s
end
in callback! word = "frog", num = 0
in callback! word = "FROG", num = 1
#=> "frog0FROG1"
Обратите внимание, что наш обратный вызов был одинаковым в каждом случае - мы можем удалить
повторение, сохраняя наш обратный вызов в объекте, а затем передавая его каждому
метод. Это можно сделать с помощью лямбда
для захвата обратного вызова в объекте,
а затем передается методу, добавляя к нему префикс &
.
irb> callback = lambda do |word, num|
puts "in callback! word = #{word.inspect}, num = #{num.inspect}"
word + num.to_s
end
#=> #<Proc:0x0052e3d8@(irb):22>
irb> meth_captures('unicorn', &callback)
in callback! word = "unicorn", num = 0
in callback! word = "nrocinu", num = 1
#=> "unicorn0nrocinu1"
irb> meth_yields('plate', &callback)
in callback! word = "plate", num = 0
in callback! word = "PLATE", num = 1
#=> "plate0PLATE1"
Важно понимать различные варианты использования &
здесь в качестве префикса к последнему аргументу функции
Если вы посмотрите вокруг, блоки используются повсюду, особенно в итераторах, например Массив # каждый
.
Это работает так:
@ cart.items.empty?
кодирование
: id => "cart"
Становится атрибутами в соответствии с соглашением, которое вы может удалить {} в хэше параметров, если он последний.
блок равен
render (: partial => "cart",: object => @cart)
поэтому внутри функции, если тележка пусто, он добавит атрибут style со значением "display: none"
Затем будет создан тег div, заполненный содержимым результата выполнения блока, который будет результатом визуализации корзины частичного просмотра с содержимым @cart.
Re attributes = {}
, это просто аргумент метода со значением по умолчанию. Поэтому, если вы вызываете hidden_div_if (любой)
, то есть передавая только первый аргумент, атрибуты
по умолчанию будут иметь пустой хэш.
Это полезно, поскольку упрощает настройку Атрибуты ["стиль"]
позже, поскольку атрибуты
не нужно сначала инициализировать хешем. (Что, тем не менее, можно сделать просто как (attributes || = {}) ["style"] =…
.)
& block
лишь немного сложнее.
Методы Ruby могут взять последний аргумент, который является блоком, используя специальный синтаксис метод (args) {| block_args | block_code}
. & block
в основном захватывает этот блок в переменную block
как объект Proc
. Таким образом, block
- это просто переменная, указывающая на анонимную процедуру здесь.
Когда вызывается более поздний content_tag
, и & block
передается в качестве последнего аргумента, он расширен в блок, как если бы вызов действительно был content_tag (…) {блок изначально был передан в hidden_if_div}
Так что, возможно, я действительно сбивал с толку. Вам следует найти в Google "аргументы по умолчанию для рубина" и "блоки рубина".
например, если бы вызов действительно был content_tag (…) {блок изначально был передан в hidden_if_div}
Так что, возможно, я действительно запутался здесь. Вам следует найти в Google "аргументы по умолчанию для рубина" и "блоки рубина".
например, если бы вызов действительно был content_tag (…) {блок изначально был передан в hidden_if_div}
Так что, возможно, я действительно запутался здесь. Вам следует найти в Google "аргументы по умолчанию для рубина" и "блоки рубина".
& block
- это способ отправки фрагмента кода Ruby в метод и последующей оценки этого кода в рамках этого метода. В приведенном выше примере кода это означает, что частично именованная корзина будет отображаться в div. Я думаю, что термин закрытие используется для этого в информатике.
Итак, в вашем примере & block
:
<%= render(:partial => "cart", :object => @cart) %>
Хорошее прочтение и объяснение блоков, процессов и lamdas можно найти в блоге Роберта Сосински .
Ruby реализует блоки, процедуры и лямбда-выражения, которые в компьютерном сообществе называются замыканиями. Если вы начинаете изучать Ruby, вы быстро столкнетесь с таким кодом.
a = ["dog", "cat", "bird"]
a.alter_each! do |n, i|
"#{i}_#{n}"
end
Так что здесь происходит?
Мы начинаем с набора имён животных и вызываем alter_each! метод передачи блока. В этом блоке кода мы можем указать, как мы хотим изменить каждый элемент. В нашем примере к каждому имени животного будет добавлена его позиция в массиве. Поскольку alter_each! метод выполняет итерацию по каждому элементу, он выполнит наш блок, передав значение и индекс. Наш блок захватывает эти параметры, добавляет к имени префикс индекса и возвращает результат. Теперь давайте посмотрим на alter_each! метод.
Обратите внимание, что метод не определяет никаких параметров, потому что блок автоматически назначается ключевому слову yield. yield вызывается как функция, передающая значение и индекс каждого элемента в массиве и переопределяющая исходное значение.
class Array
def alter_each!
self.each_with_index do |n, i|
self[i] = yield(n,i)
end
end
end
Что делать, если вам нужно передать параметр этому методу?
Вы можете изменить сигнатуру метода, чтобы принимать параметры и, наконец, перехватить блок с параметром, начинающимся с амперсанда. В приведенном ниже примере наш блок будет захвачен с параметром & block, который мы вызовем методом call. Это вместо использования yield
class Array
def modify_each!(add_one = true, &block)
self.each_with_index do |n, i|
j = (add_one) ? (i + 1) : i
self[i] = block.call(n,j)
end
end
end
Блоки, процедуры и лямбда-выражения (называемые замыканиями в информатике) являются одними из самых мощных аспектов Ruby, а также одним из наиболее неправильно понимаемых. Вероятно, это связано с тем, что Ruby обрабатывает замыкания довольно уникальным образом. Все усложняется тем, что в Ruby есть четыре различных способа использования замыканий, каждый из которых немного отличается, а иногда и бессмыслен. Есть довольно много сайтов с очень хорошей информацией о том, как закрытие работает в Ruby. Но мне еще предстоит найти хорошее, исчерпывающее руководство.
class Array
def iterate!(&code)
self.each_with_index do |n, i|
self[i] = code.call(n)
end
end
end
array = [1, 2, 3, 4]
array.iterate! do |n|
n ** 2
end
Процедуры, AKA, Procs
Блоки очень удобны и синтаксически просты, однако мы можем захотеть иметь много разных блоков в нашем распоряжении и использовать их несколько раз. Таким образом, повторное прохождение одного и того же блока снова и снова потребовало бы от нас повторения. Однако, поскольку Ruby полностью объектно-ориентирован, с этим можно легко справиться, сохранив повторно используемый код как сам объект. Этот повторно используемый код называется Proc (сокращение от «процедура»).Единственная разница между блоками и процедурами заключается в том, что блок - это процедура, которую нельзя сохранить, и поэтому она является одноразовым решением. Работая с Procs, мы можем начать делать следующее:
class Array
def iterate!(code)
self.each_with_index do |n, i|
self[i] = code.call(n)
end
end
end
array_1 = [1, 2, 3, 4]
array_2 = [2, 3, 4, 5]
square = Proc.new do |n|
n ** 2
end
Lambdas
До сих пор вы использовали Procs двумя способами, передавая их напрямую как атрибут и сохраняя их как переменную. Эти процедуры очень похожи на то, что другие языки называют анонимными функциями или лямбдами. Чтобы сделать вещи более интересными, лямбды также доступны в Ruby. Взгляните:
class Array
def iterate!(code)
self.each_with_index do |n, i|
self[i] = code.call(n)
end
end
end
array = [1, 2, 3, 4]
array.iterate!(lambda { |n| n ** 2 })
puts array.inspect
Блоки
Самый распространенный, простой и, возможно, самый «Ruby-подобный» способ использования замыканий в Ruby - это блоки. У них есть следующий знакомый синтаксис:
array = [1, 2, 3, 4]
array.collect! do |n|
n ** 2
end
puts array.inspect
# => [1, 4, 9, 16]