将 API 调用从控制器移动到 Rails 中的模型

nwi*_*123 1 api ruby-on-rails

我正在制作一个读书俱乐部应用程序。用户可以上传他们想与其他人一起阅读的书籍。我正在从 Google Books Api 引入图书信息,目前在控制器中有 API 调用。我知道这很丑陋且不合理,但无法从模型中使其正常工作。你认为最好的重构是什么让这个更干净?

new.html.erb - 来自书籍

  <%= form_for :book, url: books_path do |f| %>
    <fieldset>
      <h1 class="text-center">Add A Book</h1>

      <div class="form-group">
        <label class="col-md-4 control-label" for="name">Title</label>
        <div class="col-md-8">
          <%= f.text_field :title, required: true, class: "form-control" %><br>
        </div>
      </div>

      <div class="form-group">
        <label class="col-md-4 control-label" for="genre">Genre</label>
        <div class="col-md-8">
          <%= f.select :genre, [["Sci-fi", "Sci-fi"], ["Fantasy", "Fantasy"], ["Comic", "Comic"], ["Manga", "Manga"]], class: "form-control" %>
        </div>
      </div>

      <div class="form-group">
        <div class="col-md-12">
          <%= f.submit "Create Book", class: "btn btn-success" %>
        </div>
      </div>

    </fieldset>
  <% end %>
Run Code Online (Sandbox Code Playgroud)

book_controller.rb

def create
  @user = current_user
  find_book
  redirect_to root_path
end

require "openssl"
OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE

def find_book
  tempBook = params[:book][:title]
  tempGenre = params[:book][:genre]
  url = "https://www.googleapis.com/books/v1/volumes?q=" + tempBook + "&key=secret_key"
  uri = URI(url)
  response = Net::HTTP.get(uri)
  book_data = JSON.parse(response)    
  b = Book.new
  b.user_id = @user.id
  b.title = book_data["items"][0]["volumeInfo"]["title"]
  b.genre = tempGenre
  b.author = book_data["items"][0]["volumeInfo"]["authors"][0]
  b.publisher =  book_data["items"][0]["volumeInfo"]["publisher"]
  b.publication_date =  book_data["items"][0]["volumeInfo"]["publishedDate"]
  b.synopsis =  book_data["items"][0]["volumeInfo"]["description"]
  b.image = book_data["items"][0]["volumeInfo"]["imageLinks"]["thumbnail"]
  @book = b.save
end
Run Code Online (Sandbox Code Playgroud)

书.rb

class Book < ActiveRecord::Base
  belongs_to :user
  has_many :reviews

  def set_user(user)
    self.user_id = user.id 
    self.save    
  end

end
Run Code Online (Sandbox Code Playgroud)

它以这种方式工作,但很丑陋,我应该隐藏我的钥匙,而不是让它打开。

我尝试将函数放入模型并在 show 方法中将标题和流派声明为变量,但它们没有传递到模型中,因此它不起作用。

谢谢!

这是我试过的代码,但没有用。@tempBook 是 nil,所以它弄乱了模型。我假设这是因为模型在获取变量之前正在运行?

书.rb

class Book < ActiveRecord::Base
  belongs_to :user
  has_many :reviews

  def set_user(user)
    self.user_id = user.id 
    self.save    
  end

  require "net/http"
  require "json"

  require "openssl"
  OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE

  def self.find_book
    url = "https://www.googleapis.com/books/v1/volumes?q=" + @tempBook + "&key=SECRET_KEY"
    uri = URI(url)
    response = Net::HTTP.get(uri)
    book_data = JSON.parse(response)    
    b = Book.new
    b.user_id = @user.id
    b.title = book_data["items"][0]["volumeInfo"]["title"]
    b.genre = @tempGenre
    b.author = book_data["items"][0]["volumeInfo"]["authors"][0]
    b.publisher =  book_data["items"][0]["volumeInfo"]["publisher"]
    b.publication_date =  book_data["items"][0]["volumeInfo"]["publishedDate"]
    b.synopsis =  book_data["items"][0]["volumeInfo"]["description"]
    b.image = book_data["items"][0]["volumeInfo"]["imageLinks"]["thumbnail"]
    @book = b.save
  end

end
Run Code Online (Sandbox Code Playgroud)

book_controller.rb

  def create
    @tempBook = params[:book][:title]
    @tempGenre = params[:book][:genre]
    @user = current_user
    Book.find_book
    redirect_to root_path
  end
Run Code Online (Sandbox Code Playgroud)

C d*_*VII 5

您应该将 google 代码提取到lib目录中的某个类中,将该类实例的实例化放入书籍模型中,然后在find_book那里调用该方法。您可以将 api 的配置密钥放入yml文件中。

#lib/google_book.rb
class GoogleBook
  def initialize(info)
  end

  def find_book
    url = "https://www.googleapis.com/books/v1/volumes?q=" + tempBook + "&key=secret_key"
    uri = URI(url)
    response = Net::HTTP.get(uri)
    book_data = JSON.parse(response) 
    #rest of code
  end
end

#book.rb
class Book < ActiveRecord::Base
  belongs_to :user
  has_many :reviews

  def set_user(user)
    self.user_id = user.id 
    self.save    
  end

  def retrieve_google_book
    google_book = GoogleBook.new(some_params)
    google_book.find_book
  end

end
Run Code Online (Sandbox Code Playgroud)