Domanda

UPDATE

OK, l'ho capito. Ho dovuto chiamare quanto segue per le varietà:

<%=h @user.varieties.find_by_product_id(product.id).name %>

Ecco le mie due domande seguenti:

(1) Questo causerà problemi durante la modifica / eliminazione dei record perché non sto chiamando il modello di join? Ho visto alcuni video di Ryan Bates in cui sottolinea questo punto, ma ho problemi a cercare di fare riferimento al modello di join qui. In altre parole, il codice sopra riportato dovrebbe essere chiamato attraverso user_products?

Se uso il seguente codice, che fa riferimento alla tabella di join, sono in grado di ottenerlo per visualizzare variety_id dalla tabella di join (poiché non esiste una colonna nome per le varietà nella tabella di join). Non sono sicuro di come fare in modo che questo codice faccia riferimento a User Load (0.7ms) SELECT * FROM "users" WHERE ("users"."id" = 2) nella tabella dei join, ma poi vai alla tabella delle varietà per ottenere il nome effettivo della varietà da & Quot; name & Quot; colonna.

<% @user.products.each do |product| %>
   <% @user.user_products.find_by_product_id(product.id).variety_id %>
<% end %> 

(2) Questa roba complessa è posizionata correttamente nel livello di visualizzazione o esiste un modo migliore per spostarla nel modello o nel controller?

Grazie.

La domanda originale di seguito è ora risolta ...

Ho i seguenti modelli:
- utenti
- prodotti
- varietà - user_products

Ecco la versione reale di ciò che sto cercando di fare. Diciamo che l'utente è un negozio di alimentari. I prodotti sono frutti, come le mele. E le varietà sono tipi di mele, come fuji e mcintosh.

Devo creare un'app in cui:

  • Un utente può aggiungere molti tipi di prodotti alla sua pagina. I prodotti possono includere più varietà, ma l'utente NON è tenuto a includere alcuna varietà. Ad esempio, Topps Grocery Store può aggiungere mele alla loro pagina. Se questo è tutto ciò che vogliono visualizzare, deve essere ok. Tuttavia, possono anche aggiungere ulteriori dettagli includendo i tipi di mele che trasportano, come fuji, mcintosh, ecc. La varietà non può essere solo un prodotto dettagliato. In altre parole, non posso fare in modo che ogni prodotto sia qualcosa come apple - fuji, apple - mcintosh. Devono essere due modelli separati.

  • Nella pagina dell'utente (ad es. " show " view), devo essere in grado di visualizzare sia il prodotto che la varietà (se presenti). Il sistema deve capire che le varietà sono collegate al prodotto particolare per questo particolare utente.

Dopo la prima risposta che ho ricevuto, ho rivisto i miei modelli come descritto nella risposta di seguito. Ogni varietà appartiene a un prodotto, cioè fuji appartiene solo al prodotto Apple, che è un ID distinto nella tabella del prodotto. Inoltre, un prodotto ha molte varietà, ovvero il prodotto a base di mela potrebbe avere 5 o 10 varietà diverse.

Tuttavia, diventa più complicato perché ogni utente potrebbe avere un diverso set di combinazioni prodotto / varietà. Ad esempio, il negozio di alimentari Topps (utente) potrebbe avere mele (prodotto) che sono fuji e mcintosh (varietà). Ma il negozio di alimentari Publix (utente) potrebbe avere mele (prodotto) che sono deliziose rosse e gala (varietà).

Nella pagina utente, voglio essere in grado di richiamare ogni prodotto trasportato dall'utente e quindi visualizzare le varietà collegate a ciascuno di questi prodotti se l'utente ha scelto una varietà.

