Разделение класса на несколько файлов в Ruby on Rails - PullRequest
12 голосов
/ 09 марта 2011

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

model1.rb

class Model1 < ActiveRecord::Base
  before_destroy :destroying
  has_many :things, :dependent=>:destroy

  def method1
    ...
  end
  def method2
    ...
  end

end
require 'model1_section1'

model1_section1.rb

class Model1
  def method3
    ...
  end
  def self.class_method4
    ...
  end
end

но когда приложение загружается, и происходит вызов Model1.class_method4, я получаю:

undefined method `class_method4' for #<Class:0x92534d0>

Я также пытался это сделать по требованию:

require File.join(File.dirname(__FILE__), 'model1_section1')

Что я здесь не так делаю?

Ответы [ 5 ]

9 голосов
/ 02 июня 2012

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

Давайте это моя модель:

class Model1 < ActiveRecord::Base

  # Stuff you'd like to keep in here
  before_destroy :destroying
  has_many :things, :dependent => :destroy

  def method1
  end
  def method2
  end

  # Stuff you'd like to extract
  before_create :to_creation_stuff
  scope :really_great_ones, #...

  def method3
  end
  def method4
  end
end

Вы можете изменить его на:

# app/models/model1.rb
require 'app/models/model1_mixins/extra_stuff'
class Model1 < ActiveRecord::Base

  include Model1Mixins::ExtraStuff

  # Stuff you'd like to keep in here
  before_destroy :destroying
  has_many :things, :dependent => :destroy

  def method1
  end
  def method2
  end
end

и:

# app/models/model1_mixins/extra_stuff.rb
module Model1Mixins::ExtraStuff

  extend ActiveSupport::Concern

  included do
    before_create :to_creation_stuff
    scope :really_great_ones, #...
  end

  def method3
  end
  def method4
  end
end

Он отлично работает благодаря дополнительной чистоте, которую дает вам ActiveSupport::Concern. Надеюсь, что это решает этот старый вопрос.

5 голосов
/ 23 мая 2013

Вот статья, которая хорошо предлагает решения этой проблемы:

http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/

2 голосов
/ 20 октября 2012

Я знаю, что опаздываю, но, пытаясь понять, как это сделать сам, я наткнулся на этот вопрос.

Я думаю, что ответ на вопрос, почему повторное открытие класса не работаеткак ожидается в примере кода, класс первоначально определяется как:

(в model1.rb)

class Model1 < ActiveRecord::Base

, а затем вновь открывается как: (в model1_section1.rb)

class Model1

то есть во втором определении отсутствует унаследованный класс.

Я использовал отдельные файлы .rb, чтобы разделить мои огромные модели, и они отлично сработали для меня.Хотя я признаю, что использовал include и что-то еще подобное:

(в workcase.rb)

  class Workcase < ActiveRecord::Base
    include AuthorizationsWorkcase
    include WorkcaseMakePublic
    include WorkcasePostActions

    after_create :set_post_create_attributes 
    # associations, etc

    # rest of my core model definition
  end

(в workcase_make_public.rb)

  module WorkcaseMakePublic
    def alt_url_subject
      self.subject.gsub(/[^a-zA-Z0-9]/, '_').downcase
    end
    # more object definitions
  end

  class Workcase < ActiveRecord::Base
    def self.get_my_stuff
      do_something_non_instance_related
    end
    # more class definitions
  end  

Это позволило мне включить методы класса и объекта в каждый включенный файл .rb.Единственное предостережение (поскольку я не использовал расширение проблем) заключалось в том, что для доступа к константам класса из методов объекта модуля требовалось, чтобы константа была квалифицирована по имени класса (например, Workcase :: SOME_CONST), а не напрямую, как было бы допустимоесли вызвано в первичном файле.

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

Может быть, это не так 'Rails way ', но, похоже, это хорошо работает в моем конкретном сценарии.

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

Если вы в буквальном смысле пытаетесь разделить класс на два файла (аналогично частичным классам в C #), я не знаю, как с этим справиться.

Однако, один из распространенных способов получить классы, обладающие значительной функциональностью (включая большое количество методов), - это Mixins .Модули могут быть смешаны в класс, и их методы буквально включены в класс.

1 голос
/ 09 марта 2011

Существует аккуратный камень под названием modularity , который будет делать именно то, что вы хотите.

Хорошее руководство о том, как правильно их разделить, находится на gem-session .

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