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

<% %w[all problema target keyword messaggio servizio].each do |cat| %> <% end %>

<% 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

Temi più frequenti

<%= render_tag_cloud(@taxbranch) %>