嵌入式 javascript,将表单数据发送回应用程序。路由错误

Posted

技术标签:

【中文标题】嵌入式 javascript,将表单数据发送回应用程序。路由错误【英文标题】:Embedded javascript, sending form data back to the application. Routing error 【发布时间】:2020-06-10 06:29:25 【问题描述】:

上下文rails app 中,我使用Vue 创建了一个嵌入式javascript 表单,外部网站shops 应付/粘贴,让他们的网站访问者搜索可用的bike_categories

目标 现在我创建了他们可以复制/过去的表格,我想将数据发送回我的应用程序,这样我就可以在我的自行车管理应用程序中搜索相应shop 的可用bike_categories。

问题/错误信息 尝试将数据发送回我的应用程序时,我收到以下路由错误,即使路由在我的路由文件中也是如此。这是我第一次尝试这样的事情,所以我可能会忽略/遗漏一些东西,但是如果路由匹配,我该如何解决这个问题?

浏览器错误

No route matches [POST] "/en/shops/66/shop_availability"

.....
available routes:

shop_availability_api_v1_shop_path  POST    (/:locale)/api/v1/shops/:id/shop_availability(.:format)   api/v1/shops#shop_availability :format=>:json, :locale=>/en|nl|fr/

控制台错误

Started POST "/en/shops/66/shop_availability" for ::1 at 2020-02-27 09:15:24 +0100

ActionController::RoutingError (No route matches [POST] "/en/shops/66/shop_availability"):

actionpack (5.2.3) lib/action_dispatch/middleware/debug_exceptions.rb:65:in `call'
web-console (3.7.0) lib/web_console/middleware.rb:135:in `call_app'
web-console (3.7.0) lib/web_console/middleware.rb:30:in `block in call'
web-console (3.7.0) lib/web_console/middleware.rb:20:in `catch'
web-console (3.7.0) lib/web_console/middleware.rb:20:in `call'
actionpack (5.2.3) lib/action_dispatch/middleware/show_exceptions.rb:33:in `call'
railties (5.2.3) lib/rails/rack/logger.rb:38:in `call_app'
railties (5.2.3) lib/rails/rack/logger.rb:26:in `block in call'
activesupport (5.2.3) lib/active_support/tagged_logging.rb:71:in `block in tagged'
activesupport (5.2.3) lib/active_support/tagged_logging.rb:28:in `tagged'
activesupport (5.2.3) lib/active_support/tagged_logging.rb:71:in `tagged'
railties (5.2.3) lib/rails/rack/logger.rb:26:in `call'
sprockets-rails (3.2.1) lib/sprockets/rails/quiet_assets.rb:13:in `call'
actionpack (5.2.3) lib/action_dispatch/middleware/remote_ip.rb:81:in `call'
request_store (1.5.0) lib/request_store/middleware.rb:19:in `call'
actionpack (5.2.3) lib/action_dispatch/middleware/request_id.rb:27:in `call'
rack (2.0.7) lib/rack/method_override.rb:22:in `call'
rack (2.0.7) lib/rack/runtime.rb:22:in `call'
activesupport (5.2.3) lib/active_support/cache/strategy/local_cache_middleware.rb:29:in `call'
actionpack (5.2.3) lib/action_dispatch/middleware/executor.rb:14:in `call'
actionpack (5.2.3) lib/action_dispatch/middleware/static.rb:127:in `call'
rack (2.0.7) lib/rack/sendfile.rb:111:in `call'
webpacker (4.0.7) lib/webpacker/dev_server_proxy.rb:29:in `perform_request'
rack-proxy (0.6.5) lib/rack/proxy.rb:57:in `call'
railties (5.2.3) lib/rails/engine.rb:524:in `call'
puma (4.1.0) lib/puma/configuration.rb:228:in `call'
puma (4.1.0) lib/puma/server.rb:664:in `handle_request'
puma (4.1.0) lib/puma/server.rb:467:in `process_client'
puma (4.1.0) lib/puma/server.rb:328:in `block in run'
puma (4.1.0) lib/puma/thread_pool.rb:135:in `block in spawn_thread'

代码

routes.rb

namespace :api, defaults:  format: :json  do
  namespace :v1 do
    resources :shops, only: [:show] do
      get :form_availability , on: :member
      post :shop_availability , on: :member
    end
  end
