1

我有一个使用 YP(黄页)API 的搜索表单,用 Ruby 编码,带有 Sinatra。

我已经设法连接所有点,让搜索在后端工作,但在将搜索表单连接到 API 调用时遇到问题。一切都在页面上正确显示,但是当我单击提交按钮时什么都没有显示。

我正在使用的代码如下:

require 'rubygems'
require 'sinatra'
require 'yp'

# index.rb 

get "/" do
  # Only run the search if both of our params are available
  if params[:location] && params[:term]
  client = Yp::Client.new(api_key: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
  results = client.search(searchloc: params[:location], term: params[:term], listingcount: 1, sort: 'distance')
  erb :index, :locals => {results: results}
end

__END__

@@index

<h1>YP Search</h1>

<form action="/" method="get">  
  Location: <input type="text" name="location">  <br />
  Search Term: <input type="text" name="term" required> <br />
<input type="submit">  
</form> 

<% if results %>
 <% results.each do |result| %>
 # Print out the result info
<% end %>
<% else %>
 # They haven't searched yet.
<% end %>
4

1 回答 1

2

正如您编写的那样,您没有将结果传递给模板。块中的最后一次调用成为返回值,它是传递给客户端的主体,因此使用您的代码:

get "/" do
  # Only run the search if both of our params are available
  if params[:location] && params[:term]
  client = Yp::Client.new(api_key: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
  @results = client.search(searchloc: params[:location], term: params[:term], listingcount: 1, sort: 'distance')
end

这一行:

  @results = client.search(searchloc: params[:location], term: params[:term], listingcount: 1, sort: 'distance')

变成身体。你想要的是渲染的模板是最后一行,所以:

get "/" do
  # Only run the search if both of our params are available
  if params[:location] && params[:term]
  client = Yp::Client.new(api_key: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
  @results = client.search(searchloc: params[:location], term: params[:term], listingcount: 1, sort: 'distance')
  erb :index
end

实例变量对模板自动可见,因此您只需要这样做。如果你想传递一个局部变量:

get "/" do
  # Only run the search if both of our params are available
  if params[:location] && params[:term]
  client = Yp::Client.new(api_key: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
  results = client.search(searchloc: params[:location], term: params[:term], listingcount: 1, sort: 'distance')
  erb :index, :locals => {results: results}
end

然后从模板@中 var 的前面删除 。@results

erb :index是一个方法调用。它说“调用模板渲染器,使用 ERB 引擎并将:index模板传递给它。该方法的返回值是一个字符串。该字符串可以在任何地方使用,就像普通字符串一样,但你显然是最可能将它放在路由块的末尾,因为您想返回一个字符串。

您现在将其放置在类主体中的位置,它只是一个方法调用,其结果无处可去。这和这样做是一样的:

get "/you/can/access/this" do
  "and this would be the returned body"
end

get "/and/this" do
  erb :index, :locals=>{:what_youd_see => "would be the template"}
end

"But this is just a string that no one can access, it gets called every time, but who is the receiver?"

把你的 Sinatra 应用想象成一个类,然后 Ruby 的常规规则就变得更清晰了 :)


我克隆了你的 git repo 并发现了一些问题:

  • 您不需要在 gemspec 中将 ruby​​gems 列为依赖项。
  • Shotgun 未在 gemspec 或 Gemfile 中列为开发依赖项。
  • Rails 被列出,即使它不在项目中。

在 gemspec 中:

Gem::Specification.new do |gem|
  #other code
  gem.version       = Yp::VERSION
  gem.add_development_dependency "shotgun"
  gem.add_dependency('faraday', ["< 0.8", ">= 0.6"])    
  gem.add_dependency('faraday_middleware', [">= 0.8"])  
  gem.add_dependency('sinatra')  
end

以上是我更改yp.gemspec文件的方法,但我个人并没有将开发依赖项放在gemspec中,而是放在Gemfile中。

# Gemfile

group :development do
  gem "shotgun"
end

我认为更容易管理和更好地分离事物。bundle install我没有运行而是运行bundle install --binstubs --path vendor,因为它将所有内容都放在本地项目目录中。这样一来,所有项目都是相互沙盒化的,如果你错过了任何东西,你会注意到。要运行我使用的应用程序bundle exec ruby index.rb

  • index.rb 存在语法错误

用于ruby -c filename检查语法错误。当您在加载时遇到错误时,首先要尝试。

  • 在 Ruby 中,您必须使用 . 关闭 if...else 块end

如果未给出参数,我还添加了暂停,但您也可以使用错误处理程序或将错误传递到模板中以通知用户。YMMV。

get "/" do
  halt 400, "You need to supply a location and a term"
  # Only run the search if both of our params are available
  if params[:location] && params[:term]
    client = Yp::Client.new(api_key: "e89cba4b974a122e408d1723626f3709")
    results = client.search(searchloc: params[:location], term: params[:term], listingcount: 1, sort: 'distance')
  end
  erb :index, :locals => {results: results}
end
  • 您已硬编码 API 密钥。

我猜这应该是秘密的。最好的事情可能是获得一个新的,永远不要对其进行硬编码,也永远不要将其签入 git。我使用了一个不被 git 跟踪并加载到环境变量中的文件,例如

YAML.load_file("config/secret_settings.yml").each do |key,value|
  ENV[key.upcase] = value
end

我将它添加到 Rakefile 并从机架文件运行应用程序,例如

namespace :app do

  desc "Set up the environment locally"
  task :environment do
    warn "Entering :app:environment"
    YAML.load_file("config/secret_settings.yml").each do |key,value|
      ENV[key.upcase] = value
    end
  end

  desc "Run the app locally"
  task :run_local => "app:environment" do
    exec "bin/rackup config.ru -p 4567"
  end
end

从命令行:

bin/rake app:run_local

你可能想添加一个config.ru.

希望有帮助。

于 2013-04-12T12:45:43.823 回答