在完成REST Client时,使用路由从JS检查,在后台(DelayedJob)从此外部API获取项目。路由部分工作正常,但如何从视图中重用相同的@items_status
,以便Ajax实际上可以加载项并在完成后插入它们?
您可以即时投放的实时应用:http://runnable.com/VXIdQ6KuRrYPdhKs/rest-client-ajax(https://gist.github.com/dt1973/b57d84bf39a75ea47e9b)
index.html.erb
<!-- THIS ALWAYS RETURNS FALSE EVEN WHEN TRUE -->
<% if @items_status %>
<div class="products">
<% @products.each do |product| %>
<div class="product">
<%= link_to product.name, product.url %>
</div>
<% end %>
</div>
<% else %>
<div class="products processing">
<p>Currently fetching.. come back later</p>
<!-- Fetch via Ajax later -->
</div>
<% end %>
check_items_loaded.js.erb
<!-- This seems to return true properly though -->
alert("<%= @items_status %>");
的routes.rb
get '/check_items_loaded', to: 'main#check_items_loaded', as: :check_items_loaded
main_controller.rb
class MainController < ApplicationController
def index
# Delay fetching
@products = Affiliate.delay.fetch
end
def check_items_loaded
@items_status = Affiliate.where(url: params[:url]).exists?
respond_to do |wants|
wants.js
end
end
end
affiliate.rb
require "rest_client"
class Affiliate < ActiveRecord::Base
def self.fetch
response = RestClient::Request.execute(
:method => :get,
:url => "http://api.shopstyle.com/api/v2/products?pid=uid7849-6112293-28&fts=women&offset=0&limit=10"
)
@products = JSON.parse(response)["products"].map do |product|
product = OpenStruct.new(product)
affiliate = Affiliate.find_or_create_by(:name => product.name, :url => product.url)
affiliate.save
end
end
end
答案 0 :(得分:2)
您必须重复使用用于检查项目是否被提取的路由,而不是视图中的实例@items_status
。
在您的Ajax部分中,您基本上必须继续查询路由以检查是否已完成提取,并且当它完成时,您必须向另一个路由发出请求以将获取的项目返回到页面。
所以制作另一条路线,如get_items_fetched
,我认为最好的回应是包含这些项目的json数据。例如:
def get_fetched_items
respond_to do |format|
format.json do
render json: @products
end
end
end
您应该在/get_items_fetched.json
获取json数据。
更新1:
获取商品状态和商品的正确方法如下:
AJAX部分:
首先将setTimeout更改为setInterval,因此它会自动保持对item_status的轮询。但是如果您有自己的理由使用setTimeout,那么您可以忽略它。
poll: function() {
console.log('Ran `poll`');
// Change here, setTimeout to setInterval.
window.pollInterval = setInterval(this.request, 3000);
},
其次检查为轮询请求返回的item_status,不要在错误部分重试。
request: function() {
console.log('Ran `request`');
$.ajax({
url: "/check_items_loaded",
type: "GET",
// Change here ! Added the checking of the item status returned.
// Why ? Previsouly it wasn't checking at all. So if the request was
// successful, it meant the items_status was also true.
success: function(data){
// Note if the data has the json MIME type, it'll be automatically
// converted to a JavaScript object.
if(data.item_status == true) {
console.log('Items now ready');
$.restClient.addItems();
// Now you don't have to poll anymore, so clear interval.
clearInterval(window.pollInterval);
}
else
console.log('Fetching going on ...');
},
error: function() {
console.log('Request was not completed successfully.');
}
});
},
接下来,解析您在addItems
的响应中获得的HTML。默认情况下,如果响应是HTML,则会将其作为纯文本提供。
addItems: function() {
console.log('Ran `addItems`');
var dataUrl = '/';
$.get(dataUrl, function(data) {
// Parsing it first.
var html = $.parseHTML(data);
$(html).find('.product').appendTo($('body'));
console.log(html);
});
console.log('New items were added');
}
现在在后端,/check_items_done
路线部分:
def check_items_loaded
@items_status = Affiliate.where(url: params[:url]).exists?
render json: {item_status: @item_status}
end