#javascript #widget #ruby-on-rails-5 #jsonresponse
Вопрос:
Я создаю виджет, который клиент может отображать на своем стороннем веб-сайте. Виджет принимает информацию от потребителей о том, какой дом они ищут. При отправке виджет делает запрос на публикацию в модели поиска в API конечной точки (моя база данных). Затем я хочу отобразить результаты поиска на веб-сайте клиента.
До сих пор я успешно размещал форму поиска на стороннем веб-сайте, и при отправке создается новый объект поиска, и результаты поиска готовы для просмотра на моем веб-сайте. Но я хочу, чтобы результаты поиска были отправлены обратно на веб-сайт клиента.
На веб-сайте клиента у них есть js-скрипт, который выглядит следующим образом:
lt;script type="text/javascript" src="http://localhost:3000/searchapis/search_form.js"gt;lt;/scriptgt;
Мои маршруты.рб:
get 'searchapis/show' get '/searchapis/:template', to: "searchapis#show" post 'search/create', to: "searches#create"
Я создал контроллер searchesapi, который выглядит следующим образом:
class SearchapisController lt; ApplicationController protect_from_forgery :except =gt; :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
представление, которое выглядит примерно так:
lt;%= bootstrap_form_for @search, :html =gt; {}, :url =gt; create_search_url(@search), remote: true do |form| %gt; lt;%=form.select :beds, (select_options), {prompt: "Min # of Bedrooms", hide_label: true}, {class: "form-control form-control-sm"}%gt; lt;%=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"}%gt; lt;input type="submit" name="commit" value="SEARCH" class="btn btn-danger" data-disable-with="Finding Schools..."gt;
И, наконец, searches_controller.rb:
class SearchesController lt; 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 на сторонний веб-сайт.
Я думаю, что мне нужно будет создать дополнительный src javascript для веб-сайта клиента = ( lt;script type="text/javascript" src="http://localhost:3000/searchapis/api_search_results.js"gt;lt;/scriptgt;
), связанного с новой страницей api_search_results, и мне это понадобится rails g migration AddNewSttributeToSearch api:boolean
, чтобы я мог выполнить поиск api в контроллере и перейти на новую страницу api_search_results. Затем, когда потребитель нажимает «Отправить» на стороннем веб-сайте, 2-й src javascript отобразит результаты, но я думаю, что, возможно, есть лучший способ. Есть какие — нибудь мысли на этот счет?
Комментарии:
1. Почему бы не использовать iframe? Визуализируйте эту форму в iframe, и у вас будет полный контроль над тем, что находится внутри нее.
2. Спасибо за комментарий @razvans, я попробую. Но как только iframe будет на месте, и потребитель введет свои данные, и данные будут переданы в мою базу данных, и поиск будет проведен, и результаты будут готовы, как мне затем отобразить эти результаты на экране потребителя? Теоретически на веб-сайте клиента могут быть сотни людей, поэтому результаты должны соответствовать каждому запросу.
Ответ №1:
Я, наконец, понял это. В том же представлении, в котором есть форма, я создал таблицу для хранения данных и некоторый javascript для отображения ответа json. Новое действие «search_results» обрабатывает прием данных формы, создание поиска и возврат json.
Обновленные маршруты:
get 'searchapis/search_results' post 'searchapis/search_results' get 'searchapis/show' get '/searchapis/:template', to: "searchapis#show"
Обновленное представление формы поиска:
lt;%= bootstrap_form_for @search, :html =gt; {id: "search_api"}, :url =gt; searchapis_search_results_url(@search), remote: true do |form| %gt; lt;%=form.select :beds, (select_options), {prompt: "Min # of Bedrooms", hide_label: true}, {class: "form-control form-control-sm"}%gt; lt;%=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"}%gt; lt;input type="submit" name="commit" value="SEARCH" class="btn btn-danger" data-disable-with="Finding Schools..."gt; lt;% end %gt;
Обновленный контроллер для отображения формы, принятия данных формы, создания поиска и возврата результатов с помощью json:
class SearchapisController lt; ApplicationController protect_from_forgery :except =gt; [: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 теперь выглядит следующим образом:
lt;stylegt; #hide_table { display:none } lt;/stylegt; lt;%= bootstrap_form_for @search, :html =gt; {id: "search_api"}, :url =gt; searchapis_search_results_url(@search), remote: true do |form| %gt; lt;%=form.select :beds, (select_options), {prompt: "Min # of Bedrooms", hide_label: true}, {class: "form-control form-control-sm"}%gt; lt;%=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"}%gt; lt;input type="submit" name="commit" value="SEARCH" class="btn btn-danger" data-disable-with="Finding Schools..."gt; lt;% end %gt; lt;div class="container-fluid"gt; lt;div class="row"gt; lt;div class="col"gt; lt;div id='hide_table'gt; lt;table class="table table-sm" id="schools_api"gt; lt;theadgt; lt;trgt; lt;thgt;Namelt;/thgt; lt;thgt;Addresslt;/thgt; lt;thgt;Citylt;/thgt; lt;thgt;Scorelt;/thgt; lt;thgt;# Homeslt;/thgt; lt;/trgt; lt;/theadgt; lt;tbodygt; lt;/tbodygt; lt;/tablegt; lt;/divgt; lt;/divgt; lt;/divgt; lt;/divgt; lt;scriptgt; document.body.addEventListener("ajax:success", (event) =gt; { var response = event.detail[0]; $("#schools_api tbody tr").remove(); $('#hide_table').css("display","block"); $.each(response, function(i, item) { $('lt;trgt;').html("lt;tdgt;" item[0] "lt;/tdgt;lt;tdgt;" item[1] "lt;/tdgt;lt;tdgt;" item[2] "lt;/tdgt;lt;tdgt;" item[3] "lt;/tdgt;lt;tdgt;" item[4] "lt;/tdgt;").appendTo('#schools_api'); }); }); lt;/scriptgt;