From 1f3b0c44f7de6ba99283dba0dfb9cd294b9d9e12 Mon Sep 17 00:00:00 2001 From: Klas Eskilson Date: Sat, 29 Apr 2017 14:53:53 +0200 Subject: [PATCH] Add `sort_by` and `direction` option for HasMany field (#810) * Add `sort_by` and `direction` options to HasMany field * Add spec for `sort_by` and `direction` in HasMany field * [Docs] Add instructions for HasMany sort_by and direction options --- docs/customizing_dashboards.md | 4 +++ lib/administrate/field/has_many.rb | 15 +++++++++- spec/factories.rb | 12 +++++++- spec/lib/fields/has_many_spec.rb | 48 ++++++++++++++++++++++++++---- 4 files changed, 71 insertions(+), 8 deletions(-) diff --git a/docs/customizing_dashboards.md b/docs/customizing_dashboards.md index 8c6858e746..59447fa4b6 100644 --- a/docs/customizing_dashboards.md +++ b/docs/customizing_dashboards.md @@ -74,6 +74,10 @@ which are specified through the `.with_options` class method: `:limit` - Set the number of resources to display in the show view. Default is `5`. +`:sort_by` - What to sort the association by in the show view. + +`:direction` - What direction the sort should be in, `:asc` (default) or `:desc`. + **Field::Number** `:decimals` - Set the number of decimals to display. Defaults to `0`. diff --git a/lib/administrate/field/has_many.rb b/lib/administrate/field/has_many.rb index 53aa6ba464..04ddcac017 100644 --- a/lib/administrate/field/has_many.rb +++ b/lib/administrate/field/has_many.rb @@ -1,5 +1,6 @@ require_relative "associative" require "administrate/page/collection" +require "administrate/order" module Administrate module Field @@ -37,7 +38,7 @@ def permitted_attribute end def resources(page = 1) - data.page(page).per(limit) + order.apply(data).page(page).per(limit) end def more_than_limit? @@ -58,6 +59,18 @@ def candidate_resources def display_candidate_resource(resource) associated_dashboard.display_resource(resource) end + + def order + @_order ||= Administrate::Order.new(sort_by, direction) + end + + def sort_by + options[:sort_by] + end + + def direction + options[:direction] + end end end end diff --git a/spec/factories.rb b/spec/factories.rb index b7d7c38b8f..38cdb2b791 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -2,6 +2,16 @@ factory :customer do sequence(:name) { |n| "Customer #{n}" } email { name.downcase.gsub(" ", "_") + "@example.com" } + + transient do + order_count 3 + end + + trait :with_orders do + after(:create) do |customer, evaluator| + create_list(:order, evaluator.order_count, customer: customer) + end + end end factory :line_item do @@ -14,7 +24,7 @@ factory :order do customer address_line_one "85 2nd St" - address_line_two "#700" + sequence(:address_line_two) { |n| "#700 (#{n})" } address_city "San Francisco" address_state "CA" address_zip "94110" diff --git a/spec/lib/fields/has_many_spec.rb b/spec/lib/fields/has_many_spec.rb index b6e28c0809..f5c942ee83 100644 --- a/spec/lib/fields/has_many_spec.rb +++ b/spec/lib/fields/has_many_spec.rb @@ -106,22 +106,58 @@ describe "#resources" do it "limits the number of records shown" do limit = Administrate::Field::HasMany::DEFAULT_LIMIT - resources = MockRelation.new([:a] * (limit + 1)) + customer = FactoryGirl.create(:customer, :with_orders, order_count: 10) + resources = customer.orders association = Administrate::Field::HasMany - field = association.new(:customers, resources, :show) + field = association.new(:orders, resources, :show) - expect(field.resources).to eq([:a] * limit) + expect(field.resources.size).to eq(limit) end context "with `limit` option" do it "limits the number of items returned" do - resources = MockRelation.new([:a, :b, :c]) + customer = FactoryGirl.create(:customer, :with_orders) + resources = customer.orders association = Administrate::Field::HasMany.with_options(limit: 1) - field = association.new(:customers, resources, :show) + field = association.new(:orders, resources, :show) + + expect(field.resources).to be_one + end + end + + context "with `sort_by` option" do + it "returns the resources in correct order" do + customer = FactoryGirl.create(:customer, :with_orders) + options = { sort_by: :address_line_two } + association = Administrate::Field::HasMany.with_options(options) + field = association.new(:orders, customer.orders, :show) + + correct_order = customer.orders.sort_by(&:address_line_two).map(&:id) + reversed_order = customer.orders.sort do |a, b| + b.address_line_two <=> a.address_line_two + end + + expect(field.resources.map(&:id)).to eq correct_order + expect(field.resources.map(&:id)).to_not eq reversed_order.map(&:id) + end + end + + context "with `direction` option" do + it "returns the resources in correct order" do + customer = FactoryGirl.create(:customer, :with_orders) + options = { sort_by: :address_line_two, direction: :desc } + association = Administrate::Field::HasMany.with_options(options) + field = association.new(:orders, customer.orders, :show) + + reversed_order = customer.orders.sort_by(&:address_line_two).map(&:id) + correct_order = customer.orders.sort do |a, b| + b.address_line_two <=> a.address_line_two + end - expect(field.resources).to eq([:a]) + expect(field.resources.map(&:id)).to eq correct_order.map(&:id) + expect(field.resources.map(&:id)).to_not eq reversed_order end end end