Habtm et array

Bonjour à tous,
Je tourne un peu en rond avec une relation habtm…

J’ai un modèle “Carnets”, un modèle “Fiches” et
un modèle “Liens” qui joint les deux.

Si je veux connaitre toutes les fiches du carnet 1 pas de pb,
idem pour connaître tous les carnets qui ont la fiche 1.

Mais comment arriver à trouver tous les carnets qui
ont les fiches qui ont la même condition ?

je fais :

@fiches = Fiche.find(:all, :conditions => "annees = '1990'") @carnetsde1990 = @fiches.carnets

J’ai une erreur de type “métode non définie pour carnets”.

Comme indiqué plus haut ce code marche :

@fiches = Fiche.find(1)
@carnetsde1990 = @fiches.carnets

Je pense bloquer sur habtm et array, est-ce que cela sauve mon honneur ?
:wink:
Merci de vos lumières !

Ben

Salut,

Sans connaitre precisement ton schema de base de donnees, je pense que
ce
qu’il te faut c’est le “many-to-many” (n’existe pas tel quel avec
Rails).
De tete et sans tester:

class Lien < ActiveRecord::Base
belongs_to :carnet
belongs_to :fiche
end

class Fiche < ActiveRecord::Base
has_many :liens
has_many :carnets, :through => :liens
end

class Carnet < ActiveRecord::Base
has_many :liens
has_many :fiches, :through => :liens
end

… et maintenant tu veux faire des requetes un peu speciales, tu
rajoutes
cette ligne dans Carnet

has_many :carnets_of_1990,
:through=>:liens,
:class_name=> “Fiche”,
:conditions=> [conditions]

pour ta conditions, il faut voir dans les logs de webrick quelle requete
il
te genere et plus particulierement quelles tables il utilise de maniere
a
creer une conditions du type:
[“fiches.annee = 1990”]

Question: annee peut il etre aussi dans Lien ? Auquel cas, cela devient
vraiment simple:

has_many :carnets_of_1990,
:through=>:liens,
:class_name=> “Fiche”,
:conditions=> [“annee = 1990”]

En esperant, que cela t’aide. N’hesite pas a envoyer ton code + messages
d’erreur.
a+

Did

2006/7/24, iben [email protected]:

didier lafforgue <[email protected]…> writes:

Question: annee peut il etre aussi dans Lien ?
Auquel cas, cela devient vraiment
simple:has_many :carnets_of_1990,
:through=>:liens, :class_name=> “Fiche”,
:conditions=> [“annee = 1990”]
En esperant, que cela t’aide.
N’hesite pas a envoyer ton code + messages d’erreur.a+Â Did

Merci, c’est pas encore ça mais j’ai tout basculé en has_many :throught
et je pense que je me rapproche.

Dans mon modèle Carnet j’ai entré ça :

has_many :carnet_1990, :through => :liens, :class_name => "Fiche", :conditions => ["Fiche.annee = '1990'"]

et dans la console pour test, j’obtient ça :

Guide.find(1).carnet_1900
NoMethodError: undefined method
carnet_1990' for #<Guide:0x2731698> from /usr/lib/ruby/gems/1.8/gems/ activerecord-1.14.3/lib/active_record/base.rb:1792:inmethod_missing’
from (irb):16
from :0

J’ai essayé différentes formes de conditions mais rien de mieux !

Année ne peut pas être dans Lien, car s’il doit y avoir une date ça
sera celle de la création du Lien mais
pas de la Fiche.

Merci

et dans la console pour test, j’obtient ça :

Guide.find(1).carnet_1900
NoMethodError: undefined method
carnet_1990' for #<Guide:0x2731698> from /usr/lib/ruby/gems/1.8/gems/ activerecord-1.14.3/lib/active_record/base.rb:1792:inmethod_missing’
from (irb):16
from :0

Aie, je suis perdu, c’est quoi Guide ??? Guide = Carnet ? Des que tu
auras
resole ce probleme de NoMethodError, envoie moi la requete sql.

didier lafforgue <[email protected]…> writes:

Aie, je suis perdu, c’est quoi Guide ???
Guide = Carnet ? Des que tu auras resole ce probleme de
NoMethodError, envoie moi la requete sql.

Arf dans la pagaille je teste des changements de nom de
base au cas où ça viendrait de là … et ça multiplie les erreurs.

class Carnet < ActiveRecord::Base
has_many :liens
has_many :fiches, :through => :liens
has_many :carnet_1990,
:through => :liens,
:source => :item,
:class_name => “Item”,
:conditions => [“annee = ‘1990’”]

class GuideController < ApplicationController
@carnet = Carnet.find(1).carnet_1990
#find_all = undefined method `carnet_1990’

