2017-09-15 55 views
0

我正在尝试使用vacuum gem(v.2.0.2)从亚马逊请求信息。但是,我不知道我应该如何返回我得到的结果。目前,我有此代码为我的方法:在Ruby模型中不返回变量的方法

def self.isbn_lookup(val) 
    request = Vacuum.new('US') 
    request.configure(
    aws_access_key_id: 'access_key_goes_here', 
    aws_secret_access_key: 'secret_key_goes_here', 
    associate_tag: 'associate_tag_goes_here' 
) 
    response = request.item_lookup(
    query: { 
     'ItemId' => val, 
     'SearchIndex' => 'Books', 
     'IdType' => 'ISBN' 
    }, 
    persistent: true 
) 
    fr = response.to_h #returns complete hash 
    if fr["ItemLookupResponse"]["Items"]["Item"]["ItemAttributes"]["Author"] 
    @author = fr.dig("ItemLookupResponse","Items","Item","ItemAttributes","Author") 
    end 
    if fr["ItemLookupResponse"]["Items"]["Item"]["ItemAttributes"]["Author"] 
    @title = fr.dig("ItemLookupResponse","Items","Item","ItemAttributes","Title") 
    end 
    if fr["ItemLookupResponse"]["Items"]["Item"]["ItemAttributes"]["Manufacturer"] 
    @manufacturer = fr.dig("ItemLookupResponse","Items","Item","ItemAttributes","Manufacturer") 
    end 
    if fr["ItemLookupResponse"]["Items"]["Item"]["ItemAttributes"][6]["URL"] 
    @url = fr.dig("ItemLookupResponse","Items","Item","ItemLinks","ItemLink",6,"URL") 
    end 
end 

我想调用能够使用这个方法中创建的变量在我的控制器。我如何访问控制器中的作者,标题,制造商和网址实例变量?我想这样做是为了当用户输入他们的ISBN时,它会发送一个AJAX请求到服务器来请求相关信息(作者,标题等)。目前,这是我的控制器看起来像:

def create 
    @listing = Listing.new(listing_params) 
    @listing.user = current_user 
    if @listing.save 
    flash[:success] = "Your listing was successfully saved." 
    redirect_to listing_path(@listing) 
    else 
    render 'new' 
    end 
end  
def edit 
    @isbn = Listing.isbn_lookup(1285741552) 
end 
+2

你的实例变量从不设置。你看到'return fr'这行?该行之后的所有内容都不会执行。 –

+0

好的。我更新了代码。 –

+0

但是,我如何使它返回所有我发现存在的变量?然后,我如何在我的控制器中实现? –

回答

2

速战速决将是使该方法返回的值作为PORO(普通老式Ruby对象),然后将其分配给从控制器实例变量。在isbn_lookup方法结束时,把这个:

return {title: title, author: author, manufacturer: manufacturer, url: url} 

不要在isbn_lookup方法使用实例变量 - 他们不工作,你希望他们做的方式出现。您可能需要多了解一下Ruby类如何工作才能理解这一点。但总而言之,您的控制器方法在控制器的实例中运行(每个请求创建一个实例),而您的isbn_lookup编写为类方法,因此实例变量在这里没有真正意义。有关详情,请参阅Using Instance Variables in Class Methods - Ruby

如果您觉得列出所有像这样的键是丑陋的,您可以增量构建对象,例如,在方法的开始把isbn = {},然后做的东西一样isbn[:author] = fr.dig(...),并在年底return isbn

,并在控制器方法:

@isbn = Listing.isbn_lookup(1285741552) 
@title = @isbn[:title] 
@manufacturer= @isbn[:manufacturer] 
@author = @isbn[:author] 
@title = @isbn[:title] 

@title@manufacturer等实例变量的设置是怎么样是不必要的,因为您可以从视图中使用@isbn[:author]


响应您的跟进问题:

这一权利在这里是奇数:

if fr["ItemLookupResponse"]["Items"]["Item"]["ItemAttributes"][6]["URL"] 
    @url = fr.dig("ItemLookupResponse","Items","Item","ItemLinks","ItemLink",6,"URL") 
end 

我不知道您了解如何挖掘工作。这是一种挖掘嵌套对象的方式。如果参数中找到的键项不存在,它将返回nil。例如{}.dig(:a, :b, 1, 2, :etc) == nil。所以,你可能只是这样做:

url = fr.dig("ItemLookupResponse","Items","Item","ItemLinks","ItemLink",6,"URL") 
if url 
    # etc 

甚至利用内嵌分配的:“你的意思==”

if url = fr.dig("ItemLookupResponse","Items","Item","ItemLinks","ItemLink",6,"URL") 
    # etc 

虽然你可能会从本质上的Ruby说警告(你没有)。

我没有看到你真的在这里需要条件。例如,即使url为零,您仍然可以使用:url键(该值恰好具有零值)返回散列。然后无论你在哪里实际上需要知道url是否存在(例如视图,为了表示目的),你可以做if @isbn[:url]

+0

好吧,由于某种原因,当我使用这个,我得到错误:“未定义的方法'[]'为零:NilClass。”我认为这可能是我将元素引用为url变量的数字[6]。任何简单的方法来避免这个错误? –

+1

@JackMoody查看答案的更新。 –