我有一个电影应用程序,它搜索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
答案 0 :(得分:1)
要实现此功能,您需要做的事情。
def search
中的@movie_list变量中,以便您可以在search.html.erb上访问它。我假设您已经有两个具有相似关系的模型:
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中的信息来创建电影的新实例,然后将其添加到列表中?”“我会猜几件事:
在这种情况下,您可以创建模型关注点,其中将包含一些与OMDB服务对象进行交互的逻辑
例如,可以在这种情况下定义我放在add_to_list
上方的自定义方法。
如果您需要更多有关操作方法的信息,可以与我联系。