使用 Acts As Votable gem 为嵌套对象投票
Voting for nested objects using the Acts As Votable gem
我有一个 Restaurant
型号 has_many :dishes, through: dish_categories
。我找到了一个 post,它展示了如何编写必要的视图代码来让 Acts As Votable gem 的事情顺利进行。我的情况有所不同,因为菜肴模型是正在投票的嵌套资源。
我尝试翻译提供的代码但无济于事。在这一点上,我应该为菜肴创建一个新的控制器并将可投票的动作放在那里吗?如果是这样,我将如何设置我的路线以便我可以在我的餐厅的展示页面上完成此操作?
型号
class Restaurant < ActiveRecord::Base
has_many :dish_categories, dependent: :destroy
has_many :dishes, through: :dish_categories
end
class DishCategory < ActiveRecord::Base
belongs_to :restaurant
has_many :dishes, dependent: :destroy
delegate :name, to: :dish_category, prefix: "category"
delegate :restaurant, to: :dish_category
end
class Dish < ActiveRecord::Base
belongs_to :dish_category
end
餐厅管理员
...
def upvote
@restaurant = Restaurant.find(params[:id])
@dish = Dish.find(params[:id])
@dish.liked_by current_user
redirect_to @restaurant
end
def downvote
@restaurant = Restaurant.find(params[:id])
@dish = Dish.find(params[:id])
@dish.disliked_by current_user
redirect_to @restaurant
end
...
路线
resources :restaurants do
member do
put "upvote", to: "restaurants#upvote"
put "downvote", to: "restaurants#downvote"
end
end
餐厅 - 显示视图
...
<% @restaurant.dishes.each do |dish| %>
<div>
<h2><%= dish.category_name %></h2>
<b><%= dish.name %></b>
<%= link_to "Upvote", like_restaurant_path(dish), method: :put %>
<%= link_to "Downvote", dislike_restaurant_path(dish), method: :put %>
</div>
<% end %>
需要做很多事情才能让它发挥作用。首要任务是将我的控制器操作移至我的餐具控制器。我还添加了另外两个操作:unlike
和 undislike
用于切换功能。
NOTE:非注册用户liking/disliking菜品的鉴权逻辑还需要写,但是这个应该可以帮助您入门。
菜品控制器
class DishesController < ApplicationController
before_action :load_restaurant_and_dish, only: [:like, :unlike, :dislike, :undislike]
def like
@dish.liked_by current_user
redirect_to @restaurant
end
def unlike
@dish.unliked_by current_user
redirect_to @restaurant
end
def dislike
@dish.disliked_by current_user
redirect_to @restaurant
end
def undislike
@dish.undisliked_by current_user
redirect_to @restaurant
end
private
def load_restaurant_and_dish
@dish = Dish.find(params[:id])
@restaurant = @dish.restaurant
end
end
接下来是配置我的路线以对应我的餐厅和菜肴模型:
路线
resources :restaurants do
resources :dishes, only: [:like, :unlike, :dislike, :undislike] do
member do
put "like", to: "dishes#like"
put "unlike", to: "dishes#unlike"
put "dislike", to: "dishes#dislike"
put "undislike", to: "dishes#undislike"
end
end
end
我最终重构了我的显示视图并创建了一些部分以减少混乱,因为现在涉及到一些逻辑:
餐厅 - 显示视图
...
<%= render "restaurants/dish_partials/dishes" %>
...
部分菜肴
<% @dishes.each do |dish| %>
<div>
<h2><%= dish.category_name %></h2>
<span><b><%= dish.name %></b></span>
<%= render "restaurants/dish_partials/like_toggle", dish: dish %>
</div>
<% end %>
点赞切换部分
<% if current_user.liked? dish %>
<%= link_to "Unlike", unlike_restaurant_dish_path(@restaurant, dish), method: :put %>
<% else %>
<%= link_to "Like", like_restaurant_dish_path(@restaurant, dish), method: :put %>
<% end %>
<% if current_user.disliked? dish %>
<%= link_to "Undislike", undislike_restaurant_dish_path(@restaurant, dish), method: :put %>
<% else %>
<%= link_to "Dislike", dislike_restaurant_dish_path(@restaurant, dish), method: :put %>
<% end %>
我有一个 Restaurant
型号 has_many :dishes, through: dish_categories
。我找到了一个 post,它展示了如何编写必要的视图代码来让 Acts As Votable gem 的事情顺利进行。我的情况有所不同,因为菜肴模型是正在投票的嵌套资源。
我尝试翻译提供的代码但无济于事。在这一点上,我应该为菜肴创建一个新的控制器并将可投票的动作放在那里吗?如果是这样,我将如何设置我的路线以便我可以在我的餐厅的展示页面上完成此操作?
型号
class Restaurant < ActiveRecord::Base
has_many :dish_categories, dependent: :destroy
has_many :dishes, through: :dish_categories
end
class DishCategory < ActiveRecord::Base
belongs_to :restaurant
has_many :dishes, dependent: :destroy
delegate :name, to: :dish_category, prefix: "category"
delegate :restaurant, to: :dish_category
end
class Dish < ActiveRecord::Base
belongs_to :dish_category
end
餐厅管理员
...
def upvote
@restaurant = Restaurant.find(params[:id])
@dish = Dish.find(params[:id])
@dish.liked_by current_user
redirect_to @restaurant
end
def downvote
@restaurant = Restaurant.find(params[:id])
@dish = Dish.find(params[:id])
@dish.disliked_by current_user
redirect_to @restaurant
end
...
路线
resources :restaurants do
member do
put "upvote", to: "restaurants#upvote"
put "downvote", to: "restaurants#downvote"
end
end
餐厅 - 显示视图
...
<% @restaurant.dishes.each do |dish| %>
<div>
<h2><%= dish.category_name %></h2>
<b><%= dish.name %></b>
<%= link_to "Upvote", like_restaurant_path(dish), method: :put %>
<%= link_to "Downvote", dislike_restaurant_path(dish), method: :put %>
</div>
<% end %>
需要做很多事情才能让它发挥作用。首要任务是将我的控制器操作移至我的餐具控制器。我还添加了另外两个操作:unlike
和 undislike
用于切换功能。
NOTE:非注册用户liking/disliking菜品的鉴权逻辑还需要写,但是这个应该可以帮助您入门。
菜品控制器
class DishesController < ApplicationController
before_action :load_restaurant_and_dish, only: [:like, :unlike, :dislike, :undislike]
def like
@dish.liked_by current_user
redirect_to @restaurant
end
def unlike
@dish.unliked_by current_user
redirect_to @restaurant
end
def dislike
@dish.disliked_by current_user
redirect_to @restaurant
end
def undislike
@dish.undisliked_by current_user
redirect_to @restaurant
end
private
def load_restaurant_and_dish
@dish = Dish.find(params[:id])
@restaurant = @dish.restaurant
end
end
接下来是配置我的路线以对应我的餐厅和菜肴模型:
路线
resources :restaurants do
resources :dishes, only: [:like, :unlike, :dislike, :undislike] do
member do
put "like", to: "dishes#like"
put "unlike", to: "dishes#unlike"
put "dislike", to: "dishes#dislike"
put "undislike", to: "dishes#undislike"
end
end
end
我最终重构了我的显示视图并创建了一些部分以减少混乱,因为现在涉及到一些逻辑:
餐厅 - 显示视图
...
<%= render "restaurants/dish_partials/dishes" %>
...
部分菜肴
<% @dishes.each do |dish| %>
<div>
<h2><%= dish.category_name %></h2>
<span><b><%= dish.name %></b></span>
<%= render "restaurants/dish_partials/like_toggle", dish: dish %>
</div>
<% end %>
点赞切换部分
<% if current_user.liked? dish %>
<%= link_to "Unlike", unlike_restaurant_dish_path(@restaurant, dish), method: :put %>
<% else %>
<%= link_to "Like", like_restaurant_dish_path(@restaurant, dish), method: :put %>
<% end %>
<% if current_user.disliked? dish %>
<%= link_to "Undislike", undislike_restaurant_dish_path(@restaurant, dish), method: :put %>
<% else %>
<%= link_to "Dislike", dislike_restaurant_dish_path(@restaurant, dish), method: :put %>
<% end %>