将电影信息从API保存到数据库中的列表中

时间:2018-10-08 17:38:54

标签: ruby-on-rails

我有一个电影应用程序,它搜索OMDb API数据库并在我的应用程序中填充搜索结果。我已经获取了这些搜索结果,并对其进行迭代以为每个结果创建电影卡。

在此电影卡中,我有一个“将电影添加到列表”按钮,允许用户按下它并将其添加到已创建的列表中。用户将能够指定哪个列表,然后将其添加到数据库中。

我不确定如何执行该操作。谁能指出我正确的方向?

我的search.html.erb页面:

<div class="card-deck text-center" id="card-deck"> 
  <% if @movies %>
  <% @movies.each do |m| %>
      <div class="card">
        <img src= "<%= m["Poster"] %>" alt="No poster found." class="card-img-top">

        <div class="card-body">
          <h5 class="card-title"><%= m["Title"] %></h5>
          <p class="card-text"><%= m["Year"] %></p>
        </div>

        <div class="card-footer">
          <div class="btn-top">
            <span class="btn-group">
              <%= button_to "Add Movie To List", class: 'btn btn-primary btn-sm btn-space' %>
            </span>
          </div>
        </div>
      </div>
    <% end %>
  <% end %>
</div>

我该如何将该按钮路由到某个控制器动作,然后使用API​​中的信息来创建电影的新实例,然后将其添加到列表中?

我的searchs_controller.rb:

class SearchesController < ApplicationController

  def index
    @list = List.all.select(:id, :name)
    @movie = Movie.new
  end

  def omdb
    @movie = Movie.new
    @list = List.all.select(:id, :name)
    conn = Faraday.new(:url => 'http://www.omdbapi.com')

    @resp = conn.get do |req|
      req.params['apikey'] = ENV['OMDB_API_KEY']
      req.params['s'] = params[:movie]
    end

    body = JSON.parse(@resp.body)
    if @resp.success?
      @movies = body["Search"]
    else
      @error = "There was a timeout. Please try again."
    end
    render 'index'
  end
end

路线:

Rails.application.routes.draw do
  resources :lists, :movies
  get '/search', to: 'searches#index'
  post '/search', to: 'searches#omdb'
  root 'lists#index'
end

我在Search index.html.erb上的按钮上,将电影添加到列表中以弹出模式弹出窗口:

  <div class="btn-top">
      <button class="btn btn-primary btn-sm add-movie" movie-id="m['imdbID']" type="button" data-toggle="modal" data-target="#movielistmodal">Add Movie To List</button>
  </div>

还有我的模态主体代码:

  <div class="modal-body">
    <%= form_for @movie, method: :post, url: 'add_api_movie_to_list' do |f| %>
      <%= hidden_field_tag :movie_id, { id: "movie-id" } %>
      <% @list.each do |list| %>
        <%= f.label :name, list.name %>
        <%= f.radio_button :list_ids, list.id %>
      <% end %>
      <%= f.submit class: 'btn btn-primary btn-space btn-sm' %>
    <% end %>
  </div>
  <div class="modal-footer">
    <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
  </div>

将API电影添加到数据库控制器操作:

  def add_api_movie_to_list
    conn = Faraday.new(:url => 'http://www.omdbapi.com')

    @resp = conn.get do |req|
      req.params['apikey'] = ENV['OMDB_API_KEY']
      req.params['i'] = params[:movie_id]
    end

    body = JSON.parse(@resp.body)
    movie_params = { title: body["Title"], genre: body["Genre"], year: body["Year"], poster: body["Poster"], plot: body["Plot"], director: body["Director"] }
    movie_params.merge(params[:movie])
    @movie = Movie.new(movie_params)
    if @movie.save
      redirect_to movie_path(@movie)
    else
      flash[:error] = "Unable to save movie. Try again."
      render 'search'
    end
  end

2 个答案:

答案 0 :(得分:1)

