2012-12-13 26 views
0

這是我第一次嘗試從API獲取數據,並將數據輸出到視圖。API和XML數據軌道3 Nokogiri

我想將一個ISBN號碼放入搜索表單中,並使用http://isbndb.com/獲取該特定書籍的數據。這是我到目前爲止有:

控制器:

require 'open-uri' 
class BookController < ApplicationController 
    def searchbook 
    resp = open("http://isbndb.com/api/books.xml?access_key=#{'API KEY HERE'}&results=texts&index1=isbn&value1=#{params[:isbn]}") 
    doc = Nokogiri.XML(resp.read) 
    # ... process response here 

end 
end 

形式:

<%= form_tag({:controller => 'book', :action => 'searchbook'}, {:method => 'get'}) do |select| %> 
<%= label_tag :isbn, "Enter ISBN Number" %> 
<%= text_field_tag :isbn, params[:isbn] %> 
<%= submit_tag "Search" %> 
<% end %> 

的XML要返回

<?xml version="1.0" encoding="UTF-8"?> 
    <ISBNdb server_time="2005-07-29T03:02:22"> 
    <BookList total_results="1" page_size="10" page_number="1" shown_results="1"> 
    <BookData book_id="paul_laurence_dunbar" isbn="0766013502"> 
    <Title>Paul Laurence Dunbar</Title> 
    <TitleLong>Paul Laurence Dunbar: portrait of a poet</TitleLong> 
    <AuthorsText>Catherine Reef</AuthorsText> 
    <PublisherText publisher_id="enslow_publishers">Berkeley Heights, NJ: Enslow Publishers, c2000.</PublisherText> 
    <Summary>A biography of the poet who faced racism and devoted himself to depicting the black experience in America.</Summary> 
    <Notes>"Works by Paul Laurence Dunbar": p. 113-114. Includes bibliographical references (p. 124) and index.</Notes> 
    <UrlsText></UrlsText> 
    <AwardsText></AwardsText> 
    </BookData> 
</BookList> 
    </ISBNdb> 

如何處理XML請求或我能讀什麼來了解如何?

我在哪裏可以查看控制檯中返回的數據(如果有)?我甚至不確定這是否還在做任何事情,但是通過點擊我的表單中的「搜索」我會將其帶到現在是空白頁面的搜索簿操作。

我可能還有很長的路要走,但這是我第一次這樣做。

+0

