ruby-on-rails 在wicked wizard的“show”动作中使用涡轮机?

yv5phkfx  于 2023-03-20  发布在  Ruby
关注(0)|答案(1)|浏览(180)

我对某些人使用turbo流和wicked向导并用“show action”替换dom中的条目的模式感到困惑.在我的场景中,我尝试使用“show”操作替换step_b中存在的嵌套的turboframe“foo”,如下所示:

def show 
  case step

  when :step_a

  when :step_b
 
  when :step_c

  render_wizard
end

在step_B的视图中,我有几个链接,它们都链接回步骤b,但使用不同的参数(我实际上使用API调用在约会选择器中获取和呈现时间,参数表示这些时间的日期)。
<%= link_to "Today", step_b_path(date: 03-14-23) %>
最好将step_b视图中的“foo”涡轮机框替换为3/14/23的所有时间。
<%= link_to "Tomorrow", step_b_path(date: 03-15-23) %>
最好将step_b视图中的“foo”涡轮机框替换为3/15/23的所有时间。
用户可以不断单击这些链接,这将更新约会时间,直到他们最终选择并提交表单中该步骤的约会选择。一旦他们选择了时间并单击“提交”,它将调用update操作并继续执行step_c
我已经看到,如果在step_a中有一个<%= turbo_frame_tag "foo" %>,我可以创建一个step_b.turbo_stream.erb来替换step a中的涡轮机框架,方法如下:
<%= turbo_stream.replace "foo", partial: "partial_path", locals: { bar: @baz } %>
然而,我对此有问题,因为它似乎只有在用户“提交”并调用更新函数时才会被调用。我想要的是当用户点击到step_b的链接时,只调用“显示”操作的turbo帧才会更新。我尝试更新的嵌套turbo帧只存在于step_b中。
但是,当我尝试向show操作添加类似这样的内容时:

when :step_b
  respond_to do |format|
    format.turbo_stream { render turbo_stream: turbo_stream.replace("foo", partial: "partial_path", locals: {bar: params[:baz] 
  })}
end

它会导致与render_wizard的双重渲染冲突。我尝试过这样的if/else语句:

if step == :times
  respond_to do |format|
    format.turbo_stream { render turbo_stream: turbo_stream.replace("foo", partial: "partial_path", locals: {bar: params[:baz] } )}
    format.html { times_path }
  end
else
    render_wizard
end

这根本就不会渲染这个步骤。我还没有找到很多连接wicked和turbostreams的信息。除了step_b之外,我还有很多步骤也使用render_wizard方法,我想知道是否有一种方法可以在不使用大量重构的情况下完成这个步骤?
根据我看过的文档(链接如下),它声明“您需要在操作结束时调用render_wizard以显示正确的视图。”如果turbo_stream视图与render_wizard冲突,听起来这可能是不可能的。
https://www.rubydoc.info/gems/wicked/1.3.4
我看到的所有使用turbostream的例子都倾向于假设您有一个非常典型的rails scaffold设置,其中“create”操作Map到create.turbo_stream.erb,“delete”操作Map到delete.turbo_stream.erb,因此如果控制器看起来与它们不同,就很难准确地找出如何实现相同的解决方案,就像使用wicked向导时一样

编辑:

看到下面的评论从亚历克斯谁能够为我提供一个答案,我的问题。我只是想张贴一个快速总结:
在我的step_B视图中,有类似的内容-

步骤_B.html.erb:

<%= turbo_frame_tag "foo_frame" do %>
  <%= some_variable %>
<%= end %>

<%= link_to "step b", step_b_path(some_variable: "new value of some_variable"), data: { "turbo_stream": true } %>

如上所述,在step_b的视图中,你需要一个data-turbo-stream=true的链接,这将导致链接点击的类型为“text/vnd.turbo-stream.html”,这是一个典型的turbo-stream请求,然后当我们稍后执行respond_to do |format|时,它将告诉rails执行步骤控制器中的format.turbo_stream代码。

步骤_控制器.rb

def show
    respond_to do |format|
      case step
      when :step_a
        # dostuff
        
      when :step_b
        if request.referrer.include? wizard_url
          format.turbo_stream { render turbo_stream: turbo_stream.update("foo_frame", partial: path_to_partial, locals: { some_variable: params[:some_variable] }) }
        end
        
      when :step_c
        # dostuff
      
      format.html { render_wizard }
    end