end

javascript/packs/embed.js

import TurbolinksAdapter from 'vue-turbolinks'
import Vue from 'vue/dist/vue.esm'
import App from '../app.vue'
import store from '../store'
// store.dispatch('loadComments')

const event = (typeof Turbolinks == "object" && Turbolinks.supported) ? "turbolinks:load" : "DOMContentLoaded"

// Vue.use(TurbolinksAdapter)

document.addEventListener(event, () => 

  const el = document.querySelector('#app-reservation-form')
  store.dispatch('loadComments')
  const app = new Vue(
    el,
    store,
    render: h => h(App)
  )

  console.log(app)
)

javascript/vue

<template>
  <form id="app-reservation-form" action="http://localhost:3000/en/shops/66/shop_availability" ref="form">

    <div class="app-reservation-form-item">
      <h6>Arrival</h6>
      <input type="text" id="arrival" name="arrival" class="form-control"/>
    </div>
    <div class="app-reservation-form-item">
      <h6>Departure</h6>
      <input type="text" id="departure" name="departure" class="form-control" />
    </div>
    <div class="app-reservation-form-item">
      <h6></h6>
        <button class="btn search-bikes-button">Search</button>
    </div>
  </form>
</template>

<script>
export default 
  data: function () 
    return 
    
  ,

  methods:
    submit()
    let formData = new formData(this.$refs.form)
    this.$store.dispatch("searchBikes", formData)
    
  

</script>

<style scoped>
p 
  font-size: 2em;
  text-align: center;

</style>

javascrip/store.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const store = new Vuex.Store(
  state: 
    bike_categories:[]
  ,

  mutations: 
    load(state, bike_categories)
      state.bike_categories = bike_categories
    ,
  ,

  actions: 
    //show initial search form on website shop
    async loadComments( commit )
      let booking_url = window.location.href

      fetch(`http://localhost:3000/api/v1/shops/$encodeURIComponent(booking_url)/form_availability/`,
        headers: accept: 'application/json'
      )
      .then(response => response.json())
      .then(data => commit('load', data))
    ,

    //Deal with data coming back from shops website
    async searchBikes(commit, formData)
      let booking_url = window.location.href
      fetch(`http://localhost:3000/api/v1/shops/$encodeURIComponent(booking_url)/shop_availability/`,
        headers: accept: 'application/json',
        method: "post",
        body: formData,
      )
      .then(response => response.json())
      .then(data => console.log(data))
    
  
)



window.store = store

export default store

models/shop.rb

class Shop < ApplicationRecord
def self.by_url(booking_url)
    uri = booking_url.split("?").first
    uri.sub!(/\/$/, '')
    # binding.pry
    where(booking_url: uri)
  end
end

controllers/api/v1/shops_controller.rb

class Api::V1::ShopsController < Api::V1::BaseController
  acts_as_token_authentication_handler_for User, only: [:show]

  def show
    @user = current_user
    if @user.shops.find(params[:id])
      @shop = @user.shops.find(params[:id])
    else
      error
    end
    authorize @shop
  end

  def form_availability
    @shop = Shop.by_url(params[:id]).last
    @bike_categories = @shop.bike_categories
    render "shops/form_availability"
    authorize @shop
  end

  def shop_availability
    binding.pry
    @shop = Shop.by_url(params[:id]).last
  end

end

【问题讨论】:

浏览器控制台有错误吗?我不知道 vue,但看起来主要错误是该表单上的处理程序不起作用,并且该表单只是正常发送而不是作为 ajax 请求。 谢谢 Max,刚刚将我控制台中的日志添加到问题中。按照您的建议,我将在 vue 中寻找与 ajax 请求相关的解决方案。找到解决方案后将在此处发布解决方案。 【参考方案1】:

不敢相信我错过了,我的表单中的路由不包含到正常shops_controller 而不是api/v1shops_controller 的路由。

【讨论】:

以上是关于嵌入式 javascript,将表单数据发送回应用程序。路由错误的主要内容,如果未能解决你的问题,请参考以下文章

javascript 用表单发送数据mvc

JavaScript中 FormData 对象详解

在 volley post 请求中发送表单数据

如何将 Json 数据从 javaScript 发送到 Flask

js提交不起作用不将表单数据发送到php

如何将Javascript数组作为Json与html表单结合发送?