Quando provo il codice elencato di seguito nella vista spettacolo, ottengo il seguente errore: metodo indefinito `user_product 'per #:

<% @user.products.each do |product| %>
   <% @user.user_products.find_by_product_id(product.id).varieties %>
<% end %>

D'altra parte, quando provo l'altra opzione che mi hai dato (elencato di seguito), la pagina viene caricata e la query sql appare proprio nel registro, ma nessuna varietà viene visualizzata nella pagina, il che è strano perché ho controllato tre volte e ci sono record nel database che dovrebbero corrispondere alla query. Dettagli sotto ...

<% @user.products.each do |product| %>
   <% @user.varieties.find_by_product_id(product.id) %>
<% end %>    

Questo codice esegue la seguente query sql:

Variety Load (0.5ms) SELECT "varieties".* FROM "varieties" INNER JOIN "user_product" ON "varieties".id = "user_products".variety_id WHERE (("seasons".user_id = 2))

Product Load (0.7ms) SELECT "products".* FROM "products" INNER JOIN "user_product" ON "products".id = "user_products".product_id WHERE (("user_products".user_id = 2))

Modello di rendering in layout / applicazione
Rendering utenti / spettacolo

Variety Load (0.4ms) SELECT "varieties".* FROM "varieties" INNER JOIN "user_product" ON "varieties".id = "user_products".variety_id WHERE ("varieties"."product_id" = 1) AND (("user_products".user_id = 2)) LIMIT 1

Variety Load (0.2ms) SELECT "varieties".* FROM "varieties" INNER JOIN "user_products" ON "varieties".id = "user_products".variety_id WHERE ("varieties"."product_id" = 2) AND (("user_products".user_id = 2)) LIMIT 1

user_id=2, he does have product_id=1 and product_id=2 in the database. And, in the user_products table, I do have a few records that list this user_id connected to each of these product_ids and associated with some variety_ids.

In questo caso sopra, l'utente che sto guardando è #<User_product:0x4211bb0> Quindi sembra che dovrei mostrare alcuni risultati nella mia visualizzazione, ma non ottengo nulla.

Infine, quando provo quanto segue:

<% @user.products.each do |product| %>
   <%=h @user.user_products.find_by_product_id(product.id) %>
<% end %>

Nelle mie visualizzazioni per ogni record viene visualizzato quanto segue: <=>

È stato utile?

Soluzione

A mio modo di vedere, è che non hai molte o molte relazioni con i prodotti. Lo hai al prodotto di quella particolare varietà (se presente). Quindi, per tenerne traccia, userei un modello in più. In questo modo saresti in grado di mantenere anche il rapporto tra prodotti e varietà.

I modelli:

class User < ActiveRecord::Base
  has_many :user_products, :dependent => :destroy
  has_many :products, :through => :user_products
  has_many :varieties, :through => :user_products
end

class UserProduct < ActiveRecord::Base
  belongs_to :user
  belongs_to :product
  belongs_to :variety
end

class Product < ActiveRecord::Base
  has_many :varieties
end

class Variety < ActiveRecord::Base
  belongs_to :product
end

Il controller:

class UserProductsController < ApplicationController
    before_filter do 
        @user = User.find(params['user_id'])
    end


    def create
      product = Product.find(params['product_id'])
      variety = Variety.find(params['variety_id']) if params['variety_id']

      @user_product = UserProduct.new
      @user_product.user = user
      @user_product.product = product
      @user_product.variety = variety
      @user_product.save
    end

    def destroy
        # Either do something like this:
        conditions = {:user_id => @user.id}
        conditions[:product_id] = params[:product_id] if params[:product_id]
        conditions[:variety_id] = params[:variety_id] if params[:variety_id]

        UserProduct.destroy_all conditions
    end
end

Le visualizzazioni: Se non sei interessato a raggruppare le varietà nei diversi prodotti e semplicemente inseriscili in un elenco, è sufficiente:

# users/show.html.erb
<%= render @user.user_products %>

# user_products/_user_product.html.erb
<%= h user_product.product.name %> 
<%= h user_product.variety.name if user_product.variety %>

Altrimenti bisogna aggiungere qualcosa di un po 'più complicato. È possibile che alcuni possano essere inseriti nel modello e nel controller utilizzando i proxy di associazione, ma non posso aiutarti lì

# users/show
<% for product in @user.products do %>
    <%= product.name %>
    <%= render :partial => 'variety', 
        :collection => @user.varieties.find_by_product_id(product.id) %>
<% end %>

# users/_variety
<%= variety.name %> 

Naturalmente non è necessario dividerlo in parziali (e in questo esempio, forse un po 'ridicolo), ma aiuta a separare le diverse parti, specialmente se si desidera aggiungere più elementi da visualizzare.

E per rispondere alle tue domande:

  1. Poiché UserProduct è un modello di join, non è necessario tenere traccia del proprio ID individuale. Hai l'utente, il prodotto e la varietà (in quei casi esiste). Questo è tutto ciò di cui hai bisogno, quella combinazione è unica e quindi puoi trovare il record per la cancellazione. Inoltre, un modello di join non dovrebbe mai essere modificato (a condizione che non ci siano più attributi rispetto a questi campi). È o crea o elimina, poiché tutto ciò che fa è mantenere le associazioni.
  2. Dal momento che è fondamentalmente una cosa di visualizzazione, è meglio posizionarlo nelle viste. Puoi ovviamente usare il controller o il modello per raccogliere in anticipo tutti i prodotti e le varietà facendo qualcosa del genere:

Spostare tutta la logica nel controller e nel modello probabilmente non è una buona idea poiché non dovrebbero sapere (o preoccuparsi) di come visualizzare i dati. Quindi si tratta solo di prepararlo abbastanza.

@products_for_user = []
@user.products.each do |product|
 collected_product = {:product => product, 
                      :varieties => @user.varieties.find_by_product_id(product.id)}
  @products_for_user << collected_product
end

Altri suggerimenti

MikeH

Potresti avere solo un refuso qui, @user.user_product dovrebbe essere @user.user_products

  

Quando provo il codice elencato di seguito in   la vista spettacolo, ottengo il seguente   errore: metodo indefinito `user_product '   per #:

<% @user.products.each do |product| %>  
  <% @user.user_product.find_by_product_id(product.id).varieties %>  
<% end %>

Inoltre potresti considerare un sistema di tipo gerarchico, in cui hai solo prodotti come " Fuji " ;, " Macintosh " ;, e " Mele < !> quot ;.

&

quot; quot Fuji &; e " Macintosh " avrebbe quindi una colonna " parent_id " impostato sull'id di " Mele " ;.

Solo un pensiero.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top