Pregunta

estado tratando de resolver esto durante más de un día de estos, y estoy seguro de que es algo simple que me falta.

Tengo un proyecto, que puede tener una categoría principal y dos categorías opcionales. Mi código relevante para el modelo de proyecto:

has_many :project_categories

has_one  :optional_category_1,
         :through => :project_categories,
         :conditions => 'is_main_category = 0',
         :order => 'category_id',
         :source => :category,
         :class_name => 'Category'

has_one  :optional_category_2,
         :through => :project_categories,
         :conditions => 'is_main_category = 0',
         :order => 'category_id DESC',
         :source => :category,
         :class_name => 'Category'

has_one  :main_category,
         :through => :project_categories,
         :conditions => 'is_main_category = 1',
         :source => :category,
         :class_name => 'Category'

El código relevante de la clase Categoría:

has_many :project_categories
has_many :projects, :through => :project_categories, :source => :project

y de la clase ProjectCategory:

class ProjectCategory < ActiveRecord::Base
  belongs_to :project
  belongs_to :category
end

En mi punto de vista:

    Main Category: <%= f.select(:main_category, Category.find(:all, :order => 'parent_id, categories.desc').collect {|c| [c.display_name, c.id] }, :prompt => "Select a Main Category") %><br>
Optional Category 1: <%= f.select(:optional_category_1, Category.find(:all, :order => 'parent_id, categories.desc').collect {|c| [c.display_name, c.id] }, :prompt => "Select an Optional Category") %><br>
Optional Category 2: <%= f.select(:optional_category_2, Category.find(:all, :order => 'parent_id, categories.desc').collect {|c| [c.display_name, c.id] }, :prompt => "Select an Optional Category") %><br>

y en mi controlador:

      @project.attributes = params[:project]

Ok, por lo que al actualizar un proyecto existente, me sale el siguiente error:

undefined method `update_attributes' for #<Class:0x82efce0>

y el seguimiento de la pila correspondiente:

C:/Software/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.2/lib/active_record/associations.rb:1255:in `main_category='
C:/Software/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.2/lib/active_record/base.rb:2745:in `send'
C:/Software/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.2/lib/active_record/base.rb:2745:in `attributes='
C:/Software/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.2/lib/active_record/base.rb:2741:in `each'
C:/Software/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.2/lib/active_record/base.rb:2741:in `attributes='
C:/Development/craftbits_rails/app/controllers/projects_controller.rb:85:in `manage_project'

¿Está diciendo que hay un problema con main_category y que es una clase genérica? ¿Pero por qué? La asociación define correctamente AFAIK.

Cualquier ayuda apreciada!

Vikram

¿Fue útil?

Solución

Sé que esto no aborda el error que está recibiendo, pero me gustaría sugerir el uso de tres uno-a-muchas relaciones en lugar de uno a muchos-a-muchos relación.

El propósito convencional de has_many :through => ... (muchos-a-muchos) es para cuando se tiene algo así como students y classes. Un estudiante puede estar en cualquier número de clases. Una clase puede tener cualquier número de alumnos. números totalmente arbitraria en ambos lados de la relación.

Pero eso no es su situación aquí. Sus proyectos pueden estar exactamente en una categoría principal, una categoría opcional 1, y una categoría opcional 2. Es un problema totalmente diferente y no es el problema que has_many :through está diseñado para resolver.

Sugiero este arreglo:

class Project < ActiveRecord::Base

  belongs_to :main_category, :class_name => "Category",
    :foreign_key => 'main_category_id'

  belongs_to :optional_category_1, :class_name => "Category",
    :foreign_key => 'optional_category_1_id'

  belongs_to :optional_category_2, :class_name => "Category",
    :foreign_key => 'optional_category_2_id'

end

class Category < ActiveRecord::Base

  has_many :main_category_projects, :class_name => "Project",
    :foreign_key => 'main_category_id'

  has_many :optional_category_1_projects, :class_name => "Project",
    :foreign_key => 'optional_category_1_id'

  has_many :optional_category_2_projects, :class_name => "Project",
    :foreign_key => 'optional_category_2_id'

end

A continuación, podrás hacer cosas como:

my_project.main_category

my_category.optional_category_1_projects

# etc...

Otros consejos

Tal vez cambiar el controlador a algo como:

@project = Project.find(params[:id])
@project.update_attributes(params[:project])

Es posible que necesite usar main_category_id en su opinión, es decir.

Main Category: <%= f.select(:main_category_id, ...) %>

Usted está llamando update_attributes, pero main_category no es propiamente un atributo - es una asociación. main_category_id es un atributo.

¿Dónde está usted recibiendo @project de? ¿Usted apenas está haciendo un Project.find(params[:project_id]) normal o algo?

Intentó tirar en un comunicado debugger y ver qué clase de la @project es y cuáles son los métodos que tiene en él?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top