Pergunta

Eu estou usando Herança de Tabela Única para o gerenciamento de diferentes tipos de projetos. Eu decidi armazenar algumas informações associadas a cada tipo de projeto. Então, eu criei novos tabela "project_types" com o campo "model_type" como chave primária. valores de chave primária são valores de campo "tipo" de mesa "projectos". Problema : Quando eu tentar obter associado com ProjectTypes objeto de projeto objeto que ele sempre retorna null.

>> p = Project.find(:first)
=> #<SiteDesign id: 1, type: "SiteDesign", name: "1", description: "dddd", concept: "d", client_id: 40, created_at: "2009-10-15 08:17:45", updated_at: "2009-10-15 08:17:45">
>> p.project_type
=> nil

Começar projetos associados com projecto ProjectTypes é OK. Existe maneira de fazer ele funciona corretamente?

Models:

class Project < ActiveRecord::Base
    belongs_to :project_type, :class_name => "ProjectTypes", :foreign_key => "model_name"
end

class SiteDesign < Project
end

class TechDesign < Project
end

class ProjectTypes < ActiveRecord::Base
  self.primary_key = "model_name"
  has_many :projects, :class_name => "Project", :foreign_key => "type"
end

Migrações:

class CreateProjectTypes < ActiveRecord::Migration
  def self.up
    create_table :project_types, :id => false  do |t|
      t.string :model_name , :null => false
      t.string :name, :null => false
      t.text :description

      t.timestamps
    end

    add_index :project_types, :model_name, :unique => true


    #all project types that are used.
    models_names = {"SiteDesign" => "Site design",
      "TechDesign" => "Tech design"}

    #key for model_name and value for name
    models_names.each do |key,value|
      p = ProjectTypes.new();
      p.model_name = key
      p.name = value
      p.save
    end

  end

  def self.down
    drop_table :project_types
  end
end

class CreateProjects < ActiveRecord::Migration
  def self.up
    create_table :projects do |t|
      t.string :type
      t.string :name
      t.text :description
      t.text :concept
      t.integer :client_id

      t.timestamps
    end
  end

  def self.down
    drop_table :projects
  end
end
Foi útil?

Solução

Não é de estranhar que você está recebendo problemas. Movendo-se de um sistema STI pura para o seu sistema atual que você está terrivelmente quebrar os padrões que você está usando, misturando partes de um com peças de outro.

Eu pessoalmente ir para algo como:

class Project < ActiveRecord::Base
    attr_readonly(:project_type)
    belongs_to :project_type
    before_create :set_project_type

    def set_project_type()
        project_type = ProjectType.find_by_model_name(this.class)
    end
end

class SiteProject < Project
end

class TechProject < Project
end

class ProjectType < ActiveRecord::Base
    has_many :projects
end

com as migrações:

class CreateProjectTypes < ActiveRecord::Migration
  def self.up
    create_table :project_types  do |t|
      t.string :model_name , :null => false
      t.string :name, :null => false
      t.text :description

      t.timestamps
    end

    add_index :project_types, :model_name, :unique => true


    #all project types that are used.
    models_names = {"SiteDesign" => "Site design",
      "TechDesign" => "Tech design"}

    #key for model_name and value for name
    models_names.each do |key,value|
      p = ProjectTypes.new();
      p.model_name = key
      p.name = value
      p.save
    end

  end

  def self.down
    drop_table :project_types
  end
end

class CreateProjects < ActiveRecord::Migration
  def self.up
    create_table :projects do |t|
      t.string :type
      t.references :project_type, :null => false
      t.text :description
      t.text :concept
      t.integer :client_id

      t.timestamps
    end
  end

  def self.down
    drop_table :projects
  end
end

Ele só limpa as coisas e ele também ajuda a esclarecer o que você está fazendo. Sua mesa 'ProjectType' é puramente para dados extra, a sua árvore de herança ainda existe. Eu também jogado em algumas verificações para garantir que o tipo de projeto é sempre definido (e corretamente, com base no nome do modelo) e você pára de mudar tipo de projeto uma vez que foi salvo por fazer o atributo somente leitura.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top