From f788181850d2a2002ceda9d557dcbc7257d2d8be Mon Sep 17 00:00:00 2001 From: Aidan Cornelius-Bell Date: Thu, 9 Jan 2025 14:16:25 +1030 Subject: [PATCH] Better handling of empty slugs particularly when set via API --- app/assets/stylesheets/application.css | 4 ++ app/models/post.rb | 58 ++++++++++++++++++++------ app/views/pubview/post.html.erb | 12 +++--- 3 files changed, 57 insertions(+), 17 deletions(-) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 5ec205e..3b75d9a 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -742,6 +742,10 @@ ul .post-item a:visited { .button { margin-bottom: 4px; } + + .button-bottomless { + margin-bottom: -8px; + } } /* Margin Notes/Footnotes */ diff --git a/app/models/post.rb b/app/models/post.rb index c763de5..b76a935 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -3,26 +3,28 @@ class Post < ApplicationRecord validates :post_type, presence: true, inclusion: { in: %w[dispatch bookmark] } validates :title, presence: true - validates :slug, presence: true, uniqueness: true, if: :dispatch? + validates :slug, uniqueness: true, allow_nil: true validates :published_at, presence: true, if: :dispatch? validates :content, presence: true, if: :dispatch? validates :url, presence: true, if: :bookmark? before_validation :set_slug, if: :new_record? before_validation :set_title_from_url, if: -> { bookmark? && title.blank? } + after_create :ensure_slug_present + after_update :ensure_slug_present scope :dispatches, -> { where(post_type: 'dispatch') } scope :bookmarks, -> { where(post_type: 'bookmark') } def self.get_posts_and_bookmarks_with_pagination(page, per_page, filter) posts = case filter - when 'posts' + when 'posts' dispatches - when 'bookmarks' + when 'bookmarks' bookmarks - else + else all - end + end posts.order(published_at: :desc).page(page).per(per_page) end @@ -56,30 +58,40 @@ class Post < ApplicationRecord tags.split(/\s*(?:,|\s+and)\s*/).map { |tag| "#{tag.strip}" }.join(', ') + '.' end - def generate_excerpt(max_length = 1040, take = 10) + def generate_excerpt(max_length = 210) return "" if content.blank? stripped_content = ActionController::Base.helpers.strip_tags(content) - excerpt = stripped_content.split('.') if stripped_content.split('.') - excerpt = excerpt.take(take) - excerpt = excerpt.join('.') + excerpt = stripped_content.split('.').first || stripped_content[0...max_length] excerpt = excerpt[0...max_length] if excerpt.length > max_length excerpt.gsub!("Dear friends,", "") + excerpt.gsub!(/\s+/, ' ') excerpt.strip end private def set_slug - self.slug = title.present? ? title.parameterize : nil + return if slug.present? + + if title.present? + self.slug = title.parameterize + elsif bookmark? + # For bookmarks without a title, create a slug based on the URL's domain + uri = URI.parse(url) + domain_slug = uri.host.gsub(/^www\./, '').parameterize + timestamp = Time.current.strftime('%Y%m%d%H%M%S') + self.slug = "#{domain_slug}-#{timestamp}" + end + rescue URI::InvalidURIError + # If URL parsing fails, fall back to UUID + self.slug = "bookmark-#{SecureRandom.uuid}" end def set_published_at self.published_at ||= Time.current end - private - def set_title_from_url return unless bookmark? && url.present? && title.blank? @@ -94,4 +106,26 @@ class Post < ApplicationRecord self.title = "Bookmark" end end + + def ensure_slug_present + return if slug.present? + + # Generate a fallback slug if none exists + fallback_slug = if title.present? + base_slug = title.parameterize + slug = base_slug + counter = 1 + # Ensure uniqueness + while Post.where.not(id: id).exists?(slug: slug) + slug = "#{base_slug}-#{counter}" + counter += 1 + end + slug + else + "bookmark-#{SecureRandom.uuid}" + end + + # Use update_column to skip validations and callbacks + update_column(:slug, fallback_slug) + end end diff --git a/app/views/pubview/post.html.erb b/app/views/pubview/post.html.erb index d338a1d..67a37db 100644 --- a/app/views/pubview/post.html.erb +++ b/app/views/pubview/post.html.erb @@ -19,14 +19,14 @@

<% if !@post.short_dispatch?%>About a <%= @reading_time %> minute read, p<% else %>P<% end %>osted <%= @post.published_at.strftime('%B %d, %Y') %> and tagged <%= raw @post.format_tags %>

<% else %> -

Bookmark comment permalink:

-

<%= @post.title %>

+

Aidan Cornelius-Bell’s mind reader:

+

<%= @post.title %>

<%= link_to "👁 View linked content", @post.url, class: "button button-bottomless", target: "_BLANK" %> <%= link_to "🗞 More from mind reader", "#{root_path}", class: "button button-bottomless" %>
-

Originally bookmarked on mind reader on <%= @post.published_at.strftime('%B %d, %Y') %>.

+

A link to third party content first shared on mind reader on <%= @post.published_at.strftime('%B %d, %Y') %>.

<% end %> @@ -40,8 +40,10 @@ <% end %> <%= raw @rendered_content %> - <%= render partial: "layouts/post_navigation" %> -
+ <% if @post.post_type != "bookmark" %> + <%= render partial: "layouts/post_navigation" %> +
+ <% end %> -- 2.39.5