【问题标题】:Send JSON Response Data to a Custom Widget - Ruby Rails 5.2将 JSON 响应数据发送到自定义小部件 - Ruby Rails 5.2
【发布时间】:2021-11-06 19:51:50
【问题描述】:

我正在构建一个客户可以在其第三方网站上显示的小部件。该小部件接受消费者关于他们正在寻找什么样的房子的输入。提交时,小部件在端点 API(我的数据库)内的搜索模型上发出 POST 请求。然后我想在客户的网站上显示搜索的结果。

到目前为止,我已成功在第三方网站上发布了搜索表单,并在提交时创建了一个新的搜索对象,搜索结果已准备好在我的网站上查看。但我希望将搜索结果发送回客户的网站。

在客户的网站上,他们有一个如下所示的 js 脚本:

<script type="text/javascript" src="http://localhost:3000/searchapis/search_form.js"></script>

我的路线.rb:

get 'searchapis/show'
get '/searchapis/:template', to: "searchapis#show"
post 'search/create', to: "searches#create"

我创建了一个如下所示的 searchapi 控制器:

class SearchapisController < ApplicationController
  protect_from_forgery :except => :show
  
  def show
    @search = Search.new
    
    respond_to do |format|
      format.html { render params[:template], layout: 'searchapis' }
      format.js   { render js: js_constructor }
    end
  end
  
  private
    def js_constructor
      content = render_to_string(params[:template], layout: false)
      "document.write(#{content.to_json})"
    end
end

我创建了一个如下所示的search_form.html.erb 视图:

<%= bootstrap_form_for @search, :html => {}, :url => create_search_url(@search), remote: true do |form| %>

<%=form.select :beds, (select_options), {prompt: "Min # of Bedrooms", hide_label: true}, {class: "form-control form-control-sm"}%>

<%=form.select :max_price, (100000..2000000).step(10000).map{|x| number_to_currency(x, precision: 0)}, {hide_label: true, prompt: "Select Max Price"}, {class: "form-control form-control-sm", id: "sale_price"}%>

<input type="submit" name="commit" value="SEARCH" class="btn btn-danger" data-disable-with="Finding Schools...">

最后是 searchs_controller.rb:

class SearchesController < ApplicationController
  skip_before_action :verify_authenticity_token
  before_action :set_search, only: [:show, :edit, :update, :destroy]
  before_action :require_admin, only: [:index, :destroy]

  def create
      @search = Search.new(search_params)

      respond_to do |format|
        if @search.save

          format.html { redirect_to @search, notice: 'Search was successfully created.'}
          results = @search.listings
          p results #this is what I want to send to the third party site
          format.json { render json: results.to_json, remote: true, notice: "Search results below"}
        end
      end
  end
end

现在表单已显示,提交时会创建一个新搜索,但我不确定如何继续,因此可以通过 JSON 响应将搜索结果发送到第三方网站。

我想我需要为客户的网站生成一个额外的 javascript src =(&lt;script type="text/javascript" src="http://localhost:3000/searchapis/api_search_results.js"&gt;&lt;/script&gt;) 链接到一个新的 api_search_results 页面,我需要rails g migration AddNewSttributeToSearch api:boolean 这样我才能捕获一个 api 搜索在控制器中并路由到新的 api_search_results 页面。然后,当消费者在第三方网站上点击提交时,第二个 javascript src 会显示结果,但我认为也许有更好的方法。有什么想法吗?

【问题讨论】:

  • 为什么不使用 iframe?在 iframe 中呈现该表单,您将完全控制其中的内容。
  • 感谢@razvans 的评论,我会试一试。但是一旦 iframe 就位,消费者输入他们的数据,并将数据传递到我的数据库,进行搜索并准备好结果,我该如何在消费者的屏幕上显示这些结果?理论上,客户的网站上可能有数百人,因此结果必须与每个查询匹配。

标签: javascript widget ruby-on-rails-5 jsonresponse


【解决方案1】:

