svergeylen / collector

Collector : site de gestion des BD, films, DVD, jeux de société, ...
2 stars 0 forks source link

Généricité #34

Closed dvergeylen closed 6 years ago

dvergeylen commented 6 years ago

Coucou,

J'ai parcouru un peu le code et surtout les liens entre les différentes tables. C'est pas mal du tout, mais je pense qu'il y aurait moyen d'apporter + de généricité, ce qui ajouterait de la flexibilité.

Pour l'instant, il y a les relations (l'historique étant qu'on encode des BDs uniquement):

Category → Series → Item Item → Authors (+ itemauthors)

Je pense qu'on pourrait améliorer le schéma en faisant:

Ceci voudrait dire que:

De cette façon faire des requêtes revient à filtrer sur les Tags et mettre en page. Par exemple,

# Liste des livres en PDF
Item.joins(:tags).where(tags: {name: ["livre", "pdf"]})

Et on pourrait même exclure des tags, par exemple:

# Liste des livres qui ne sont pas des BDs
Item.joins(:tags).where(tags: {name: ["livre"]}).where.not(tags: {name: ["BD"]})

# Liste des bonzaï qui ne sont pas des graines
Item.joins(:tags).where(tags: {name: ["bonzaï"]}).where.not(tags: {name: ["graines"]})

Comme ce sont des tableaux, il y a évidemment moyen de filtrer sur plusieurs tags systématiquement.

Je pense que ça simplifierait drastiquement la DB, puisque les catégories mais aussi les auteurs et les séries deviendraient des tags, ce qui permettrait de filtrer sur plusieurs d'entre eux à la fois et de totalement s'abstraire de comment encoder ça dans la DB. :smile:

Edit: Si tu veux garder des types préfaits, tu peux le faire via scope:

# app/models/item.rb
scope :bds, -> { joins(:tags).where({tags: {name: "BD"}})}

# Accessibles par
Item.bds

Scopes en rails

svergeylen commented 6 years ago

Haha, merci pour l'intérêt vers le collector :-)

Je pense avoir pu résoudre cette demande... ou en tout ca avoir bien avancé dans ce sens... (La raison du controlleur "authors" était historique mai effectivement, cela n'a plus de sens de mettre des auteur à des bonsais je te l'accorde !)

Dans la version mise en ligne aujourd'hui, tu retrouves :

