Rails-эквивалент ApplicationController для моделей - PullRequest
1 голос
/ 13 февраля 2012

Я понимаю, что application_controller.rb - это место для размещения всех методов и т. Д., Которые вы хотели бы сделать доступными во всех ваших контроллерах, поскольку все они наследуются от этого класса.Отлично.

Но что такое эквивалент для моделей?Другими словами, я хочу место, где я мог бы создать пару суперклассов, от которых унаследуют мои модели.

Например, у меня есть метод, который ищет в разных таблицах записи во всех CAPS через REGEXP в Mysql.Я хотел бы иметь возможность создать метод только один раз и вызвать его для разных таблиц / моделей.

Как Rails это делает?

Я думал, что смогу создать класс, который будет наследовать от ActiveRecord :: Base (как это делают все модели), поместить туда методы, а затем наследовать все мои модели из этого класса.Но думал, что, несомненно, будет лучший способ сделать это.

Спасибо.

Редактировать

За ответ Семена Я редактирую пост, чтобы показать маршруты, которые я использую.Это работает сейчас:

# models/dvd.rb
require 'ModelFunctions'
class Dvd < ActiveRecord::Base
    extend ModelFunctions
    ...
end

# lib/ModelFunctions.rb
module ModelFunctions
    def detect_uppercase(object)
        case object
        ...
        where("(#{field} COLLATE utf8_bin) REGEXP '^[\w[:upper:]]{5,}' ").not_locked.reorder("LENGTH(#{field}), #{table}.#{field} ASC")
    end
end

В config / application.rb

config.autoload_paths += %W(#{config.root}/lib)

Ответы [ 2 ]

2 голосов
/ 13 февраля 2012

Взгляните на миксины, например здесь:

http://ruby -doc.org / docs / ProgrammingRuby / html / tut_modules.html

ВВ приложении Rails вы можете создать модуль в каталоге lib, который определяет ваши методы, а затем include его в ваших моделях.

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

module Common
  module ClassMethods
    def detect_uppercase(object)
      case object
      when 'dvd'
          field = 'title'
      ... 
      end    
      where("(#{field} COLLATE utf8_bin) REGEXP '^[\w[:upper:]]  {5,}').not_locked.reorder('LENGTH(title), title ASC')"
    end
  end

  def self.included(base)
    base.extend(ClassMethods)
  end
end

Теперь, когда вы включите include Common в свою модель, класс этой модели будет расширен для включения новых методов класса, и вы сможете вызывать Dvd.detect_uppercase.

1 голос
/ 13 февраля 2012

Поместите метод многократного использования в какой-то модуль рядом с вашим классом DVD.Позже вы можете переместить его в отдельный файл.

# app/models/dvd.rb
module CaseInsensitiveSearch
  def case_insensitive_search(field, value)
    # searching field for value goes here
  end
end

class Dvd
end

После расширения класса модулем вы можете использовать case_insensitive_search для этого класса.Включение модуля сделает case_insensitive_search методом экземпляра, который вам не подходит.

class Dvd
  extend CaseInsensitiveSearch
end

Dvd.case_insensitive_search("title", "foo")

И, конечно, вы можете использовать его внутри класса DVD.

class Dvd
  def self.search(query)
    case_insensitive_search("title", query)
  end
end

Dvd.search("foo")

Теперь, когда вы убедились,это работает, вы, вероятно, захотите переместить его в отдельный файл и использовать его в нескольких классах.Поместите его в lib / case_insensitive_search.rb и убедитесь, что у вас есть эта строка в config / application.rb:

config.autoload_paths += %W(#{config.root}/lib)

Теперь вы можете требовать ее везде, где хотите:

require 'case_insensitive_search'

class Dvd
  extend CaseInsensitiveSearch
end

Последнее, что я хотел бы предложить.Создайте несколько модулей со значимыми именами.Поэтому вместо CommonModel есть CaseInsensitiveSearch и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...