这是模块中与STI模型有任何关联的最干净的方法吗



以下方法有效,但它是最干净的方法吗?

简而言之,一个项目:has_many Tasks。任务由STI表表示,任务的不同子类在Task::module(和子目录):中

# schema
create_table projects do |t|
  # t.integer :id  - implicitly generated
end
create_table task_bases do |t|
  # t.integer :id  - implicitly generated
  t.string    :type        # for STI support
  t.integer   :project_id
end
# file: app/models/project.rb
class Project < ActiveRecord::Base
  :has_many :tasks, :class_name => "Task::Base", :dependent => :destroy
end
# file: app/models/task.rb
module Task
  def self.table_name_prefix
    "task_"
  end
end
# file: app/models/task/base.rb
module Task
  class Base < ActiveRecord::Base
    :belongs_to :project
  end
end
# file app/models/task/priority.rb
module Task
  class Priority < Base
    :belongs_to :project
  end
end

几个问题:

  • 任务::Base永远不应该被实例化——我们只会使用它的子类。我认为这意味着我将它声明为abstract_class——正确的方法是什么
  • 将STI表命名为tasks而不是task_bases会更好吗?如果是,还需要进行哪些更改
  • 我应该为:class_name => "Task::Base"声明感到困扰吗

如前所述,上述方法有效。但在常见的情况下,您有一个Task::模块、一个Task::基类和几个Task::Base的子类,下面的更干净:

使用模块名称定义STI表

create_table task_bases do |t|
  # t.integer :id  - implicitly generated
  t.string    :type        # for STI support
  t.integer   :project_id
end

创建应用程序/模型/<module_name>.rb

这个文件只包括<module_name>子目录中的所有文件:

# file: app/models/task.rb
module Task
  require 'task/base'  # comment out unless task/base.rb must be loaded first
  Dir[Rails.root.join("app/models/task/**/*.rb").to_s].each {|f| require f}
end

创建app/models/<module_name>/base.rb

将所有子类通用的任何功能放在这里。请注意,这是我们定义STI表名称的地方。

# file: app/models/task/base.rb
module Task
  class Base < ActiveRecord::Base
    self.table_name = 'tasks'
    # include common functionality here
  end
end

创建您需要的任何子类

# file: app/models/task/batch.rb
module Task
  class Batch < Base
    # batch specific code here
  end
end
# file: app/models/task/sequential.rb
module Task
  class Sequential < Base
    # sequential specific code here
  end
end

最新更新