【问题标题】:Connecting Search Form in Ruby with Sinatra将 Ruby 中的搜索表单与 Sinatra 连接起来
【发布时间】:2013-04-04 12:16:39
【问题描述】:

我有一个使用 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 %>

【问题讨论】:

  • 您对 client.search 的调用是否实际上向@results 返回任何内容? “# Print out the result info”是为了简洁起见,还是您忘记打印某些内容?

标签: ruby api search sinatra yellow-pages


【解决方案1】:

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

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')

变成身体。你想要的是 rendered template 作为最后一行,所以:

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

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

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 中,您必须使用 end 关闭 if…else 块。

如果未提供参数,我还添加了halt,但您也可以使用error handler 或将错误传递到模板中以通知用户。 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

希望对您有所帮助。

【讨论】:

  • 我试着按照你说的移动 erb: index,但是我的搜索表单和文本没有显示出来。由于我对 Ruby 很陌生,因此我不确定从那里解决问题时出了什么问题。
  • @JohnBlanchard 我注意到您提供的代码中可能存在拼写错误,您在其中定义了@@ index 的模板,它应该是@@index。看看这是否有所作为。如果没有,请发布新代码或上传到 github/bitbucket,如果可以的话,我们可以尝试自己运行。
  • 我根据您的建议更新了原始问题。完整代码可在此处获得:github.com/theblanchard/yp
  • 我更新了依赖项,添加了暂停,并运行了语法错误检查,现在返回正常,但运行搜索时仍然没有得到任何结果。当你在本地运行它时它会返回结果吗?我还用新增内容更新了 Github 链接。
  • 我实际上做了更多的挖掘并且能够让它工作。非常感谢您的帮助!
猜你喜欢
  • 2013-12-05
  • 1970-01-01
  • 1970-01-01
  • 2016-01-28
  • 2016-01-14
  • 2016-05-03
  • 1970-01-01
  • 2011-07-25
  • 2015-06-23
相关资源
最近更新 更多