在Ruby on Rails中将类拆分为多个文件

时间:2011-03-09 04:56:04

标签: ruby-on-rails model

我正在尝试将大型模型拆分为多个文件以进行逻辑组织。所以我有两个文件:

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 个答案:

答案 0 :(得分:9)

我知道我的回答有点晚了,但我刚刚在我的一个应用程序中做了这个,所以我想发布我用过的解决方案。

让我们这是我的模特:

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给你的额外清洁度,它完美地运作。希望这能解决这个老问题。

答案 1 :(得分:5)

这篇文章很好地提出了解决这个问题的方法:

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

答案 2 :(得分:2)

我知道我迟到了,但在试图弄清楚如何做到这一点时,我偶然发现了这个问题。

我认为类重新打开的原因在示例代码中没有按预期工作的答案是该类最初被定义为:

(在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方式',但它确实在我的特定情况下运行良好。

答案 3 :(得分:1)

有一个叫做modularity的整洁宝石,可以完全满足您的需求。

关于如何正确拆分它们的一个很好的指南是gem-session

答案 4 :(得分:1)

如果你真的试图将一个类拆分成两个文件(类似于C#中的部分类),我不知道这样做的红宝石友好方式。

然而,通过Mixins获得具有相当功能(包括大量方法)的类的一种常见方法。模块可以混合到一个类中,它们的方法实际上包含在类中。