2015-10-03 9 views
6

Proverò a spiegare:Rails include solo le colonne selezionate dalla relazione

Ho una tabella 'Prodotto' e una tabella 'Store'. Sto cercando di ottenere solo il nome del negozio da mostrare sulla pagina, ma ActiveRecord mi sta restituendo tutte le colonne dallo store.

Ecco il codice:

@product = Product 
      .order(id: :desc) 
      .includes(:store) 
      .select("products.id, products.store_id, stores.name") 
      .limit(1) 

La query costruita (da Rails):

Processing by IndexController#index as HTML 
Product Load (0.0ms) SELECT products.id, products.store_id FROM `products` ORDER BY `products`.`id` DESC LIMIT 1 
Store Load (1.0ms) SELECT `stores`.* FROM `stores` WHERE `stores`.`id` IN (111) 

voglio solo mostrare il nome del negozio del prodotto, ma Rails sta selezionando tutte le colonne dei negozi.

I miei modelli:

Product.rb

class Product < ActiveRecord::Base 
    belongs_to :store, :foreign_key => 'store_id' 
end 

Store.rb:

class Loja < ActiveRecord::Base 
    has_many :products 
end 

Qualsiasi ideia?

risposta

5

È possibile farlo tramite coraggio e si unisce:

Product 
    .order(id: :desc) 
    .joins(:store) 
    .pluck("products.id, products.store_id, stores.name") 
    .limit(1) 

Stai andando a ottenere un array di nuovo che segue l'ordine delle colonne definite in coraggio. I've written about pluck before if you're not familiar with it.


L'altro modo è tramite una query SQL dritto:

sql =<<-EOF 
    SELECT products.id, products.store_id, stores.name 
    FROM products INNER JOIN stores 
    ON products.store_id = stores.id 
    ORDER BY products.id DESC 
    LIMIT 1 
EOF 
records = ActiveRecord::Base.connection.execute(sql) 

#=> [{"id" => X, "store_id" => Y, "name" => Z, ... }] 

Entrambe le opzioni producono la stessa istruzione SQL, il giusto variano nel modo in cui i risultati vengono fuori.

+0

L'SQL che hai dato può essere scritto direttamente usando AR. –

+0

Ma con la cotta non sarà più un oggetto, giusto? –

+0

@HonlonAguiar, giusto, restituirà una serie di valori. Questo è uno degli svantaggi di cogliere vs selezionare. –

2

Ho appena provato qualcosa di simile a questo sul mio progetto. Questo dovrebbe funzionare:

@products = Product. 
    .order(id: :desc) 
    .joins(:store) 
    .select("products.id, products.store_id, stores.name") 
    .limit(1) 

Utilizzando joins al contrario di includes farà rotaie eseguire una sola interrogazione, perché joins non ansioso-caricare l'associazione.

+0

Grazie per la risposta Ma ho già provato, sta anche caricando Tutte le colonne del negozio –

+0

Sei sicuro di non avere qualcosa sul prodotto (forse un ambito predefinito o un after_initialize) che carica i negozi? – TheSuper

+0

Sì, ho aggiornato il post con i miei modelli, dai uno sguardo –

Problemi correlati