我终于明白了。在具有表单的同一个视图中,我创建了一个表格来保存数据和一些 javascript 来显示 json 响应。新操作“search_results”处理接受表单数据、创建搜索和返回 json。

更新路线:

  get 'searchapis/search_results'
  post 'searchapis/search_results'
  get 'searchapis/show'
  get '/searchapis/:template', to: "searchapis#show"

更新了 search_form 视图:

<%= bootstrap_form_for @search, :html => {id: "search_api"}, :url => searchapis_search_results_url(@search), remote: true do |form| %>

<%=form.select :beds, (select_options), {prompt: "Min # of Bedrooms", hide_label: true}, {class: "form-control form-control-sm"}%>

<%=form.select :max_price, (100000..2000000).step(10000).map{|x| number_to_currency(x, precision: 0)}, {hide_label: true, prompt: "Select Max Price"}, {class: "form-control form-control-sm", id: "sale_price"}%>

<input type="submit" name="commit" value="SEARCH" class="btn btn-danger" data-disable-with="Finding Schools...">

<% end %>

更新后的控制器显示表单,接受表单数据,创建搜索,并通过 json 返回结果:

class SearchapisController < ApplicationController
  protect_from_forgery :except => [:show, :search_results]
  
  def show
      @search = Search.new
      @search.api_search = true
    
    respond_to do |format|
      format.html { render params[:template], layout: 'searchapis' }
      format.js   { render js: js_constructor }
    end
  end
  
  def search_results
    @search = Search.new(search_params)
    @search.save
    @results = @search.listings
    response = @results.map{|x| [x[0].name,x[0].address,x[0].city,x[0].performance_stats.find_by(year: "1819").rating,x[1].count]}
    render json: response.to_json
  end

  
  private
    def js_constructor
      content = render_to_string(params[:template], layout: false)
      "document.write(#{content.to_json})"
    end
    
    #note, I had to copy search_params from the SearchesController, so perhaps the search_results method could be added to the Searches Controller to avoid this

    def search_params
      params.require(:search).permit(:name, :address, :city)
    end
end

SearchesController 创建动作:

respond_to do |format|
      if @search.save
        if @search.api_search == true
          return
        end
       *additional routing*
      end
end

search_form 视图现在如下所示:

<style>
  #hide_table {
     display:none
  }
</style>

<%= bootstrap_form_for @search, :html => {id: "search_api"}, :url => searchapis_search_results_url(@search), remote: true do |form| %>

<%=form.select :beds, (select_options), {prompt: "Min # of Bedrooms", hide_label: true}, {class: "form-control form-control-sm"}%>

<%=form.select :max_price, (100000..2000000).step(10000).map{|x| number_to_currency(x, precision: 0)}, {hide_label: true, prompt: "Select Max Price"}, {class: "form-control form-control-sm", id: "sale_price"}%>

<input type="submit" name="commit" value="SEARCH" class="btn btn-danger" data-disable-with="Finding Schools...">

<% end %>



<div class="container-fluid">
    <div class="row">
        <div class="col">
            <div id='hide_table'>
                <table class="table table-sm" id="schools_api">
                    <thead>
                        <tr>
                            <th>Name</th>
                            <th>Address</th>
                            <th>City</th>
                            <th>Score</th>
                            <th># Homes</th>
                        </tr>
                    </thead>
                    <tbody>
                    </tbody>
                </table>
            </div>
        </div>
    </div>
</div>

<script>
document.body.addEventListener("ajax:success", (event) => {
        var response = event.detail[0];
        $("#schools_api tbody tr").remove(); 
        $('#hide_table').css("display","block");
        $.each(response, function(i, item) {
            $('<tr>').html("<td>" + item[0] + "</td><td>" + item[1] + "</td><td>" + item[2] + "</td><td>" + item[3] + "</td><td>" + item[4] + "</td>").appendTo('#schools_api');
        });
    });

</script>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-11-26
    • 2018-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-09
    • 2016-07-27
    相关资源
    最近更新 更多