end

对于我遇到的问题,当从step_a导航到step_B时,它似乎试图将其作为turbostream进行处理,而不呈现step_b的视图。这可能是因为我的案例中有一个嵌套的turbostream。然而,我希望能够定位并替换一个特定的嵌套turbostream。
if request.referrer.include? wizard_url基本上只是说“如果请求来自相同的step_b页面,则在“foo”涡轮帧上执行此涡轮流更新。因此,当从step_a转换到step_b时,此代码不会执行,这解决了上述问题
感谢Alex的所有帮助,并提供了解决方案

mi7gmzs6

mi7gmzs61#

我真的觉得 wicked 只是让你更困惑。你可以很容易地使用turbo frame与你现有的控制器与任何行动和React,你喜欢。
以下是我提出的 wicked 和一些评论的常规控制器替代品:

class OnboardingController < ApplicationController
  include Wicked::Wizard

  steps :one, :two, :complete
  # # or you can do it on your own
  # STEPS = ["one", "two", "complete"].freeze

  # GET wizard_path
  def show
    # NOTE: if you want to add turbo_stream responses here, respond_to
    #       block needs to wrap around the case statement, so that
    #       render_wizard can be wrapped as well.
    respond_to do |format|
      # case params[:id].to_sym
      case step
      when :one
        # NOTE: it's better to have a default value when params[:date] is empty
        #       on initial request.
        #       add links in step :one template with different date params
        #       when you click them, just let the page render again, there is
        #       no need to do anything else.
        @user = current_user
        format.turbo_stream { render turbo_stream: turbo_stream.update("stream_target", "step one content") }
      end
      format.html { render_wizard }
    end

    # # if you just replace `render_wizard` with you own simple logic, you
    # # won't need wicked wizard and won't have to fight it
    # respond_to do |format|
    #   format.html { render params[:id].presence_in(STEPS) || STEPS.first }
    # end
  end

  # PUT wizard_path
  def update
    case step
    when :one
      @user = current_user
      skip_step if @user.save
    end
    render_wizard
    # # or let render_wizard save it for you and go to the next step
    # render_wizard @user

    # # or do it yourself and turn it into a regular controller
    # respond_to do |format|
    #   if @user.save
    #     next_step = STEPS[STEPS.index(params[:id]).next]
    #     format.html { render next_step }
    #   else
    #     format.html { render params[:id] }
    #   end
    # end
  end

  # # and make your own helpers
  # private
  # def step
  #   params[:id].to_sym
  # end
  # helper_method :step
end

您可以添加部分版面,这样就不必在步骤之间重复操作:
x一个一个一个一个x一个一个二个x

更新

<button>提交它嵌套的表单,这只是html。button_to是一个 rails 帮助器,它创建一个表单,该表单带有一个按钮来发出 POST/PUT/PATCH/DELETE 请求,在表单之外使用它。
问题是所有的东西都在一个动作中完成了。当你提交表单时,它会发送一个 TURBO_STREAM 请求,当你重定向时,turbo 会发送另一个 TURBO_STREAM 请求到重定向的URL(这是show动作)。如果你有format.turbo_stream,这就是你会得到的响应,否则,使用format.html
我的意思是,这只是另一个放弃向导的原因,或者至少为turbo_stream请求添加一些新的操作。

def update
  # ...

  # NOTE: redirect with .html extension so that `show` response
  #       would be html instead of turbo_stream
  render_wizard @user, {}, format: :html
end

def show
  respond_to do |format|
    case step
    when :one
      @user = current_user
      format.turbo_stream { render turbo_stream: turbo_stream.update("stream_target", "step one content") }
    when :two
      # NOTE: only accept turbo_stream requests from the current
      #       step. that means when you redirect there is no
      #       turbo_stream format and html format will be used instead
      if request.referrer == wizard_url
        format.turbo_stream { render turbo_stream: turbo_stream.update("stream_target", "step two content") }
      end
    end
    format.html { render_wizard }
  end
end

这可能有助于进一步解释这一点:* 一个月一次 *

相关问题