Связь формы поиска в Ruby с Sinatra
У меня есть форма поиска, которую я использую с API YP (Желтые страницы), написанная на 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 %>
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')
становится телом. Вы хотите, чтобы отображаемый шаблон был последней строкой, поэтому:
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
template`. Возвращаемое значение метода - строка. Затем эту строку можно использовать где угодно, как обычную строку, но вы, скорее всего, скорее всего поместите ее в конец блока маршрута, поскольку вы хотите вернуть строку.
Там, где вы поместили его прямо сейчас, в теле класса, это просто вызов метода, результат которого ни к чему не приведет. Это то же самое, что и:
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 и обнаружил несколько проблем:
- Вам не нужно перечислять rubygems как зависимость в gemspec.
- Дробовик не был указан в 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, но лично я не помещаю зависимости разработки в 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
,
Я также добавил в остановке, если параметры не заданы, но вы также можете использовать обработчик ошибок или передать ошибку в шаблон, чтобы проинформировать пользователя. 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
,
Надеюсь, это поможет.