2009-12-29 13 views
2

J'utilise 2 modèles JOINTESRails rendent XML d'un INNER JOIN

class Product < ActiveRecord::Base 
    has_and_belongs_to_many :providers 
end 
class Provider < ActiveRecord::Base 
    has_and_belongs_to_many :products 
end 

et mon contrôleur ressemble à ce

class ProductsController < ApplicationController 
    @products = Product.find( 
     :all, 
     :joins => :providers, 
     :select => "providers.id, providers.title, products.id, products.title, products.price", 
     :limit => 10) 
    respond_to do |format| 
     format.xml { render :xml => @products } 
     format.json { render :json => @products } 
    end 
    end 
end 

Les @products ne sont pas rendus comme prévu. Seules les colonnes du modèle de produit sont affichées dans le fichier XML. J'ai essayé de changer la ligne de format.xml à

format.xml { render :xml => @products.to_xml(:include => :providers) } 

mais ce n'est pas ce que je veux. Comme vous pouvez voir mes requêtes SQL pour 5 colonnes

SELECT providers.id, providers.title, products.id, products.title, products.price 
FROM `products` 
INNER JOIN `products_providers` ON `products_providers`.product_id = `products`.id 
INNER JOIN `providers` ON `providers`.id = `products_providers`.provider_id 
LIMIT 10 

mais dans mon XML 3 seulement sont montrés. La méthode to_xml génère aussi des requêtes SQL extran et je ne le veux pas.

Quelqu'un peut-il me fournir une information sur la façon de dire aux rails de rendre tous mes champs SQL? Je veux aussi que le code soit optimisé.

La conception XML/JSON idéal serait

<products type="array"> 
<product> 
    <id type="integer">1</id> 
    <price type="decimal">9.99</price> 
    <title type="string">Sanke Rolex</title> 
    <provider> 
    <id type="string">1</id> 
    <title type="string"></title> 
    </provider> 
</product> 
</products> 

THX!

Répondre

4

Je ne comprends pas pourquoi vous vous limitez à certaines colonnes du paramètre :select lorsque vous avez clairement indiqué que vous souhaitez que la sortie XML contienne tous les attributs.

Le code plus optimisé serait:

@products = Product.all(:include => :providers, :limit => 10) 
respond_to do |format| 
    format.xml { render :xml => @products.to_xml(:include => :providers) } 
    format.json { render :json => @products.to_json(:include => :providers) } 
end 

J'utilise :include au lieu de :joins dans le viseur, ce qui signifie AR utilisera 2 requêtes SQL pour aller chercher les premiers produits puis les fournisseurs, ce qui est plus rapide avec plus tables qu'une jointure.

Pour exclure certaines colonnes privées de montrer dans la sortie XML, utilisez :except

@products.to_xml(
    :except => [:price], 
    :include => { :providers => {:except => [:title]} } 
) 

Vous voulez presque toujours, puisque chaque modèle contient des informations à ne pas être publiquement exposés.

1

Dans les cas où je veux une sortie très spécifique, j'utilise un Builder template au lieu du raccourci render: xml. C'est assez simple.

+0

Qu'en est-il du format JSON? Je voudrais créer une @ variable variable universelle qui peut être convertie en n'importe quel format - XML, JSON – xpepermint

+0

Et comment puis-je accéder aux informations à partir des deux tabels. La seule façon de voir est d'utiliser AS-SELECT products.id AS product_id ... – xpepermint