沒有你試圖解析它很難爲您提供的示例代碼使用XML的一個樣本。使用Nokogiri解析XML很容易,但是,如果沒有示例XML,您需要使用[Nokogiri的解析教程](http://nokogiri.org/tutorials/parsing_an_html_xml_document.html)。 –

+0

我已經添加了預期的XML,這是否有幫助 – Richlewis

回答

1

解析XML很簡單:

require 'nokogiri' 

doc = Nokogiri::XML(<<EOT) 
    <?xml version="1.0" encoding="UTF-8"?> 
    <ISBNdb server_time="2005-07-29T03:02:22"> 
    <BookList total_results="1" page_size="10" page_number="1" shown_results="1"> 
    <BookData book_id="paul_laurence_dunbar" isbn="0766013502"> 
    <Title>Paul Laurence Dunbar</Title> 
    <TitleLong>Paul Laurence Dunbar: portrait of a poet</TitleLong> 
    <AuthorsText>Catherine Reef</AuthorsText> 
    <PublisherText publisher_id="enslow_publishers">Berkeley Heights, NJ: Enslow Publishers, c2000.</PublisherText> 
    <Summary>A biography of the poet who faced racism and devoted himself to depicting the black experience in America.</Summary> 
    <Notes>"Works by Paul Laurence Dunbar": p. 113-114. Includes bibliographical references (p. 124) and index.</Notes> 
    <UrlsText></UrlsText> 
    <AwardsText></AwardsText> 
    </BookData> 
</BookList> 
    </ISBNdb> 
EOT 

isbn_data = doc.search('BookData').map{ |book_data| 

    hash = {} 

    %w[ book_id isbn ].each do |p| 
    hash[p.downcase.to_sym] = book_data[p] 
    end 

    %w[ Title TitleLong AuthorsText PublisherText Summary ].each do |t| 
    hash[t.downcase.to_sym] = book_data.at(t).text 
    end 

    hash 
} 

pp isbn_data 

,輸出:

 
[{:book_id=>"paul_laurence_dunbar", 
    :isbn=>"0766013502", 
    :title=>"Paul Laurence Dunbar", 
    :titlelong=>"Paul Laurence Dunbar: portrait of a poet", 
    :authorstext=>"Catherine Reef", 
    :publishertext=>"Berkeley Heights, NJ: Enslow Publishers, c2000.", 
    :summary=> 
    "A biography of the poet who faced racism and devoted himself to depicting the black experience in America."}] 

此代碼是基於這樣的想法,你可能會收到多個<BookData>塊,所以它返回哈希值的數組。如果你只有一個用途:

hash = {} 
book_data = doc.at('BookData') 

%w[ book_id isbn ].each do |p| 
    hash[p.downcase.to_sym] = book_data[p] 
end 

%w[ Title TitleLong AuthorsText PublisherText Summary ].each do |t| 
    hash[t.downcase.to_sym] = book_data.at(t).text 
end 

pp hash 

輸出現在看起來像:

 
{:book_id=>"paul_laurence_dunbar", 
:isbn=>"0766013502", 
:title=>"Paul Laurence Dunbar", 
:titlelong=>"Paul Laurence Dunbar: portrait of a poet", 
:authorstext=>"Catherine Reef", 
:publishertext=>"Berkeley Heights, NJ: Enslow Publishers, c2000.", 
:summary=> 
    "A biography of the poet who faced racism and devoted himself to depicting the black experience in America."} 
0

當你正在尋找基本的指向正確的方向,這裏有幾點我認識到。

1)對於通過HTTP獲取任何源代碼,通常使用HTTP客戶端寶石。我可以推薦Excon和價值低估的HTTP Client寶石,不過您會發現更多選擇,例如在Ruby工具箱中。

2)要深入瞭解API響應,您可以只是引發輸出結果的異常。我從RailsCast學到了這個技巧。

# Example with Curb 
http = Curl.get("http://www.google.com/") 
body = http.body_str 

# Raise an exception displaying the value you want to see 
raise body.inspect 
# or in nicely structured yaml format 
raise body.to_yaml 

當你想看看你剛發到某個控制器動作多的PARAMS你到處都可以使用這種技術,對我來說就派上用場了。

甚至可以通過最近的better_errors gem來實現與返回值進行交互的方式(例如嘗試一些方法調用)。它附帶一個控制檯,您始終可以通過瀏覽器與當前環境進行交互。

+0

感謝您的迴應,所以沒有HTTP客戶端寶石我不能執行api調用或接收響應? – Richlewis

+0

現在我可以不使用open-uri嗎? – Richlewis

+0

OpenURI是[Ruby標準庫](http://ruby-doc.org/stdlib-1.9.3/libdoc/open-uri/rdoc/OpenURI.html)的一部分,因此直接附帶Ruby而不是Rails。它當然有效,但你正在尋求改進你的代碼。我會考慮一個專門的HTTP客戶端在選擇方面有很好的投資。在檢查HTTP響應或解析的Nokogiri XML對象之前,你還有一些進展嗎? –

1

我強烈建議通過將與ISBNdb相關的代碼移動到它自己的模型來簡化您的控制器。這樣做的一個好方法是通過HTTParty

class ISBNdb 
    include HTTParty 

    base_uri "http://isbndb.com/api" 
    @key = "API_KEY_HERE" 

    def self.get_book(isbn) 
    params = {'value1' => isbn, 'results' => 'texts', 'index1' => 'isbn', 'access_key' => @key} 
    get('/books.xml', :query => params)['ISBNdb']['BookList']['BookData'] 
    end 
end 

然後,在你的控制器,你可以使用它像這樣:

book = ISBNdb.get_book('1934356166') 
puts book['Title'] #=> "Agile Web Development with Rails" 

正如你所看到的,HTTParty解析你的反應,所以你可以像散列一樣訪問它。

該解決方案使您的控制器保持簡單,並且還提供了一個方便的地方爲其他API調用添加方法,如果您需要其他功能。這在實踐中是Single Responsibility Principle