Relation entre 3 models

Salut,

J’ai le besoins de faire une application contenant les models suivants:

  • house
  • season
  • tariff

Je suppose que vous avez déjà compris le principe :wink:

En fait au final je souhaiterai avoir les relations suivantes:

1) une maison à plusieurs saisons et chacune de ces saisons à un tarif

associé

  • house.seasons et house.seasons[0].tariff

2) un tarif correspond à une saison et cette ensemble appartient à une

maison

  • tariff.season.house

3) une saison à plusieurs maisons et cette ensemble à un tarif

  • season.houses et season.houses[0].tariff

Je dois dire que pour mettre en place de relation je bloque, toute aide
sera plus qu’aprécié :wink:

Sébastien Grosjean - ZenCocoon

Salut Sébastien,

1) une maison à plusieurs saisons et chacune de ces saisons à un tarif

Je dois dire que pour mettre en place de relation je bloque, toute aide
sera plus qu’aprécié :wink:

Je n’ai étudié ton problème que moins de 10 minutes, mais je me demande
si les conditions 2 et 3 sont compatibles. Voilà un début de piste.

Tu rajoutes un modèle Reservation ou Booking parce que tu as choisi
de tout coder en anglais.

class House < AR::B
has_many :bookings
has_many :seasons, :through :booking
has_many :tariffs, :through :booking
end

class Season < AR::B
has_many :bookings
has_many :houses, :through :booking
has_many :tariffs, :through :booking
end

class Tariff < AR::B
has_one :tariff
end

class Booking < AR::B
belongs_to :house
belongs_to :season
belongs_to :tariff
end

la table bookings a les champs house_id, season_id, tariff_id.