Vue :
<% @carnet.each do |c| %>

  • <%=h c.nom %>

  • <% end %>

    J’ai en résultat les noms des 3 fiches de 1990 mais pas les 3 titres des
    carnets.

    log :

    [0mSELECT fiches.* FROM fiches INNER JOIN liens ON
    fiches.id = liens.fiche_id WHERE (liens.carnet_id =

    1. e[0m
      e[4;36;1mCarnet Load (0.004476)e[0m e[0;1mSELECT
      carnets.* FROM carnets INNER JOIN liens ON
      carnets.id = liens.carnet_id WHERE (liens.fiche_id = 1) e[0m
      e[4;35;1mFiche Load (0.007638)e[0m e[0mSELECT fiches.* FROM
      fiches INNER JOIN liens ON fiches.id =
      liens.fiche_id WHERE (liens.carnet_id = 1 AND ((annee = ‘1990’)))

    allez je t’ai trouve la soluce. De maniere generale et c’est une
    convention
    (je suis desole pour les pro-Toubon), toutes les variables + noms de
    methodes + noms de classe doivent etre en anglais. D’autant plus que M.
    Rails utilisent pas mal de raccourcis pour les pluriels et cie.

    class Card < ActiveRecord::Base
    has_many :subscriptions
    has_many :books, :through => :subscriptions
    end

    class Subscription < ActiveRecord::Base
    belongs_to :book
    belongs_to :card
    end

    et la plus importante

    class Book < ActiveRecord::Base
    has_many :subscriptions
    has_many :cards, :through => :subscriptions

    def self.find_from_year(year)
    self.find(:all, :select => “books.*”,
    :include => [ :subscriptions, :cards ], :conditions =>
    [‘cards.year= ?’, year])
    end
    end

    et dans ta vue:

      <% Book.find_from_year('1990').each do |book| %>
    • <%=h book.name %>
    • <% end %>

    sinon ceci marche mais tu auras des doublons ========> EN GROS CRADE
    —> dans le controller
    Card.find(:all, :conditions => “year = ‘1990’”)

    —> dans ta vue:

      <% @cards.each do |card| %> <% card.books.each do |book| %>
    • <%=h book.name %>
    • <% end %> <% end %>

    A mon avis pour la 1ere solution, tu n’es pas oblige d’utilise un modele
    dedie a la relation (subscription dans mon cas), si tu crees juste une
    table
    books_cards (convention), cela devrait marcher.

    Amuse toi bien.

    Didier

    2006/7/24, Ben [email protected]:

    p lafforgue <[email protected]…> writes:

    toutes les variables + noms de methodes + noms de
    classe doivent etre en anglais. D’autant plus que M. >Rails utilisent
    pas mal de raccourcis pour les pluriels et cie.

    Je suis donc bon pour me refaire mes tables ! Je teste ça et te tiens
    au courant, merci.

    au fait, tu peux enlever :select => “books.*” dans la requete find, cela
    ne
    sert a rien.

    2006/7/24, didier lafforgue [email protected]:

    iben wrote:

    J’ai une erreur de type “métode non définie pour carnets”.

    En fait l’erreur est plutot simple, ton code marche très bien la seul
    chose c’est que dans ton code tu cherche avec find toutes les fiches, il
    te renvoi donc un tableau ou nil.

    Dans ton cas il te faut donc quelque chose du genre:

    @fiches = Fiche.find(:all, :conditions => "annees = '1990'") for fiche in @fiches @carnetsde1990 << fiche.carnets end

    cela devrai fonctionner.

    Pour la petite astuce, tu peux aussi pre-charger les champs fils (soit
    les carnets dans ton cas) en ajoutant :include => [:carnets] dans ton
    find, cela t’evitera de faire des requettes dans ta boucle.

    Ton code deviendrai donc:

    @fiches = Fiche.find(:all, :conditions => "annees = '1990'", :include => [:carnets]) for fiche in @fiches @carnetsde1990 << fiche.carnets end

    Je pense bloquer sur habtm et array, est-ce que cela sauve mon honneur ? :wink:

    Non, en tous cas pas pour moi :wink:

    Merci de vos lumières !

    Lumières, lumières, à toi de voir :slight_smile:

    Ben

    En espérant que ca te soit utile,

    P.S.: Je viens de me lire la partie sur ActiveRecord de “Agile Web
    Development with Rails 2nd ed” et je doit dire que ca aide bien pour ce
    genre de problème.

    Avec la solution de Didier (has_many :through) et mes tables
    version anglais j’ai réussi à faire ce que je
    voulais. ^^
    Me reste à tenter la version de sebastien (avec habtm) sur une appli
    propre !

    encore merci à vous
    Ben

    Sébastien Grosjean (ZenCocoon <[email protected]…> writes:

    <at> carnetsde1990 << fiche.carnets
    

    end

    Nouvelle tentative avec ta propositin avant de renommer toutes mes
    tables :

    “You have a nil object when you didn’t expect it!
    You might have expected an instance of Array.
    The error occured while evaluating nil.<<”

    Est-ce parce que je suis désormais en has_many :through et plus en habtm
    ?

    P.S.: Je viens de me lire la partie sur ActiveRecord de “Agile Web
    Development with Rails 2nd ed” et je doit dire que ca aide bien pour ce
    genre de problème.

    Je n’ai que l’édition 1 en fr (version papier) et c’est vrai qu’il y a
    beaucoup
    de choses mais pas tout !

    Merci
    Ben

    Sébastien Grosjean (ZenCocoon <[email protected]…> writes:

    Pour le cas de tester, c’est ce que j’ai fait en fait Et pour ma
    part cela marche au poil.

    Je n’ai plus d’erreurs avec l’initialisation du tableau
    mais en revanche les réponses sont mauvaise :

    @fiches = Card.find(:all, :conditions => "year = '1990'", :include => [:books])
     @carnetsde1990 = []
    for fiche in  @fiches
        @carnetsde1990 << fiche.books
    end
    

    => j’utilise mon appli de test avec Book, Card et Souscriptions,
    histoire d’avoir de l’anglais dans les modeles

    avec dans la vue :

    <% @carnetsde1990.each do |c| %>
  • <%=h c.name %>
  • <% end %>

    ==> m’affiche deux réponses : Book et Book au lieu de “Livre 1 Livre 2”.

    Je suis un manche.

    iben wrote:

    “You have a nil object when you didn’t expect it!
    You might have expected an instance of Array.
    The error occured while evaluating nil.<<”

    Exacte, il te faut initialiser le tableau avant je pense, donc le code
    devrai etre:

    @fiches.find(:all, :conditions =< "annees = '1990'", :include => [:carnets])

    @carnetsde1990 = []
    for fiche in @fiches
    @carnetsde1990 << fiche.carnets
    end

    Est-ce parce que je suis désormais en has_many :through et plus en habtm ?

    Ca je ne sais pas.

    Pour le cas de tester, c’est ce que j’ai fait en fait :wink: Et pour ma
    part cela marche au poil.

    Sébastien Grosjean (ZenCocoon <[email protected]…> writes:

    Je doit dire que j’ai un peu de mal à te suivre.

    Je pense que le plus simple serai que tu puisse fournir ton code, tes
    models et insertion en base (pourquoi pas avec pastie:
    http://pastie.caboo.se/ )

    Voilà le code de la des modèles et de la vue.
    http://pastie.caboo.se/6084

    Comme je disais, je n’ai que des Books qui ont pour “name”
    Livre 1, Livre 2 etc, je ne comprends pas pourquoi dans les
    réponses ils me donne le nom de la table (Book) !

    iben wrote:

    Voilà le code de la des modèles et de la vue. http://pastie.caboo.se/6084

    Comme je disais, je n’ai que des Books qui ont pour “name”
    Livre 1, Livre 2 etc, je ne comprends pas pourquoi dans les
    réponses ils me donne le nom de la table (Book) !

    Pourrais tu ajouter:

    p @carnetsde1990 </code

    Ã la fin de ton def index dans ListController et copier me renvoyer le
    résultat.

    Comme ca je n’ai aucune idée du problème. Pour ma part je n’ai jamais
    utiliser has_many avec :through mais plutot habtm pour ce genre de chose
    mais je ne pense pas que le problème vienne de la.

    iben wrote:

    <% @carnetsde1990.each do |c| %>
  • <%=h c.name %>
  • <% end %>

    ==> m’affiche deux réponses : Book et Book au lieu de “Livre 1 Livre 2”.

    Je doit dire que j’ai un peu de mal à te suivre.

    Je pense que le plus simple serai que tu puisse fournir ton code, tes
    models et insertion en base (pourquoi pas avec pastie:
    http://pastie.caboo.se/ )

    Sébastien Grosjean (ZenCocoon <[email protected]…> writes:

    utiliser has_many avec :through mais plutot habtm pour ce genre de chose
    mais je ne pense pas que le problème vienne de la.

    Ca donne la même chose :confused:

    code modifié : http://pastie.caboo.se/6084

    (c’est top ce pastie !)

    iben wrote:

    Ca donne la même chose :confused:

    code modifié : http://pastie.caboo.se/6084

    Essaye avec http://pastie.caboo.se/6090 pour ton controller et copie la
    sortie de webrick stp.

    Cela semble bon pour le moment donc à voir plus loin :wink:

    (c’est top ce pastie !)

    Comme tu dis, très bon outil :wink:

    Ca donne la même chose :confused:

    code modifié : http://pastie.caboo.se/6084

    Mets un :

    @carnetsde1990.flatten!

    ou bien, remplace le #<< :

    for fiche in @fiches
    @carnetsde1990 += fiche.books
    end

    sois bien conscient aussi que des carnets peuvent
    se retrouver plusieurs fois, puisque tu as une relation N-N
    fiches <-> carnets.

    РJean-Fran̤ois.

    Jean-François <[email protected]…> writes:

    carnetsde1990 += fiche.books
    end

    CA MARCHE :sunglasses:
    Mais j’ai effectivement des doublons.

    glaçons(pastis.51) pour tous !

    This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

    | Privacy Policy | Terms of Service | Remote Ruby Jobs