Это самый чистый подход для: has_many ассоциации с моделями ИППП в модуле? - PullRequest
0 голосов
/ 13 января 2012

Следующее работает, но это самый чистый подход?

Короче говоря, проект: has_many Задачи.Задачи представлены таблицей STI, а различные подклассы задач находятся в модуле Task :: (и подкаталоге):

# 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

Пара вопросов:

  • Task ::База никогда не должна создаваться - мы будем использовать только ее подклассы.Я думаю, это означает, что я объявляю это как abstract_class - как правильно это сделать?
  • Было бы лучше назвать таблицу STI tasks, а не task_bases, и если да, то чтодругие изменения должны произойти?
  • Должен ли я быть обеспокоен объявлением :class_name => "Task::Base"?

1 Ответ

0 голосов
/ 08 апреля 2012

Как уже упоминалось выше, работает.Но в общем случае, когда у вас есть Task :: module, класс Task :: Base и несколько подклассов 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

create app / models / <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

create 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
...