要实现此功能,您需要做的事情。

  1. 添加将包含电影列表的引导程序模式。
  2. 将movie_lists带入def search中的@movie_list变量中,以便您可以在search.html.erb上访问它。
  3. 您必须使用另一个OMDb API来获取要保存在数据库中的特定电影的详细信息。
  4. 创建一种方法,该方法将使用控制器方法在列表中添加电影。
  5. 一些JQuery。

我假设您已经有两个具有相似关系的模型:

Class MovieList
  has_many :movies
end

Class Movie
  belongs_to :movie_list
end

在movies_controller或定义了def search方法的任何其他控制器中。

添加此行。

def search
  #your pre existing code
  #add the following line
  @movie_list = MovieList.all.select(:id, :name)
end

在search.html.erb

为模态添加html代码。 在模式主体中,为表单添加代码,您将在其中将movie_id存储在隐藏字段中,并在复选框中选择列表。

<%= form_for :movie, method: :post, url: 'path_of_the_method' do |f| %>
  <%= hidden_field_tag :movie_id, { id: "movie-id" } %>
  <% @movies_list.each do |item| %>
    <%= f.radio_button :movie_list_id, item.id %>
  <% end %>
  <%= f.submit %>
<% end %>

在routes.rb中指定此路由

现在

搜索结果中的每个电影都有一个与之关联的按钮。让我们重写它的功能。

<%= button_to "Add Movie To List", class: 'btn btn-primary btn-sm btn-space add-movie', 'data-movie-id': m['id'] %>

注意::我猜你对每部电影都具有独特的movie_id

jQuery:

要使其正常运行,您可以在search.html.erb的末尾进行定义

<script>
  $('.add-movie').click(function(e){
    e.preventDefault();
    //Let's assume the id of the Modal (popup) is #list-modal
    $('#movie-id').val($(this).data('movie-id')); //id of the hidden field
    $('#list-modal').modal('show');
  });
</script>

现在在您刚定义的用于保存表单值的控制器方法中 我们假设方法名称为create_movie,或者如果您使用的是资源,则可以直接编写create

def create_movie
  #API to fetch details of the movie id you've passed in `params[:movie_id]`
  #movie = API call
  #select the attributes you'll be saving in the database. eg:
  hash_params = { title: movie['title'], name: movie['name'] }
  hash_params.merge(params[:movie])!
  movie = Movie.new(hash_params)
  if movie.save
    #redirect with success message
  else
    #redirect with failure message
  end
end

我试图以最好的方式进行解释。 :P您可以从中获得一些提示,您需要做些什么。如果您仍然需要帮助,请告诉我。

答案 1 :(得分:0)

由于电影已保存到数据库中,因此您可以结合link_to设置电影的自定义操作路线。

例如,如果您定义了resources :movies,则可以执行以下操作->

routes.rb

resources :movies do
  post '/add_to_list', action: 'add_to_list'
end

movies_controller.rb->

def add_to_list
  @movie = Movie.find(params[:movie_id]
  @movie.add_to_list
end

add_to_list可以在您的Movie模型中定义为需要执行的任何操作。

在视图(search.html.erb内而不是button_to内,您可以像这样使用link_to->

<%= link_to 'Add Movie To List', movie_add_to_list_path(m), class: "btn btn-primary btn-sm btn-space", method: :post %>

这是针对您的问题的快速解决方案:“ 我如何将该按钮路由到某个控制器操作”。

对于这部分->“ 然后使用API​​中的信息来创建电影的新实例,然后将其添加到列表中?”“我会猜几件事:

  • 您有一些服务对象通过一些gem向OMDB API发出查询
  • 您在电影模型中保存了足够的信息,因此可以向OMDB API发出另一个查询以获取有关特定电影的信息(该用户将在列表中单击)

在这种情况下,您可以创建模型关注点,其中将包含一些与OMDB服务对象进行交互的逻辑

例如,可以在这种情况下定义我放在add_to_list上方的自定义方法。

如果您需要更多有关操作方法的信息,可以与我联系。