From 048d83cba46579321a516bf41d08da576c09bdc1 Mon Sep 17 00:00:00 2001 From: eelco Date: Tue, 19 May 2026 20:59:41 +0530 Subject: [PATCH] Add in_order_of to Resource ```ruby Content::Post.in_order_of(:category, %w[featured popular recent]) Content::Post.in_order_of(:category, %w[featured popular], filter: false) ``` --- lib/perron/relation.rb | 15 ++++++++++++ lib/perron/resource/class_methods.rb | 2 ++ .../content/posts/2023-05-15-sample-post.md | 1 + .../content/posts/2023-06-15-another-post.md | 1 + test/dummy/app/models/content/post.rb | 2 +- test/perron/relation_test.rb | 23 +++++++++++++++++++ 6 files changed, 43 insertions(+), 1 deletion(-) diff --git a/lib/perron/relation.rb b/lib/perron/relation.rb index e2a18d3..944d0ab 100644 --- a/lib/perron/relation.rb +++ b/lib/perron/relation.rb @@ -47,5 +47,20 @@ def pluck(*attributes) end end end + + def in_order_of(attribute, values, filter: true) + return Relation.new([]) if values.empty? + + indexed = values.each_with_index.to_h + + resources = if filter + select { indexed.key?(it.public_send(attribute)) } + .sort_by { indexed[it.public_send(attribute)] } + else + sort_by { indexed[it.public_send(attribute)] || Float::INFINITY } + end + + Relation.new(resources) + end end end diff --git a/lib/perron/resource/class_methods.rb b/lib/perron/resource/class_methods.rb index 3abbce3..d4fbc27 100644 --- a/lib/perron/resource/class_methods.rb +++ b/lib/perron/resource/class_methods.rb @@ -22,6 +22,8 @@ def count = all.size def order(attribute, direction = :asc) = all.order(attribute, direction) + def in_order_of(attribute, values, filter: true) = all.in_order_of(attribute, values, filter:) + def first(n = nil) n ? all.first(n) : all[0] end diff --git a/test/dummy/app/content/posts/2023-05-15-sample-post.md b/test/dummy/app/content/posts/2023-05-15-sample-post.md index 81d626a..33b7254 100644 --- a/test/dummy/app/content/posts/2023-05-15-sample-post.md +++ b/test/dummy/app/content/posts/2023-05-15-sample-post.md @@ -5,6 +5,7 @@ image: https://example.com/images/sample.jpg author_id: rails-designer updated_at: 2023-05-15 processor_class: custom-from-metadata +category: news --- Labore qui mollit commodo id nulla qui exercitation nulla reprehenderit nulla excepteur aute eu sint. Minim sit aute et ad ut esse aute sunt magna voluptate duis tempor. Commodo commodo qui amet ullamco Lorem ex cillum ea occaecat deserunt elit amet consequat nulla Lorem. Reprehenderit id aute dolor minim aliquip officia et reprehenderit nisi. Aute labore ex veniam enim enim duis sint elit proident aute sunt consectetur ut aliqua. Laboris elit exercitation veniam non commodo magna sunt in sunt id. diff --git a/test/dummy/app/content/posts/2023-06-15-another-post.md b/test/dummy/app/content/posts/2023-06-15-another-post.md index 57549d4..0e9b8cb 100644 --- a/test/dummy/app/content/posts/2023-06-15-another-post.md +++ b/test/dummy/app/content/posts/2023-06-15-another-post.md @@ -3,6 +3,7 @@ title: Another Sample Post description: Describing another sample post image: https://example.com/images/sample.jpg author: Kendall +category: tutorial --- Content goes here… diff --git a/test/dummy/app/models/content/post.rb b/test/dummy/app/models/content/post.rb index 777d58a..2df26e8 100644 --- a/test/dummy/app/models/content/post.rb +++ b/test/dummy/app/models/content/post.rb @@ -28,7 +28,7 @@ class Content::Post < Perron::Resource belongs_to :author belongs_to :editor, class_name: "Content::Data::Editors" - delegate :title, to: :metadata + delegate :title, :category, to: :metadata scope :ordered, -> { order(:slug) } scope :limited, -> { limit(2) } diff --git a/test/perron/relation_test.rb b/test/perron/relation_test.rb index 9a46905..96e07a0 100644 --- a/test/perron/relation_test.rb +++ b/test/perron/relation_test.rb @@ -101,4 +101,27 @@ class Perron::RelationTest < ActiveSupport::TestCase assert_equal 2, slugs.size assert_equal "another-post", slugs.first end + + test "#in_order_of filters and sorts by values (filter: true by default)" do + result = @posts.in_order_of(:category, %w[tutorial news]) + + assert_instance_of Perron::Relation, result + assert_equal 2, result.size + assert_equal "tutorial", result.first.category + assert_equal "news", result.second.category + end + + test "#in_order_of sorts all records with filter: false" do + result = @posts.in_order_of(:category, %w[tutorial], filter: false) + + assert_equal 4, result.size + assert_equal "tutorial", result.first.category + end + + test "#in_order_of returns empty relation for empty values" do + result = @posts.in_order_of(:category, []) + + assert_instance_of Perron::Relation, result + assert_equal 0, result.size + end end