Rails злой волшебник с JavaScript
Я хочу создать мастера в JS.
steps :first_step,
:second_step
В моем 'controller_step'
def show
case step
when :first_step
@r = R.new
when :second_step
end
render_wizard
end
def update
case step
when :first_step
@r = R.new(r_params)
when :second_step
end
render_wizard @r
end
У меня проблемы после обновления первого шага. Я получаю следующее сообщение об ошибке:
"Отсутствует шаблон controller_step/second_step, application/second_step с {:locale=>[:en],:format =>[:html],: варианты =>[],: обработчики => [: эрб,: строитель,: сырье,:ruby,:coffee,:jbuilder]}. ".
Как я могу принудительно загрузить JS Templete? Я бы загрузил "second_step.js.erb".
Я пытался изменить метод обновления:
respond_to do |format|
format.js { render :js => ( render_wizard @r ) }
end
Конечно, я получаю следующую ошибку:
"AbstractController:: DoubleRenderError in... Controller # update Рендеринг и / или перенаправление вызывались несколько раз в этом действии. Обратите внимание, что вы можете вызывать только перенаправление рендеринга ИЛИ и не более одного раза для каждого действия. Также обратите внимание, что ни перенаправление, ни рендеринг прекратить выполнение действия, поэтому, если вы хотите выйти из действия после перенаправления, вам нужно сделать что-то вроде "redirect_to(...) и вернуть".
Я также пытался изменить код (в обновлении):
respond_to do |format|
format.js { render :js => ( render_wizard @room_types and return ) }
end
Я получаю ту же ошибку ( ... application/second_step с {:locale=>[:en],:format => [: html]....)
PS
С учетом первого шага:
<%= form_for(@r, url: wizard_path, method: :put, remote: true) do |f| %>
....
<%= f.submit "Submit", class: "btn btn-default" %>
<% end %>
Как мне исправить? заранее спасибо
2 ответа
#render_wizard
метод, определенный в Wicked::Controller::Concerns::RenderRedirect
это метод обертки вокруг ActionController::Base#render
метод. Он принимает хэш опций и передает его в обычный контроллер #render
метод.
Это исходный код из библиотеки Wicked:
def render_wizard(resource = nil, options = {})
...
if @skip_to
...
else
render_step wizard_value(step), options
end
end
def render_step(the_step, options = {})
if the_step.nil? || the_step.to_s == Wicked::FINISH_STEP
...
else
render the_step, options #<-- Here
end
end
Ваш код:
respond_to do |format|
format.js { render :js => ( render_wizard @r ) }
end
в основном делает:
respond_to do |format|
format.js { render :js => ( render @r ) }
end
который фактически вызывает метод рендеринга дважды.
Как это ищет .html
шаблон, а не .js.erb
один, попробуйте добавить formats: 'js'
опция для метода render_wizard. Следует добавить ['JS'] к :formats=>[:html]
мы видим в Missing template
сообщение об ошибке.
respond_to do |format|
format.js { render_wizard(@r, formats: 'js') }
end
также убедитесь, что имя файла шаблона соответствует соглашению с rails и начните с _
, (То есть: _second_step.js.erb
)
Насчет двойной ошибки рендера, вы правы. Вы должны вернуться из контроллера #show
или же #update
метод и предотвратить дальнейший код от вызова #render
метод во второй раз. Вы, кажется, уже исправили эту проблему.
EDIT # 1
Похоже, что вы можете вызвать этот метод непосредственно в вашем контроллере..:
def render_step(the_step, options = {})
# Wicked::FINISH_STEP = "wicked_finish"
if the_step.nil? || the_step.to_s == Wicked::FINISH_STEP
redirect_to_finish_wizard options
else
render the_step, options
end
end
я верю the_step
будет имя частичного. Я думаю, что вы должны быть в состоянии позвонить #render_step
метод от вашего контроллера.
Вы можете сделать:
def show
respond_to do |f|
f.js do
case step
when :first_step
@r = R.new
render_step(step) and return
when :second_step
...
end
end
end
end
Я решил таким образом:
в модели r:
validates :x, presence: true
в шаговом контроллере:
...
steps :first_step,
:second_step,
:finish_step
...
def show
case step
when :first_step
@room_types = R.new
end
render_wizard
end
def update
case step
when :view_new_room_type_step
@r = R.create(r_params)
when :view_desc_step
@r = R.find(params[:r][:id])
@r.update(r_params)
end
respond_to do |format|
if !@r.errors.any?
format.js { !next_step?(:finish_step) ? ( render next_wizard_path ) : ( redirect_to_finish_wizard ) }
else
format.js { render wizard_path, r: @r }
end
end
end
private
...
def redirect_to_finish_wizard
redirect_to r_index_path , notice: "Ok"
end
в first_step.js.erb
$("#modal").html("<%= escape_javascript(render 'form_first_step') %>")
в _form_first_step.html.erb:
<% if @r.errors.any? %>
<div class="alert fade in alert-danger alert-dismissable"><button aria-hidden="true" class="close" data-dismiss="alert" type="button">×</button>
<ul>
<% @r.errors.full_messages.each do |msg| %>
<%= content_tag :li, msg, :id => "error_#{msg}" if msg.is_a?(String) %>
<% end %>
</ul>
</div>
<% end %>
<%= form_for(@room_types, url: wizard_path, method: :put, remote: true) do |f| %>
...
<% end %>
во второй форме (второго этапа):
<%= form_for(@room_types, url: wizard_path(:second_step), method: :put, remote: true) do |f| %>
....
<%= f.hidden_field :id %>
<% end %>
Идея: для проверки данных на этапах вы можете использовать https://github.com/gustaflindqvist/jquery-form-validator-rails