用Sinatra连接Ruby中的搜索表单



我有一个搜索表单,我使用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 %>

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

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

,然后从模板中@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仓库,发现了一些问题:

  • 你不需要在gemspec中将rubygems列为依赖项。
  • Shotgun没有在gemspec或Gemfile中作为开发依赖项列出。
  • Rails即使不在项目中也被列出。

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文件中,而是放在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块。

如果没有给出参数,我还添加了一个选项,但是您也可以使用错误处理程序或将错误传递到模板中以通知用户。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 .

最新更新