使用Acts As Votable gem投票给嵌套对象

时间:2015-07-13 17:50:33

标签: ruby-on-rails ruby controller routes

我有一个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 %>

1 个答案:

答案 0 :(得分:2)

要使其发挥作用,还需要做很多事情。第一项业务是将我的控制器动作移动到我的餐具控制器上。我还添加了两个操作:unlikeundislike用于切换功能。

注意:用于验证未注册的用户喜欢/不喜欢菜肴的逻辑仍然需要写入,但这应该有助于您入门。

菜肴控制器

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 Partial

<% @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 %>