Ruby on rails 方法在Ruby模型中不返回变量

Ruby on rails 方法在Ruby模型中不返回变量,ruby-on-rails,ruby,scope,Ruby On Rails,Ruby,Scope,我正试图使用真空宝石(v.2.0.2)向亚马逊索取信息。然而,我不确定我应该如何返回我得到的结果。目前,我已经为我的方法编写了以下代码: 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

我正试图使用真空宝石(v.2.0.2)向亚马逊索取信息。然而,我不确定我应该如何返回我得到的结果。目前,我已经为我的方法编写了以下代码:

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
我想调用,以便能够在我的控制器中使用此方法中创建的变量。如何访问控制器中的作者、标题、制造商和url实例变量?我希望这样,当用户输入他们的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

一个快速修复方法是使该方法以PORO(普通的旧ruby对象)的形式返回值,然后将它们从控制器分配给实例变量。在
isbn\u lookup
方法的末尾,输入以下内容:

return {title: title, author: author, manufacturer: manufacturer, url: url}
不要在
isbn\u lookup
方法中使用实例变量-它们没有按照您希望的方式工作。为了理解这一点,您可能需要进一步了解Ruby类是如何工作的。但总而言之,您的控制器方法在控制器的一个实例中运行(为每个请求创建一个实例),而您的
isbn\u查找
是作为类方法编写的,因此实例变量在那里没有真正的意义。有关这方面的更多解释,请参阅

如果您觉得像这样列出所有键很难看,您可以增量地构建对象,例如,在方法开始时放置
isbn={}
,然后执行类似
isbn[:author]=fr.dig(…)
,最后返回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
我不确定你是否了解dig的工作原理。这是挖掘嵌套对象的安全方法。如果在参数中找到的键处的项不存在,它将返回
nil
。e、 g.
{}.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为nil,您仍然可以让该方法返回一个带有
:url
键的散列(恰好有一个nil值)。然后,无论您实际需要知道url是否存在(例如,出于表示目的,视图),您都可以执行
如果@isbn[:url]

一个快速修复方法是使该方法将值作为PORO(普通的旧ruby对象)返回,然后将它们从控制器分配给实例变量。在
isbn\u lookup
方法的末尾,输入以下内容:

return {title: title, author: author, manufacturer: manufacturer, url: url}
不要在
isbn\u lookup
方法中使用实例变量-它们没有按照您希望的方式工作。为了理解这一点,您可能需要进一步了解Ruby类是如何工作的。但总而言之,您的控制器方法在控制器的一个实例中运行(为每个请求创建一个实例),而您的
isbn\u查找
是作为类方法编写的,因此实例变量在那里没有真正的意义。有关这方面的更多解释,请参阅

如果您觉得像这样列出所有键很难看,您可以增量地构建对象,例如,在方法开始时放置
isbn={}
,然后执行类似
isbn[:author]=fr.dig(…)
,最后返回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
我不确定你是否了解dig的工作原理。这是挖掘嵌套对象的安全方法。如果在参数中找到的键处的项不存在,它将返回
nil
。e、 g.
{}.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为nil,您仍然可以让该方法返回一个带有
:url
键的散列(恰好有一个nil值)。如果@isbn[:url]

您的实例变量从未设置,那么无论您实际需要知道url是否存在(例如,出于表示目的,视图),都可以执行
。您看到行
return fr
?那一行之后的一切都不会执行。我已经更新了代码。但是我如何使其返回我发现存在的所有变量呢?那么我该如何在我的控制器中实现呢?你的实例变量永远不会被设置。您看到行
return fr
?那一行之后的一切都不会执行。我已经更新了代码。但是我如何使其返回我发现存在的所有变量呢?那么我该如何在我的控制器中实现它呢?好吧,出于某种原因,当我使用它时,我得到了一个错误:“nil:NilClass的未定义方法”[]”。我想这可能是我引用元素作为url变量的数字[6]的方式。有什么简单的方法可以避免这个错误吗?好的,出于某种原因,当我使用它时,我得到了一个错误:“nil:NilClass的未定义方法”[]”。我想这可能是我引用元素作为url变量的数字[6]的方式。有什么简单的方法可以避免这个错误吗?