将 JSON 响应数据发送到自定义小部件 - Ruby Rails 5.2
Send JSON Response Data to a Custom Widget - Ruby Rails 5.2
我正在构建一个客户可以在其第三方网站上显示的小部件。该小部件接受消费者关于他们正在寻找什么样的房子的输入。提交时,小部件对端点 API(我的数据库)内的搜索模型发出 POST 请求。然后我想在客户的网站上显示搜索结果。
到目前为止,我已经在第三方网站上成功发布了搜索表单,并在提交时创建了一个新的搜索对象,并且可以在我的网站上查看搜索结果。但我希望将搜索结果发送回客户的网站。
在客户的网站上,他们有一个如下所示的 js 脚本:
<script type="text/javascript" src="http://localhost:3000/searchapis/search_form.js"></script>
我的routes.rb:
get 'searchapis/show'
get '/searchapis/:template', to: "searchapis#show"
post 'search/create', to: "searches#create"
我创建了一个搜索api控制器,如下所示:
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...">
最后 searches_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 =(<script type="text/javascript" src="http://localhost:3000/searchapis/api_search_results.js"></script>
) 链接到一个新的 api_search_results 页面,我会需要 rails g migration AddNewSttributeToSearch api:boolean
以便我可以在控制器中进行 api 搜索并路由到新的 api_search_results 页面。然后,当消费者在第三方网站上点击提交时,第二个 javascript src 将显示结果,但我认为也许有更好的方法。有什么想法吗?
我终于明白了。在具有该表单的同一视图中,我创建了一个 table 来保存数据和一些 javascript 来显示 json 响应。新操作“search_results”处理接受表单数据、创建搜索和 returning 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 %>
更新的控制器显示表单,接受表单数据,创建搜索,return 结果通过 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>
我正在构建一个客户可以在其第三方网站上显示的小部件。该小部件接受消费者关于他们正在寻找什么样的房子的输入。提交时,小部件对端点 API(我的数据库)内的搜索模型发出 POST 请求。然后我想在客户的网站上显示搜索结果。
到目前为止,我已经在第三方网站上成功发布了搜索表单,并在提交时创建了一个新的搜索对象,并且可以在我的网站上查看搜索结果。但我希望将搜索结果发送回客户的网站。
在客户的网站上,他们有一个如下所示的 js 脚本:
<script type="text/javascript" src="http://localhost:3000/searchapis/search_form.js"></script>
我的routes.rb:
get 'searchapis/show'
get '/searchapis/:template', to: "searchapis#show"
post 'search/create', to: "searches#create"
我创建了一个搜索api控制器,如下所示:
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...">
最后 searches_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 =(<script type="text/javascript" src="http://localhost:3000/searchapis/api_search_results.js"></script>
) 链接到一个新的 api_search_results 页面,我会需要 rails g migration AddNewSttributeToSearch api:boolean
以便我可以在控制器中进行 api 搜索并路由到新的 api_search_results 页面。然后,当消费者在第三方网站上点击提交时,第二个 javascript src 将显示结果,但我认为也许有更好的方法。有什么想法吗?
我终于明白了。在具有该表单的同一视图中,我创建了一个 table 来保存数据和一些 javascript 来显示 json 响应。新操作“search_results”处理接受表单数据、创建搜索和 returning 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 %>
更新的控制器显示表单,接受表单数据,创建搜索,return 结果通过 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>