1/ Pas vérifié que toutes les associations que tu voulais marche
(d’ailleurs pas testé le code :slight_smile:
2/ jamais essayé des has_many :through avec des 1:n / 1:1
je dirais que ça devrait marcher (au pire rajouter une méthode
dans House par ex)
3/ Schéma pas forcément optimal (Tariff, ya qu’un champ tarif ?
ça peut se transformer en colonne pour la table bookings, etc).

Voilà , c’est un point de départ.

– Jean-François.

Jean-François wrote:

En fait au final je souhaiterai avoir les relations suivantes:

has_many :bookings
class Tariff < AR::B

– Jean-François.
J’ai pas essayé mais dans le concept je doute que cela puisse
fonctionner comme je l’attend. J’ai posé la même question sur rails
weenie, toujours sans réponse valide.

Pour tous les anglophone, plus d’info serons disponible si vous avez
l’envie, le courage, … de me filer un coups de main sur cette enigme
:wink:

Voici l’url:
http://rails.techno-weenie.net/question/2006/9/12/logic-relation-between-model-house-season-and-tariff


Sébastien Grosjean - ZenCocoon

D’après les explications initiales je n’arrive pas à déterminer si des
saisons peuvent être associées à des maisons mais sans tarif
correspondant.
Si on suppose que non, le modèle proposé par Guillaume me convient bien.
Ce qui donnerait ça (en espérant que la superbe mise en forme soit respectée)


| maisons | | tarifs | | saisons |
----------- <-----> ------------- <-----> -----------
| id | | maison_id | | id |
----------- | saison_id | -----------
-------------

Pour ce qui est de la traduction ensuite en modèles ActiveRecord
j’utiliserais has_many :through pour mettre en place des raccourcis
entre
Maison et Saison.

Ca doit donner quelque chose dans le style suivant

Maison
has_many :tarifs
has_many :saisons, :through => :tarifs

Tarif
belongs_to :maison
belongs_to :saison

Saison
has_many :tarifs
has_many :maisons, :through => :tarifs

Les réserves de base :

  1. Si l’hypothèse de départ est fausse forcément ça marche beaucoup moins
    bien…
  2. Tout ceci écrit sans filet et sans test bien évidemment :wink:

HTH,
Stéphane.

Salut Guillaume,

Guillaume B. wrote:

salut !

je suis très grand débutant en RoR, par contre je connais les BdD.

petite question : combien de saisons manipules-tu ? si la réponse est 2
(période “été” et période “reste de l’année”), ca ne sert strictement à
rien de faire une classe saison. saison pourra etre un simple attribut
de la table des tarifs.

Nous somme d’accord, hors dans mon cas mon nombres de saisons doit être
illimité.

si tu en manipules plusieurs (par exemple tu crées une saison
“artificielle” par vacances scolaires), à ce moment tu peux imaginer les
tables suivantes :

  • maisons (id,adresse,nb_chambres,…)
  • saisons (id,date_debut,date_fin,…)
  • tarif (id_maison, id_saison, montant,…)

Je fonctionne en effet de la sorte, et avec un model de BDD identique au
tiens.

Hors mon problème été (maintenant solutionné, réponse à venir) comment
géré mes model avec ActiveRecord

Merci pour ton coup de main Guillaume,

Sébastien Grosjean - ZenCocoon

salut !

je suis très grand débutant en RoR, par contre je connais les BdD.

petite question : combien de saisons manipules-tu ? si la réponse est 2
(période “été” et période “reste de l’année”), ca ne sert strictement à
rien de faire une classe saison. saison pourra etre un simple attribut
de la table des tarifs.

si tu en manipules plusieurs (par exemple tu crées une saison
“artificielle” par vacances scolaires), à ce moment tu peux imaginer les
tables suivantes :

  • maisons (id,adresse,nb_chambres,…)
  • saisons (id,date_debut,date_fin,…)
  • tarif (id_maison, id_saison, montant,…)

je ne sais pas trop traduire ca en belongs_to et has_many, mais j’espere
t’avoir un peu
aidé.
gUI

Stéphane Thibaudeau wrote:

D’après les explications initiales je n’arrive pas à déterminer si des
saisons peuvent être associées à des maisons mais sans tarif
correspondant.

Pas besoins non

Pour ce qui est de la traduction ensuite en modèles ActiveRecord
belongs_to :maison
belongs_to :saison

Saison
has_many :tarifs
has_many :maisons, :through => :tarifs

Les réserves de base :

  1. Si l’hypothèse de départ est fausse forcément ça marche beaucoup moins
    bien…
  2. Tout ceci écrit sans filet et sans test bien évidemment :wink:

Beau sans filet car l’idee de base et la, j’ai maintenant une solution
fonctionnel avec 2-3 finnesse en plus mais la base et la.

Pour les interressé voici le recap général qui répond bien à mes besoins:

# 001_create_houses.rb class CreateHouses < ActiveRecord::Migration def self.up create_table :houses do |t| t.column :name, :string end end

def self.down
drop_table :houses
end
end

002_create_tariffs.rb

class CreateTariffs < ActiveRecord::Migration
def self.up
create_table :tariffs do |t|
t.column :house_id, :integer
t.column :season_id, :integer
t.column :price, :string
end
end

def self.down
drop_table :tariffs
end
end

003_create_seasons.rb

class CreateSeasons < ActiveRecord::Migration
def self.up
create_table :seasons do |t|
t.column :name, :string
end
end

def self.down
drop_table :seasons
end
end

app/models/house.rb

class House < ActiveRecord::Base
has_many :tariffs do
def find_by_season( season )
find_by_season_id( season.id )
end
end
has_many :seasons, :through => :tariffs
end

app/models/tariff.rb

class Tariff < ActiveRecord::Base
belongs_to :season
belongs_to :house
validate_uniqueness_of :house, :scope => :season_id
end

app/models/season.rb

class Season < ActiveRecord::Base
has_many :tariffs
has_many :houses, :through => :tariffs
end

Une fois tous cela mis en place, voila quelques exemple d’utilisation:

# Insertion initial grace à la console house1 = House.create(:name => 'House 1') house2 = House.create(:name => 'House 2') house3 = House.create(:name => 'House 3')

high_season = Season.create(:name => ‘High’)
medium_season = Season.create(:name => ‘Medium’)
low_season = Season.create(:name => ‘Low’)

house1.seasons << high_season
house1.seasons << medium_season

house2.seasons << high_season

Créer des tarifs

house1.tariffs.create( :season => high_season, :price => 1000 )
house1.tariffs.create( :season => medium_season, :price => 500 )

Trouver le tarif pour un saison, dependant d’une maison

house1.tariffs.find_by_season( high_season )

OU

house1.tariffs.detect { |t| t.season_id = high_season.id }

Trouver toutes les maisons avec un tarif durant la saison souhaité

high_season.houses

Ou de trouver les tariffs, puis trouver les maisons

tariffs.find( :all, :conditions => {:season => high_season}, :include =>
:houses )

Et voila au final au solution que je trouve simple et logic tous en
répondant à mes attentes. Je souhaiterai remercier “liquid” de rails
weenie pour m’avoir donner cette solution.

Merci à Stéphane, Guillaume et Jean-François pour votre aide.

Sébastien Grosjean - ZenCocoon