8

tener una aplicación de comercio electrónico en desarrollo Estoy tratando de entender el siguiente problema: Tengo mis categorías realizadas a través del plugin awesome_nested_set. Si enumero mis artículos seleccionando una categoría todo funciona bien, pero para algunos enlaces quiero mostrar todos los productos de una categoría y los productos de sus categorías secundarias.obtener todos los productos de categoría y categorías de niños (rieles, awesome_nested_set)

aquí es el código de controlador que funciona bien con una sola categoría:

# products_controller.rb 
    def index 
    if params[:category] 
     @category = Category.find(params[:category]) 
     #@products = @category.product_list 
     @products = @category.products 
    else 
     @category = false 
     @products = Product.scoped 
    end 
    @products = @products.where("title like ?", "%" + params[:title] + "%") if params[:title] 
    @products = @products.order("created_at).page(params[:page]).per(params[:per_page] ? params[:per_page] : 25) 
    @categories = Category.all 
    end 

La línea Comenté a cabo es un método de ayuda que escribí yo mismo en la categoría de modelo que devuelve todos los productos de la categoría y su hijo categorías en una matriz.

Se define como sigue:

# app/models/category.rb 
def product_list 
    self_and_ancestors.to_a.collect! { |x| x.products } 
end 

Ahora, cuando me descomentar esta línea y tratar de seleccionar las pausas código de una categoría mis productos controlador con errores como

undefined method `order' for #<Array:0x1887c2c> 

o

undefined method `page' for #<Array:0x1887c2c> 

porque estoy usando el orden y la paginación y ya no puede ordenar el arario.

¿Alguna idea de cómo obtener todos los productos en un elemento Relación de ActiveRecord en mi controlador? gracias

ACTUALIZACIÓN

así, cuando utilizo el siguiente:

class Category < ActiveRecord::Base 
    acts_as_nested_set 

    attr_accessible :name, :description, :lft, :rgt, :parent_id 

    has_many :categorizations 
    has_many :products, :through => :categorizations 

    attr_accessor :product_list 

    def branch_ids 
     self_and_descendants.map(&:id).uniq 
    end 

    def all_products 
     Product.find(:all, :conditions => { :category_id => branch_ids }) 
    end 


end 

y pedir el controlador para @category.all_products me sale el siguiente error:

Mysql::Error: Unknown column 'products.category_id' in 'where clause': SELECT `products`.* FROM `products` WHERE `products`.`category_id` IN (6, 8, 9) 

¿Cómo me obtener todos los productos con esta constelación?

ACTUALIZACIÓN 2

Ok, así que voy a empezar una recompensa.

si trato:

def all_products Categorization.find (: todos,: condiciones => {: category_id => branch_ids}) final

consigo de nuevo undefined method fin' para `# Necesito saber cómo puedo obtener todos los productos de una relación many_to_many como una relación ActiveRecord.

ACTUALIZACIÓN 3

pongo el código en cuestión en una esencia https://gist.github.com/1211231

Respuesta

5

La clave con awesome_nested_set es usar un rango en la columna lft. Aquí está un ejemplo de código de cómo lo hago con una asociación directa (artículos categoría has_many)

module Category 
    extend ActiveSupport::Concern 
    included do 
     belongs_to :category 
     scope :sorted, includes(:category).order("categories.lft, #{table_name}.position") 
    end 

    module ClassMethods 
     def tree(category=nil) 
     return scoped unless category 
     scoped.includes(:category).where([ 
      "categories.tree_id=1 AND categories.lft BETWEEN ? AND ?", 
      category.lft, category.rgt 
     ]) 
     end 
    end # ClassMethods 
    end 

Entonces en algún lugar de un controlador

@category = Category.find_by_name("fruits") 
@articles = Article.tree(@category) 

que encontrará todos los artículos en las categorías manzanas, naranjas, plátanos, etc. etc. Debe adaptar esa idea con una combinación en categorizaciones (¿pero está seguro de que necesita una relación muchos a muchos aquí?)

De todos modos, probaría esto:

class Product < AR 
     has_many :categorizations 

     def self.tree(category=nil) 
     return scoped unless category 
     select("distinct(products.id), products.*"). 
     joins(:categorizations => :category).where([ 
      "categories.lft BETWEEN ? AND ?", category.lft, category.rgt 
     ]) 
     end 
end 

Quiero saber si hay alguna Gotcha

+0

esto me da un error de sintaxis .. . "/Users/frankblizzard/Sites/rails_projekte/sotaca/app/models/product.rb:56: error de sintaxis, inesperado '}', esperando tASSOC scoped.joins (: categorizations => {: category}) where ([" – tmaximini

+0

espera - creo que funciona ahora (eliminó las llaves alrededor de: categoría) - probará en profundidad ahora – tmaximini

+0

vale, hasta ahora funciona - lo único que queda es que ahora algunos artículos aparecerán dos veces - si tienen dos categorías secundarias asociadas, por ejemplo. Sé que existe el método "uniq" que resolverá los duplicados, pero de nuevo ".order" y "paginate" no funcionarán, ya que estos convierten la relación ActiveRecord en una matriz. manejar duplicados con este enfoque? – tmaximini

3

Hay varias maneras en que podría mejorar su código, pero si usted está en busca de todos los productos que pertenecen a una categoría e hijos (descendientes) de la categoría a continuación, por qué no hacerlo de esta manera:

def branch_ids 
    self_and_descendants.map(&:id).uniq 
end 

def all_products 
    Product.find(:all, :conditions => { :category_id => branch_ids }) 
end 

he hecho algunas suposiciones aquí, pero espero que se entiende la idea.

+0

gracias, lo probaré más tarde e informaré – tmaximini

+0

Hola, lo siento por volver tarde, pero ahora recuerdo que intenté algo similar. El problema es que no hay una columna "category_id" en la tabla de productos. Tengo una relación has_many: a través de la 'categorización', ya que un producto puede tener más de una categoría. Es por eso que esta consulta no funcionará. Actualizaré la pregunta. – tmaximini

+0

Reúna todas las categorizations_ids en lugar de category_ids y haga algo similar a lo que describí anteriormente o escriba un alcance nombrado que realice join en los modelos implicados ... – socjopata

0

Extendiendo respuesta charlysisto 's, cuando se trata de has_and_belongs_to_many categorías, pronto se entera de que la perspectiva de la fuerza bruta es bastante lento ... Es necesario algún tipo de "middleware" para hacerlo más rápido ...

La respuesta de socjopata ofrece un buen enfoque de cómo mejorar esto. Por lo tanto, se utiliza la definición

def branch_ids 
    self_and_descendants.map(&:id).uniq 
end 

en su archivo category.rb (modelo).

Entonces, por ejemplo, en el controlador (ejemplo con paginación):

@category = Category.find... # whatever 
branches = @category.branch_ids 
@prodcats = ProductCategory.select('distinct product_id') 
          .where('category_id IN (?)',branches) 
          .order(:product_id) 
          .paginate(page: params[:page], :per_page => 25) 
ids  = @prodcats.map(&:product_id) 
@products = Product.where('id IN (?)', ids) 

Por último, en su opinión, se necesita una "técnica" poco a fin de tener la paginación. Va a paginas en @prodcats, no @products ...

<%= will_paginate @prodcats %> 
<% @products.each do |product| %> 
    .... 
<% end %> 

Este enfoque es mucho más rápido, cuando se trata de many_to_many, aunque no al 100% políticamente correcto, debo admitir.

Cuestiones relacionadas