Generics Пример вопроса - PullRequest
       2

Generics Пример вопроса

4 голосов
/ 12 февраля 2011

Я довольно новичок в Ruby on Rails и, как разработчик C #, когда я хочу повторно использовать код (для класса репозитория), я мог бы поместить его в базовый класс типа <T>, чтобы иметь возможность делать как то так:

public virtual IEnumerable<T> GetAll()
{
    return Context<T>.GetAll();
}

Если мне нужно выполнить какую-либо собственную логику, я, конечно, мог бы переопределить метод в моем хранилище 'User'.

В Ruby я знаю, что вы можете сделать это:

class UsersController < ApplicationController

Это позволит получить доступ ко всем методам в ApplicationController и его родительских классах. При использовании скаффолдинга он генерирует следующий метод в каждом из моих дочерних классов:

def index
  @users = User.all

  respond_to do |format|
    format.html # index.html.erb
    format.xml  { render :xml => @users }
  end
end

В итоге я получу 10 классов с одинаковым методом, но единственное отличие - это «User.all», «Post.all» и т. Д.

Как бы я сделал этот метод универсальным, чтобы я мог поместить его в мой класс ApplicationController?

Спасибо за любую помощь, которую вы можете оказать новичку в Ruby on Rails.

Ответы [ 5 ]

4 голосов
/ 12 февраля 2011

Первое, что нужно понять о коде скаффолдинга, это то, что он может быть сокращен следующим образом:

def index
  @users = User.all
end

, если только вы не намереваетесь предоставить представление в другом формате, таком как json, html, pdf,Блок response_to не нужен.Если вы все еще чувствуете необходимость высушить этот метод, вы можете сделать что-то вроде

# app/controllers/concerns/autoload_records.rb

module AutoloadRecords
  included do
    before_action :load_records, only: :index
    before_action :load_record, only: [:create, :show, :edit, :update, :destroy]
  end

  private
  def load_records
    @records = model_class.all
  end

  def load_record
    @record = model_class.find(params[:id])
  end

  def model_class
    klass = self.class.to_s[/\A(\w+)sController\Z/,1] #=> get the name of the class from the controller Constant
    Object.const_get(klass)
  end
end

и написать свой контроллер как

class UsersController < ApplicationController
  include AutoloadRecords

  def index
    @records # => #<ActiveRecord::Relation[...]>
  end

  def show
    @record # => #<User ...>
  end

  def non_rest_action
    @record # => nil
    @records # => nil
  end
end
3 голосов
/ 12 февраля 2011

Возможно, простым решением было бы положиться на миксины.

Вы определяете модуль,

module MyModule 
   def my_index(klass)
     @elements = klass.all

     respond_to do |format|
       format.html # index.html.erb
       format.xml  { render :xml => @elements }
     end
   end
end 

Тогда у вас в контроллере,

include MyModule
def index
   my_index(User)
end 

Конечно, вам нужно использовать @elements в ваших представлениях. Если вам нужно другое имя переменной в каждом представлении, вы можете сделать

   def my_index(klass, var_name)
     self.instance_variable_set(var_name, klass.all)
     ...
   end
3 голосов
/ 12 февраля 2011

Вместо того, чтобы делать eval, где вы действительно не хотите делать один. Проверьте Унаследованные ресурсы Хосе Валима драгоценный камень. Он предоставляет стандартные методы CRUD для всех ваших контроллеров и довольно сложен. Он также тщательно протестирован, поэтому вам не нужно беспокоиться о том, чтобы ваш общий код работал должным образом во всех случаях.

Подробнее о том, как его использовать, см. На странице GitHub по ссылке.

1 голос
/ 12 февраля 2011

Есть несколько плагинов rails, которые помогают уменьшить этот тип дублирования. Этот был покрыт эпизодом Railscast 230.

https://github.com/josevalim/inherited_resources

0 голосов
/ 12 февраля 2011
  1. Исходя из моего опыта, вы редко получаете 10 индексных действий, похожих на @user = User.all. Если вы заранее знаете, что некоторые действия между различными моделями будут идентичны - тогда, возможно, имеет смысл извлечь общую логику. Но опять же, может быть, эти модели как-то связаны? Я бы не сказал заранее, что у Post и User будут одинаковые действия с индексами.
  2. Для такого короткого метода, как этот, я бы не пытался исключить повторение, потому что вы можете потерять читабельность
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...