Tag positioning
bin/rails g scaffold TagPositioning
taxbranch:references
post:references
name:string
category:string
metadata:jsonb
# db/migrate/xxxx_create_tag_positionings.rb class CreateTagPositionings < ActiveRecord::Migration[7.1] def change create_table :tag_positionings do |t| t.references :taxbranch, null: false, foreign_key: true t.references :post, null: true, foreign_key: true t.string :name, null: false # il “termine” (es. “dolori cervicali”) t.string :category, null: false # libera: “problema”, “target”, … t.jsonb :metadata, null: false, default: {}
t.timestamps
end
add_index :tag_positionings, [:taxbranch_id, :category]
add_index :tag_positionings, [:taxbranch_id, :category, :name], unique: true
add_index :tag_positionings, :metadata, using: :gin end end
1) Flag pubblico + nuvola “positioning” Migration bin/rails g migration AddPositioningTagPublicToTaxbranches positioning_tag_public:boolean
db/migrate/XXXXXXXXXX_add_positioning_tag_public_to_taxbranches.rb
class AddPositioningTagPublicToTaxbranches < ActiveRecord::Migration[7.1] def change add_column :taxbranches, :positioning_tag_public, :boolean, default: false, null: false add_index :taxbranches, :positioning_tag_public end end
Model
app/models/taxbranch.rb
class Taxbranch < ApplicationRecord has_ancestry acts_as_list scope: [:ancestry]
has_many :tag_positionings, dependent: :destroy has_many :posts, dependent: :nullify
scope :ordered, -> { order(:position, :slug_label) } scope :home_nav, -> { where(home_nav: true).ordered } scope :positioning_on, -> { where(positioning_tag_public: true) }
# Vista etichetta leggibile (dato che hai la colonna slug_label) def display_label slug_label.presence || slug.to_s.titleize end
# Conta i tag per nuvola (public o admin) def positioning_items counts = tag_positionings.group(:name, :category).count counts.map { |(name, cat), n| { text: name, count: n, cat: cat } } end end
Mostrare la nuvola nella show pubblica del ramo (solo se pubblico)
Nella pagina che mostra un ramo (es. TreepagesController#show o la tua page equivalente), sotto al titolo:
<% if @taxbranch.positioning_tag_public? %>
Concetti collegati
<% end %>
User.create!( email_address: “markpostura@gmail.com”, password: “ChiComin67?”, password_confirmation: “ChiComin67?”, superadmin: true )
——- Versione nuova ——
app/models/tag_positioning.rb
class TagPositioning < ApplicationRecord belongs_to :post has_one :taxbranch, through: :post belongs_to :lead, optional: true
validates :name, :category, presence: true
# Evita doppioni sullo stesso post validates :name, uniqueness: { scope: [:post_id, :category] }
# Conteggio utile per nuvole o ranking scope :by_category, ->(cat) { where(category: cat) } scope :for_branch, ->(tb) { joins(:post).where(posts: { taxbranch_id: tb.id }) }
def self.cloud_for(branch, category = nil) query = joins(:post).where(posts: { taxbranch_id: branch.id }) query = query.where(category: category) if category query.group(:name).order(“count_all desc”).count end end 🌥️ Come costruire la “nuvola di tag” Esempio in un helper:
ruby Copia codice
app/helpers/tags_helper.rb
module TagsHelper def render_tag_cloud(branch, category: nil) tags = TagPositioning.cloud_for(branch, category) return content_tag(:p, “Nessun tag disponibile”) if tags.empty?
max = tags.values.max
min = tags.values.min
range = [max - min, 1].max
safe_join(
tags.map do |name, count|
weight = ((count - min) / range.to_f * 4).round + 1
link_to(
name,
"#", # in futuro potrai mettere il link SEO
class: "text-slate-600 hover:text-blue-700 text-sm font-medium tag-size-#{weight}"
)
end,
" "
) end end E CSS/Tailwind per scalare i pesi:
html Copia codice
E nel template:
erb Copia codice