Pour les séries, je voudrais garder cela dans un controlleur séparé des tags, parce que cela a beaucoup de sens pour 95% de la banque de données et cela garde du sens pour les autres types plus spéciaux comme les bonsais (mais finalement, même les bonsais classés par type de plante, c'est assez cohérent)

Donc au final, cela donne dans tes suggestions

dvergeylen commented 6 years ago

Category supprimée; --> Je souhaite garder les cétagories

Je ne comprends pas la différence entre une Category et un Tag, puisque les tags ont une relation self-join.

Series renommée en Tag --> Je souhaite garder les séries

Je ne comprends pas la différence non plus.

svergeylen commented 6 years ago

Ce n'est pas un soucis de compréhension, mais un choix de design... On a eu au bureau un gars qui voulait stocker la documentation sans plus aucune structure et mettre plein de tags sur tous les documents pour pouvoir filtrer naturellement en multi-critères... un gros bide, personne ne s'y est retrouvé, personne ne mettait des tags, et au final, on a créé une structure rigide dossier/sous dossier pour s'y retrouver :-(

Que voudrai-tu faire exactement avec des tags ? filtrer par tag ? Naviguer par tag ? Remplacer la recherche par mot clé ? Je ne vois pas l'intéret de faire des recherche qui donnerait des livres et des bonsais dans les résultats... Si tu expliques l'objectif poursuivi, je comprendrai sans doute ce que tu veux proposer... mais là, cela ressemble à un concept "nouveau" que je n'ai jamais rencontré et que Luc et Vince n'accorcheront pas trop je crois...

As-tu esayé les tags qui existent déjà aujourd'hui ?? Peut-etre pourrais-tu proposer un truc sur base de ca ?

dvergeylen commented 6 years ago

Le problème avec la structure actuelle est qu'il faut systématiquement rentrer dans le moule Category > Series > Item, ce qui convient pour une grande partie des items (BDs), mais pas toujours...

Par exemple, tu as créé une Category "Romans" dans laquelle Series sont des thèmes ("Science-fiction"). Le problème est que tu as du créer une Série 'Werber' (qui est un auteur!) car ses livres ne sont pas vraiment classables dans des thèmes particuliers. Et comment on fait pour filtrer sur les BDs de type science-fiction? (Réponse: c'est impossible)

Tu connais L., il va vouloir ajouter des références de pièces de catamaran, pour lesquelles il va créer une catégorie 'matériel', série 'catamaran'. Mais là il va tomber sur le manuel et/ou la préparation au permis Mer (qui sont des livres), donc il va créer une catégorie Livres Voile (il y a déjà livres techniques et livres automobiles) série 'catamaran' (aïe, conflit, il en existe déjà une!), et en plus l'un est à Noirmoutier et l'autre non, donc il va ajouter un Tag Noirmoutier. Mais alors, pourquoi est-ce que Noirmoutier est un tag alors que Voyage & patrimoine ont une série France (qui est une série et pas un tag!)?

Et si j'achète un livre sur Neuschwanstein, je dois le mettre dans Voyages&Patrimoine > Allemagne, alors que d'autres ouvrages sur les châteaux sont déjà dans la série France, donc pas au même endroit...

Il y a un routard "Chateau de la Loire" dans France et un routard dans la série Portugal (WTF? Routard n'est pas une série alors?). Moi j'ai un routard Milan et un routard Corse, je les mets dans quoi?

J'ai des livres de cuisine, mais dois-je les mettre dans "Livres Cuisine" (nouvelle catégorie) > "Poisson" (nouvelle série) > Nom du livre ou "Livres techniques" > "Cuisine" > Nom du livre (et tant pis pour son thème, ballot quand on fait de la cuisine)? :confused:

J'ai pris des exemples un peu forts exprès mais ça illustre quand même pas mal (j'aimerais pouvoir filtrer sur "chateaux" ou "BD et Science-fiction", ce qui parait raisonnable). Tous ces problèmes viennent du fait qu'il est impossible de faire des associations many to many parce que la structure Category > Series > Item est figée.

Ce que je propose c'est de se libérer de cette structure figée en faisant en sorte

Là où c'est le plus intéressant c'est qu'on puisse continuer à avoir l'interface existante pour la majorité des écrans. Par exemple, l'interface avec les Bds ne doit pas changer, mais le serveur en background associe la nouvelle série à son Tag parent BD et crée les auteurs comme étant des tags.

Idem quand on browse, on peut très bien continuer à parcourir depuis les tags qui n'ont pas de parents, puis quand on clique arriver sur ses enfants etc... Ce qui simule Category > Series > ... sauf qu'on a une profondeur flexible! :smiley: En plus, un même item peut se retrouver en plusieurs endroits de la hiérarchie s'il correspond à plusieurs catégories!

La difficulté du concept est qu'il ne faut pas voir la DB comme un registre papier virtualisé, mais comme un vrai graphe avec des liens entre les entités créées (impossible à faire sur papier, ou alors tu dupliques les entrées comme dans un certain cahier Atoma bleu :laughing: ).

@vergeylen L., je te cite pour que tu reçoives un e-mail de notification, tu peux voir toute la discussion avec St. en cliquant sur "view on Github" ci-dessous. :kissing_heart:

svergeylen commented 6 years ago

Cela me semble une bonne idée, mais largement différent de ce qui existe aujourd'hui.... je ne vois pas directement comment implémenter tout cela... (améliorer les tags est 100% une bonne idée, supprimer les séries et catégories viendront quand les tags seront nickels. Svp ne pas virer les séries et les catégories avant que cela ne soit nickel de ton coté)

svergeylen commented 6 years ago

j'ai poursuivi le blabla sur ton pull request...

svergeylen commented 6 years ago

Branche dev. Commit 975d1fc

svergeylen commented 6 years ago

Le message du pull request de Daniel était :

J'ai écrit les instructions pour migrer les Series et les Categories vers les Tags. Je pense n'avoir rien oublié.

Evidemment, l'idéal est de tester avant de migrer, voici comment faire:

cd /tmp
git clone https://github.com/dvergeylen/collector dvergeylen-collector
cd dvergeylen-collector/
scp [USER]@[VPS]:[HOME/]collector/db/data.yml db/
bundle install
bundle exec rake db:setup
bundle exec rake db:rollback
bundle exec rake db:data:load
bundle exec rake db:migrate

Ensuite, il faut migrer les valeurs de Serie et Category vers Tags (SANS supprimer ces deux modèles):

# Créer arborescence minimale:
livres            = Tag.create(name: "📚 livres")
bd                = Tag.create(name: "📘 bandes dessinées")
themes            = Tag.create(name: "🏷 thèmes")
auteurs           = Tag.create(name: "🖌 auteurs")
romans            = Tag.create(name: "📕 romans")
voyages           = Tag.create(name: "🏰 ✈ voyages & patrimoines")
bonsais           = Tag.create(name: "🌳 bonsaïs")
livres_techniques = Tag.create(name: "⚙ livres techniques")
livres_beaux      = Tag.create(name: "📗 beaux livres")
series            = Tag.create(name: "✨ séries")

sf = Tag.create(name: "🚀 science-fiction")
hs = Tag.create(name: "🏰 historique")
ph = Tag.create(name: "🤔 philosophie")
so = Tag.create(name: "🌌 space opera")
th = Tag.create(name: "🔎 thrillers")

# Lier les tags entre eux:
livres.tags << [bd, romans, livres_techniques, livres_beaux]
bd.tags     << [series, themes, auteurs]
romans.tags << [themes, auteurs]
themes.tags << [sf, hs, ph, so, th]

# Transfert des Categories et Series vers de nouveaux Tags
adder = User.first

# Tous les Tags dont category_id égale celles de Bande Dessinées (la 'categorie') ou 'Romans'
# sont des tags représentants des auteurs de BD/Romans.
# Ils doivent donc avoir 'auteurs' (tag) pour parent
# et leurs Items doivent avoir le Tag BD/Romans.
category_BD     = Category.find_by(name: "Bandes dessinées")
category_roman  = Category.find_by(name: "Romans")
[[category_BD, bd], [category_roman, romans]].each do |cat, parent_tag|
  Tag.where(category_id: cat.id).each do |auteur|
    auteur.parent_tags << auteurs
    auteur.items.each do |item|
      item.tags << [livres, parent_tag, auteurs, auteur]
      item.adder = adder if item.adder.nil? # Needed bcs of validation
      item.save
    end
  end
end

# Toutes les Séries dont category_id égale celle de Bande Dessinées (la 'categorie')
# doivent être converties en Tag et ceux-ci associés au Tag 'series'.
# Les Items de ces séries doivent recevoir ce nouveau tag également.
category_BD = Category.find_by(name: "Bandes dessinées")
Series.where(category_id: category_BD).each do |serie|
  serie_as_tag = Tag.create(name: serie.name)
  serie_as_tag.parent_tags << series
  serie.items.each do |album|
    album.tags << [series, serie_as_tag]
  end
end

# Toutes les Séries dont category_id égale celle de Romans (la 'categorie')
# doivent être converties en Tag et ceux-ci associés au Tag 'romans'.
# Les Items de ces séries doivent recevoir ce nouveau tag également.
category_roman = Category.find_by(name: "Romans")
Series.where(category_id: category_roman).each do |serie|
  theme_as_tag = Tag.create(name: serie.name)
  theme_as_tag.parent_tags << themes
  theme_as_tag.save
  serie.items.each do |roman|
    roman.tags << [themes, theme_as_tag]
  end
end

# Toutes les Séries dont category_id égale celle de Voyages&Patrimoine (la 'categorie')
# doivent être converties en Tag et ceux-ci associés au Tag 'voyages'.
# Les Items de ces séries doivent recevoir ce nouveau tag également.
category_vp = Category.find_by(name: "Voyages et patrimoine ")
Series.where(category_id: category_vp).each do |serie|
  tag = Tag.create(name: serie.name)
  tag.parent_tags << voyages
  tag.save
  serie.items.each do |item|
    item.tags << [voyages, tag]
  end
end

# Toutes les Séries dont category_id égale celle de Bande Dessinées (la 'categorie')
# doivent être converties en Tag et ceux-ci associés au Tag 'series'.
# Les Items de ces séries doivent recevoir ce nouveau tag également.
category_livres_tech = Category.find_by(name: "Livres techniques")
Series.where(category_id: category_livres_tech).each do |serie|
  tag = Tag.create(name: serie.name)
  tag.parent_tags << livres_techniques
  tag.save
  serie.items.each do |item|
    item.tags << [livres, livres_techniques, tag]
  end
end

# Toutes les Séries dont category_id égale celle de Bonzaï (la 'categorie')
# doivent être converties en Tag et ceux-ci associés au Tag 'bonzais'.
# Les Items de ces séries doivent recevoir ce nouveau tag également.
category_bonzais = Category.find_by(name: "Bonsais")
Series.where(category_id: category_bonzais).each do |serie|
  bonsai_as_tag = Tag.create(name: serie.name)
  bonsai_as_tag.parent_tags << bonsais
  bonsai_as_tag.save
  serie.items.each do |item|
    item.tags << [bonsais, bonsai_as_tag]
  end
end

J'ai TOUT testé, normalement tout marche. A ce stade, Series et Category deviennent redondants, il faut alors adapter les vues pour créer de bonnes combinaisons de tags quand on enregistre des BD / Romans / Series etc...

svergeylen commented 6 years ago

OK, je ferme ce point car il est subdivisé en mille autres points avec l'étiquette "ownertags"... je travaille dessus