From 9f6ce5446b68e4f843b1373abad10ecda1cefd4f Mon Sep 17 00:00:00 2001 From: James Smith Date: Wed, 4 Sep 2024 08:43:17 +0100 Subject: [PATCH 1/5] DRY up linkable models into a concern --- app/models/collection.rb | 3 +-- app/models/concerns/linkable.rb | 9 +++++++++ app/models/creator.rb | 3 +-- app/models/model.rb | 4 +--- 4 files changed, 12 insertions(+), 7 deletions(-) create mode 100644 app/models/concerns/linkable.rb diff --git a/app/models/collection.rb b/app/models/collection.rb index 4827ac8f4..d39e276a2 100644 --- a/app/models/collection.rb +++ b/app/models/collection.rb @@ -1,14 +1,13 @@ class Collection < ApplicationRecord include Followable include CaberObject + include Linkable acts_as_federails_actor username_field: :slug, name_field: :name, profile_url_method: :url_for, actor_type: "Collection", include_in_user_count: false has_many :models, dependent: :nullify has_many :collections, dependent: :nullify - has_many :links, as: :linkable, dependent: :destroy belongs_to :collection, optional: true - accepts_nested_attributes_for :links, reject_if: :all_blank, allow_destroy: true validates :name, uniqueness: {case_sensitive: false} validates :slug, uniqueness: true diff --git a/app/models/concerns/linkable.rb b/app/models/concerns/linkable.rb new file mode 100644 index 000000000..1fa7fcd2d --- /dev/null +++ b/app/models/concerns/linkable.rb @@ -0,0 +1,9 @@ +module Linkable + extend ActiveSupport::Concern + + included do + has_many :links, as: :linkable, dependent: :destroy + accepts_nested_attributes_for :links, reject_if: :all_blank, allow_destroy: true + end + +end diff --git a/app/models/creator.rb b/app/models/creator.rb index 8bcf157d7..768c6da04 100644 --- a/app/models/creator.rb +++ b/app/models/creator.rb @@ -1,12 +1,11 @@ class Creator < ApplicationRecord include Followable include CaberObject + include Linkable acts_as_federails_actor username_field: :slug, name_field: :name, profile_url_method: :url_for, include_in_user_count: false has_many :models, dependent: :nullify - has_many :links, as: :linkable, dependent: :destroy - accepts_nested_attributes_for :links, reject_if: :all_blank, allow_destroy: true validates :name, uniqueness: {case_sensitive: false} validates :slug, uniqueness: true diff --git a/app/models/model.rb b/app/models/model.rb index 901723fef..c43e38e8f 100644 --- a/app/models/model.rb +++ b/app/models/model.rb @@ -4,6 +4,7 @@ class Model < ApplicationRecord include PathParser include Followable include CaberObject + include Linkable acts_as_federails_actor username_field: :slug, name_field: :name, profile_url_method: :url_for, actor_type: "Document", include_in_user_count: false @@ -14,12 +15,9 @@ class Model < ApplicationRecord belongs_to :collection, optional: true belongs_to :preview_file, class_name: "ModelFile", optional: true has_many :model_files, dependent: :destroy - has_many :links, as: :linkable, dependent: :destroy has_many :problems, as: :problematic, dependent: :destroy acts_as_taggable_on :tags - accepts_nested_attributes_for :links, reject_if: :all_blank, allow_destroy: true - before_validation :strip_separators_from_path, if: :path_changed? before_validation :slugify_name, if: :name_changed? From af1607dbeeff3311a1499bcd6b4f652dd51bb49a Mon Sep 17 00:00:00 2001 From: James Smith Date: Wed, 4 Sep 2024 08:55:11 +0100 Subject: [PATCH 2/5] move slug generation into concern --- app/models/collection.rb | 10 +--------- app/models/concerns/sluggable.rb | 14 ++++++++++++++ app/models/creator.rb | 10 +--------- app/models/model.rb | 6 +----- 4 files changed, 17 insertions(+), 23 deletions(-) create mode 100644 app/models/concerns/sluggable.rb diff --git a/app/models/collection.rb b/app/models/collection.rb index d39e276a2..cb4873bba 100644 --- a/app/models/collection.rb +++ b/app/models/collection.rb @@ -2,6 +2,7 @@ class Collection < ApplicationRecord include Followable include CaberObject include Linkable + include Sluggable acts_as_federails_actor username_field: :slug, name_field: :name, profile_url_method: :url_for, actor_type: "Collection", include_in_user_count: false @@ -9,9 +10,6 @@ class Collection < ApplicationRecord has_many :collections, dependent: :nullify belongs_to :collection, optional: true validates :name, uniqueness: {case_sensitive: false} - validates :slug, uniqueness: true - - before_validation :slugify_name, if: :name_changed? default_scope { order(:name) } # returns all collections at and below given ids @@ -74,10 +72,4 @@ def self.ransackable_attributes(_auth_object = nil) def self.ransackable_associations(_auth_object = nil) ["collection", "collections", "links", "models"] end - - private - - def slugify_name - self.slug = name.parameterize - end end diff --git a/app/models/concerns/sluggable.rb b/app/models/concerns/sluggable.rb new file mode 100644 index 000000000..3cb000b01 --- /dev/null +++ b/app/models/concerns/sluggable.rb @@ -0,0 +1,14 @@ +module Sluggable + extend ActiveSupport::Concern + + included do + validates :slug, uniqueness: true + before_validation :slugify_name, if: :name_changed? + end + + private + + def slugify_name + self.slug = name.parameterize + end +end diff --git a/app/models/creator.rb b/app/models/creator.rb index 768c6da04..8c2440ba6 100644 --- a/app/models/creator.rb +++ b/app/models/creator.rb @@ -2,17 +2,15 @@ class Creator < ApplicationRecord include Followable include CaberObject include Linkable + include Sluggable acts_as_federails_actor username_field: :slug, name_field: :name, profile_url_method: :url_for, include_in_user_count: false has_many :models, dependent: :nullify validates :name, uniqueness: {case_sensitive: false} - validates :slug, uniqueness: true default_scope { order(:name) } - before_validation :slugify_name, if: :name_changed? - def self.ransackable_attributes(_auth_object = nil) ["caption", "created_at", "id", "name", "notes", "slug", "updated_at"] end @@ -20,10 +18,4 @@ def self.ransackable_attributes(_auth_object = nil) def self.ransackable_associations(_auth_object = nil) ["links", "models"] end - - private - - def slugify_name - self.slug = name.parameterize - end end diff --git a/app/models/model.rb b/app/models/model.rb index c43e38e8f..971a66fba 100644 --- a/app/models/model.rb +++ b/app/models/model.rb @@ -5,6 +5,7 @@ class Model < ApplicationRecord include Followable include CaberObject include Linkable + include Sluggable acts_as_federails_actor username_field: :slug, name_field: :name, profile_url_method: :url_for, actor_type: "Document", include_in_user_count: false @@ -19,7 +20,6 @@ class Model < ApplicationRecord acts_as_taggable_on :tags before_validation :strip_separators_from_path, if: :path_changed? - before_validation :slugify_name, if: :name_changed? before_validation :normalize_license # In Rails 7.1 we will be able to do this instead: @@ -169,8 +169,4 @@ def move_files # Remove the old folder if it's still there previous_library.storage.delete_prefixed(previous_path) end - - def slugify_name - self.slug = name.parameterize - end end From 3418b908ce1c9a8d8b67897d9608228a71e92bf6 Mon Sep 17 00:00:00 2001 From: James Smith Date: Wed, 4 Sep 2024 09:53:53 +0100 Subject: [PATCH 3/5] DRY up sluggable tests --- spec/models/collection_spec.rb | 6 +----- spec/models/concerns/sluggable_shared.rb | 7 +++++++ spec/models/creator_spec.rb | 6 +----- spec/models/model_spec.rb | 6 +----- 4 files changed, 10 insertions(+), 15 deletions(-) create mode 100644 spec/models/concerns/sluggable_shared.rb diff --git a/spec/models/collection_spec.rb b/spec/models/collection_spec.rb index a021b276c..78c4b1330 100644 --- a/spec/models/collection_spec.rb +++ b/spec/models/collection_spec.rb @@ -3,9 +3,5 @@ RSpec.describe Collection do it_behaves_like "Followable" it_behaves_like "Caber::Object" - - it "automatically generates a slug from the name" do - collection = create(:collection, name: "Spın̈al Tap") - expect(collection.slug).to eq "spin-al-tap" - end + it_behaves_like "Sluggable" end diff --git a/spec/models/concerns/sluggable_shared.rb b/spec/models/concerns/sluggable_shared.rb new file mode 100644 index 000000000..34b455804 --- /dev/null +++ b/spec/models/concerns/sluggable_shared.rb @@ -0,0 +1,7 @@ +shared_examples "Sluggable" do + + it "automatically generates a slug from the name" do + thing = create(described_class.name.parameterize.to_sym, name: "Spın̈al Tap") + expect(thing.slug).to eq "spin-al-tap" + end +end diff --git a/spec/models/creator_spec.rb b/spec/models/creator_spec.rb index 0bf541b3e..8ec02c9be 100644 --- a/spec/models/creator_spec.rb +++ b/spec/models/creator_spec.rb @@ -3,9 +3,5 @@ RSpec.describe Creator do it_behaves_like "Followable" it_behaves_like "Caber::Object" - - it "automatically generates a slug from the name" do - creator = create(:creator, name: "Spın̈al Tap") - expect(creator.slug).to eq "spin-al-tap" - end + it_behaves_like "Sluggable" end diff --git a/spec/models/model_spec.rb b/spec/models/model_spec.rb index 53b71ae5b..16711baee 100644 --- a/spec/models/model_spec.rb +++ b/spec/models/model_spec.rb @@ -4,6 +4,7 @@ RSpec.describe Model do it_behaves_like "Followable" it_behaves_like "Caber::Object" + it_behaves_like "Sluggable" it "is not valid without a path" do expect(build(:model, path: nil)).not_to be_valid @@ -71,11 +72,6 @@ expect(model.path).to eq "models/car" end - it "automatically generates a slug from the name" do - model = create(:model, name: "Spın̈al Tap") - expect(model.slug).to eq "spin-al-tap" - end - context "with a library on disk" do around do |ex| MockDirectory.create([ From 1f46582e9a7004242865ae32585c55f94a93cab8 Mon Sep 17 00:00:00 2001 From: James Smith Date: Wed, 4 Sep 2024 09:58:43 +0100 Subject: [PATCH 4/5] don't need slug uniqueness validation, it'll just match name uniqueness --- app/models/concerns/sluggable.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/app/models/concerns/sluggable.rb b/app/models/concerns/sluggable.rb index 3cb000b01..44e072fd8 100644 --- a/app/models/concerns/sluggable.rb +++ b/app/models/concerns/sluggable.rb @@ -2,7 +2,6 @@ module Sluggable extend ActiveSupport::Concern included do - validates :slug, uniqueness: true before_validation :slugify_name, if: :name_changed? end From 85ed544ddc17617cb5487017ea338745edce9ef2 Mon Sep 17 00:00:00 2001 From: James Smith Date: Wed, 4 Sep 2024 10:03:32 +0100 Subject: [PATCH 5/5] lint --- app/models/concerns/linkable.rb | 1 - spec/models/concerns/sluggable_shared.rb | 1 - 2 files changed, 2 deletions(-) diff --git a/app/models/concerns/linkable.rb b/app/models/concerns/linkable.rb index 1fa7fcd2d..1e979f11d 100644 --- a/app/models/concerns/linkable.rb +++ b/app/models/concerns/linkable.rb @@ -5,5 +5,4 @@ module Linkable has_many :links, as: :linkable, dependent: :destroy accepts_nested_attributes_for :links, reject_if: :all_blank, allow_destroy: true end - end diff --git a/spec/models/concerns/sluggable_shared.rb b/spec/models/concerns/sluggable_shared.rb index 34b455804..3b646b1e3 100644 --- a/spec/models/concerns/sluggable_shared.rb +++ b/spec/models/concerns/sluggable_shared.rb @@ -1,5 +1,4 @@ shared_examples "Sluggable" do - it "automatically generates a slug from the name" do thing = create(described_class.name.parameterize.to_sym, name: "Spın̈al Tap") expect(thing.slug).to eq "spin-al-tap"