在Rails中干燥重复的方法和路由

时间:2016-11-14 17:04:08

标签: ruby-on-rails ruby

我是ruby / rails的新手,我有3个资源的情况,这些资源使用acts_as_votable gem提供的注释。问题是,我在所有资源中添加了必要的方法和路线,从而产生完全的非干像差。

我的路线是:

 Rails.application.routes.draw do
  root to: 'home#index'

  get 'home/index', to: 'home#index'

  resources :users

  get 'thinga/tagged/:tag', to: 'thinga#tags', as: 'tagged_thingas'
  get 'thingb/tagged/:tag', to: 'thingb#tags', as: 'tagged_thingbs'

  resources :thinga do
    member do
      get :like
      get :dislike
      get :unvote
    end
  end

  resources :thingb do
    member do
      get :like
      get :dislike
      get :unvote
    end
  end

  resources :thingc, only: [:create, :update, :destroy] do
    member do
      get :like
      get :dislike
      get :unvote
    end
  end

  devise_for :users, path: 'auth',
  :controllers => { :omniauth_callbacks => 'omniauth_callbacks' }
end

在控制器中重复的代码是

  def like
    @thinga = Thinga.find(params[:id])
    @thinga.liked_by current_user
    respond_to do |format|
      format.html { redirect_to :back }
      format.js { render layout: false }
    end
  end

  def dislike
    @thinga = Thinga.find(params[:id])
    @thinga.disliked_by current_user
    respond_to do |format|
      format.html { redirect_to :back }
      format.js { render layout: false }
    end
  end

  def unvote
    @thinga = Thinga.find(params[:id])
    @thinga.unvote_by current_user
    respond_to do |format|
      format.html { redirect_to :back }
      format.js { render layout: false }
    end
  end

有人可以帮我学习如何干掉这个案子吗?谢谢。

2 个答案:

答案 0 :(得分:2)

尝试铁路路线问题

http://edgeguides.rubyonrails.org/routing.html#routing-concerns

而且我认为你能够做到这一点

concern :votable do
  member do
    get :like
    get :dislike
    get :unvote
  end
end

resources :thinga, :thingb, :concerns => :votable
resources :thingc, :concerns => :votable, only: [:create, :update, :destroy]

对于控制器 - 创建VotablesController并将ThingasControllerThingbsController子类化。您可以调用before操作来设置@votable实例变量,并让子类设置变量。共享方法将在一个地方。

class VotablesController < ApplicationController

  before_action :set_votable

  def like
    @votable.liked_by current_user
    respond_to do |format|
      format.html { redirect_to :back }
      format.js { render layout: false }
    end
  end

  def dislike
    @votable.disliked_by current_user
    respond_to do |format|
      format.html { redirect_to :back }
      format.js { render layout: false }
    end
  end

  def unvote
    @votable.unvote_by current_user
    respond_to do |format|
      format.html { redirect_to :back }
      format.js { render layout: false }
    end
  end

end

在子类中(这是事物的一个例子)

class ThingasController < VotablesController

  def set_votable
    @votable = Thinga.find(params[:id])
  end

end

答案 1 :(得分:0)

Ruby为使用代码编写代码(元编程)提供了很多空间,因此您应该能够编写一个方法来完成为您添加重复路由的工作。可能会运行以下代码:

Rails.application.routes.draw do
  def create_votes_resources(name, options = {})
    resources name, options do
      member do
        get :like
        get :dislike
        get :unvote
      end
    end
  end

  create_votes_resources :thing_a
  create_votes_resources :thing_b
  create_votes_resources :thing_c, only: [:create, :update, :destroy]
end