ruby Rails 7 respond_do错误ActionController::UnknownFormat

lg40wkob  于 2023-08-04  发布在  Ruby
关注(0)|答案(1)|浏览(111)

我尝试在rails7中做一个 AJAX 请求,当表单提交时(当按钮被按下时),它呈现JavaScript
在我的股票控制器中,我有:

class StocksController < ApplicationController

    def search
        if params[:stock].present?
            @stock = Stock.new_lookup(params[:stock])
           if @stock
                 respond_to do |format|
                     format.js {render partial: 'users/result'}
                end
           else
                flash[:alert] = "Please enter a valid symbol to search"
                redirect_to my_portfolio_path
           end
        else
            flash[:alert] = "Please enter a symbol to search"
            redirect_to my_portfolio_path
        end

    end

end

字符串
我的表格我有:

<div class="search-area">
<h3>Search Stocks</h3>
<%= form_tag search_stock_path, method: :get, remote: true do %>
    <div class="form-group row">
        <div class="col-sm-9 noRightPad">
            <%= text_field_tag :stock, params[:stock], placeholder: "Stock ticker symbol", 
            autofocus: true, class: "form-control form-control-lg" %>
        </div>
        <div class="col-sm-3 noLeftPad">
            <%= button_tag type: :submit, class: "btn btn-success" do %>
                <%= fa_icon "search 2x" %>
            <% end %>
        </div>
    </div>
<% end %>


错误消息:

的数据
谢谢你的时间。

更新控制器已更新

class StocksController < ApplicationController
respond_to :js

def search
    if params[:stock].present?
        @stock = Stock.new_lookup(params[:stock])
       if @stock
        respond_to do |format|
            format.turbo_stream do
              render turbo_stream: turbo_stream.update(
                "results",
                partial: "users/result" # render any partial and remove js code.
              )
            end
          end
       else
            flash[:alert] = "Please enter a valid symbol to search"
            redirect_to my_portfolio_path
       end
    else
        flash[:alert] = "Please enter a symbol to search"
        redirect_to my_portfolio_path
    end

end


结束
表单标记

<%= form_tag search_stock_path, method: :get, data: {turbo_stream: true}, remote: true do %>


我已经研究了406不可接受的错误在控制台,但它说要添加respond_,我已经这样做了,仍然是同样的问题

to94eoyn

to94eoyn1#

我会在这里揭开魔法的神秘面纱,我已经看到这个问题出现了很多次。
设置:

rails new rails_formats -c tailwind
cd rails_formats
bin/rails g scaffold stock name
bin/rails db:migrate
open http://localhost:3000/stocks/new
bin/dev

字符串

头部

Rails将这些抽象出来,所以你不必处理这些。有两个标题你只需要知道:

Content-Type

这是您发送到服务器的请求,以及您发送回的响应。例如,您可以发送多部分表单数据并获得JSON作为响应 (当您需要将图像上传到API服务器时)

Accept

这就是你想要得到的回应。这是一个决定什么格式块轨道将运行。

Mime types

这就是进入 AcceptContent-Type 头文件的内容。Rails 有一个类来处理它:
https://api.rubyonrails.org/classes/Mime/Type.html

Mime::Type.register "text/vnd.hyper-stream.html", :hyper
# if you send this in Accept ^ header, then run this ^ format block

ActiveSupport.on_load(:action_controller) do
  ActionController::Renderers.add :hyper do |html, options|
    # set response type if rendering ^ `render hyper: ..`
    self.content_type = Mime[:hyper] if media_type.nil?
    html
  end
end

# now you have your own format
format.hyper { render hyper: ... }

控制器和窗体

你知道要使用什么标题,这里是如何使用它们:

<!-- app/views/stocks/_form.html.erb -->

<!-- disable Turbo for now so it doesn't interfere -->
<script type="module"> Turbo.session.drive = false </script>

<!-- make your own remote form -->
<div id="remote_response"></div>
<%= form_with model: stock, html: {onsubmit: "remote(event)"} do |form| %>
  <%= form.submit %>
<% end %>

  • 在真实的应用中使用事件监听器和事件委托。
<script charset="utf-8">
  function remote(event) {
    event.preventDefault();
    const form = event.target;

    fetch(form.action, {
      // headers: { "Accept": "text/html" },
      // headers: { "Accept": "text/vnd.turbo-stream.html" },
      headers: { "Accept": "application/json" },
      method: form.method,
      body: new FormData(form),
    })
      .then(response => response.text())
      .then(text => {
        document.querySelector("#remote_response").innerHTML = text;
      })
  }
</script>
def create
  puts "# CONTENT TYPE  | #{request.content_type}"  # what you sent
  puts "# ACCEPT        | #{request.accept}"        # what you want

  # Change Accept header in `fetch` to choose which format block to run
  respond_to do |format|
    format.html         { render html:         "Responded with html" }
    format.json         { render json:         "Responded with json" }
    format.js           { render js:           "console.log('railsujs')" }
    format.turbo_stream { render turbo_stream: "Responded with turbo stream" }
  end

  puts "# RESPONSE TYPE | #{response.content_type}" # what you get
end

{remote:true}

remote: true(如果使用form_with,则为local: false)将把data-remote="true"添加到表单标记中,仅此而已。前端的东西必须知道如何处理它。这就是 RailsUJS,它在 rails 7 中被Turbo取代。

$ bin/importmap pin @rails/ujs


选择Turbo或RailsUJS:

// app/javascript/application.js

// import "@hotwired/turbo-rails"
// import "controllers"

import Rails from "@rails/ujs";
Rails.start();
<%= form_with model: stock, local: false do |form| %>
...

现在 RailsUJS 将执行我们对remote()函数所做的操作,并将Accept设置为text/javascript,以便format.js块运行。它还将处理响应并执行代码。

Turbo

流和帧和广播需要一点时间来让你的头脑围绕它。从turbo_stream开始,我发现一开始更容易理解。
无需设置,所有表单都以TURBO_STREAM格式(又名"Accept": "text/vnd.turbo-stream.html, text/html, application/xhtml+xml")“远程”提交。这意味着您可以使用format.htmlformat.turbo_stream进行响应。

respond_to do |format|
  format.turbo_stream do
    render turbo_stream: turbo_stream.update(
      "id_of_the_element_to_update",
      partial: "users/result" # render any partial and remove js code.
    )
  end
end

更新

  • 获取 * 流**

data-turbo-stream="true"添加到带有method: :get和链接的表单。

form_tag "/", method: :get, data: {turbo_stream: true} do

  • https:turbo.hotwired.dev/handbook/streams#streaming-from-http-responses*
    Bootstrap

你不能导入“bootstrap”,除非你有一个pin:

import * as bootstrap from "bootstrap"
//                          ^^^^^^^^^
// browser doesn't know how to get that


添加一个大头针(并从cdn获取样式):

bin/importmap pin bootstrap


如果importmaps增加了太多麻烦,请使用cssbundling-rails。Rails内置了以下功能:

rails new my_app -c bootstrap


但是关于如何在rails 7中安装bootstrap还有很多其他的答案。

调试

使用JavaScript,你必须查看浏览器控制台。

相关问题