1

Sinatra を使用して、Ruby でコーディングされた YP (Yellow Pages) A​​PI で使用している検索フォームがあります。

検索をバックエンドで機能させるためにすべてのドットを接続することができましたが、検索フォームを 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 リポジトリのクローンを作成したところ、いくつかの問題が見つかりました。

  • gemspec で ruby​​gem を依存関係としてリストする必要はありません。
  • 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ファイルを変更した方法ですが、個人的には開発依存関係を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 に答える