From e8dc0bf0da6c0315f87a33b196c3d5e0aa927510 Mon Sep 17 00:00:00 2001 From: David Brennan Date: Sun, 19 Apr 2015 21:00:39 +0200 Subject: [PATCH 1/3] Adds ability to exclude count from results --- lib/brainstem/presenter.rb | 39 +++++++++++++++++++++ lib/brainstem/presenter_collection.rb | 31 ++++++++++++++-- spec/brainstem/presenter_collection_spec.rb | 27 ++++++++++++++ 3 files changed, 95 insertions(+), 2 deletions(-) diff --git a/lib/brainstem/presenter.rb b/lib/brainstem/presenter.rb index 65202dac..4db3e29d 100644 --- a/lib/brainstem/presenter.rb +++ b/lib/brainstem/presenter.rb @@ -28,6 +28,32 @@ def self.default_sort_order(sort_string = nil) end end + # @overload exclude_count + # set exclude_count = true and allow_count = false (i.e. exclude the count and do not + # do not allow a request for the count via the url query string) + # @return [Boolean, Boolean] + # @overload exclude_count( allow: true ) + # set exclude_count = true and allow_count = false (i.e. exclude the count by default + # but allows a request for it via the url query string with (e.g. ?count=true) + # @return [Boolean, Boolean] + # @overload exclude_count( exclude: false ) + # set exclude_count = false. This is only needed for testing to toggle back to the + # including the count by default, otherwise some of the subsequent tests may fail + # @return [Boolean, Boolean] + def self.exclude_count(exclude: true, allow: false) + [@exclude_count = exclude, @allow_count = allow] + end + + def self.exclude_count? + @exclude_count == true ? true : false + end + + def self.allow_count? + (@exclude_count == true && @allow_count == true) ? true : false + end + + + # @overload sort_order(name, order) # @param [Symbol] name The name of the sort order. # @param [String] order The SQL string to use to sort the presented data. @@ -191,6 +217,19 @@ def default_sort_order self.class.default_sort_order end + # @!attribute [r] exclude_count + # The boolean value set in the definition of this presenter to indicate if the count is excluded + def exclude_count? + self.class.exclude_count? + end + + # @!attribute [r] exclude_count + # The boolean value set in the definition of this presenter to indicate if the count may + # be included even if it has been excluded by default + def allow_count? + self.class.allow_count? + end + # @!attribute [r] sort_orders # The sort orders that were declared in the definition of this presenter. def sort_orders diff --git a/lib/brainstem/presenter_collection.rb b/lib/brainstem/presenter_collection.rb index 44f6a47b..549897b3 100644 --- a/lib/brainstem/presenter_collection.rb +++ b/lib/brainstem/presenter_collection.rb @@ -93,7 +93,13 @@ def presenting(name, options = {}, &block) models = perform_preloading records, includes_hash primary_models, associated_models = gather_associations(models, includes_hash) - struct = { :count => count, options[:as] => [], :results => [] } + + + if present_count?(options) + struct = { :count => count, options[:as] => [], :results => [] } + else + struct = { options[:as] => [], :results => [] } + end associated_models.each do |json_name, models| models.flatten! @@ -154,7 +160,18 @@ def paginate(scope, options) offset = limit * (calculate_page(options) - 1) end - [scope.limit(limit).offset(offset).uniq, scope.select("distinct #{scope.connection.quote_table_name options[:table_name]}.id").count] # as of Rails 3.2.5, uniq.count generates the wrong SQL. + # DBR + paginate_results = [] + paginate_results << scope.limit(limit).offset(offset).uniq + if present_count?(options) + paginate_results << scope.select("distinct #{scope.connection.quote_table_name options[:table_name]}.id").count + else + paginate_results << :no_count_retrieved + end + + paginate_results + +# [scope.limit(limit).offset(offset).uniq, scope.select("distinct #{scope.connection.quote_table_name options[:table_name]}.id").count] # as of Rails 3.2.5, uniq.count generates the wrong SQL. end def calculate_per_page(options) @@ -387,6 +404,16 @@ def set_default_filters_option!(options) options[:apply_default_filters] = [true, "true", "TRUE", 1, "1"].include? options[:params].delete(:apply_default_filters) end + + # Return boolean indicating whether or not the count should be presented + def present_count?(options) + p = options[:presenter] + count_true = [true, "true", "TRUE", 1, "1"].include? options[:params][:count] + count_false = [false, "false", "FALSE", 0, "0"].include? options[:params][:count] + ( !p.exclude_count? && !count_false ) || ( p.allow_count? && count_true ) + end + + # Class Methods # In Rails 4.2, ActiveRecord::Base#reflections started being keyed by strings instead of symbols. diff --git a/spec/brainstem/presenter_collection_spec.rb b/spec/brainstem/presenter_collection_spec.rb index 65d7611c..a4ff020d 100644 --- a/spec/brainstem/presenter_collection_spec.rb +++ b/spec/brainstem/presenter_collection_spec.rb @@ -149,6 +149,33 @@ class MyException < Exception; end result = @presenter_collection.presenting("workspaces", :params => { :per_page => 2, :page => 1 }) { Workspace.order('id desc') } expect(result[:count]).to eq(Workspace.count) end + + it "are excluded when exclude_count method defined" do + WorkspacePresenter.exclude_count + result = @presenter_collection.presenting("workspaces", :params => { :per_page => 2, :page => 1 }) { Workspace.unscoped } + WorkspacePresenter.exclude_count(exclude: false) + expect(result[:count]).to be_nil + end + + it "are included when exclude_count method defined with 'allow = true' and 'count=true' passed in url query string" do + WorkspacePresenter.exclude_count(allow: true) + result = @presenter_collection.presenting("workspaces", :params => { :per_page => 2, :page => 1, :count => "true" }) { Workspace.unscoped } + WorkspacePresenter.exclude_count(exclude: false) + expect(result[:count]).to eq(Workspace.count) + end + + it "are excluded when exclude_count method defined without 'allow = true' and 'count=true' passed in url query string" do + WorkspacePresenter.exclude_count + result = @presenter_collection.presenting("workspaces", :params => { :per_page => 2, :page => 1, :count => "true" }) { Workspace.unscoped } + WorkspacePresenter.exclude_count(exclude: false) + expect(result[:count]).to be_nil + end + + it "are excluded when count=false appears in the url query string" do + result = @presenter_collection.presenting("workspaces", :params => { :per_page => 2, :page => 1, :count => "false" }) { Workspace.unscoped } + expect(result[:count]).to be_nil + end + end end From 1a8fd3f6e498612d0badf1307928f1f8a7c6b09a Mon Sep 17 00:00:00 2001 From: David Brennan Date: Sun, 19 Apr 2015 21:08:18 +0200 Subject: [PATCH 2/3] Minor removed some unwanted comments --- lib/brainstem/presenter_collection.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/brainstem/presenter_collection.rb b/lib/brainstem/presenter_collection.rb index 549897b3..2baf1263 100644 --- a/lib/brainstem/presenter_collection.rb +++ b/lib/brainstem/presenter_collection.rb @@ -160,7 +160,6 @@ def paginate(scope, options) offset = limit * (calculate_page(options) - 1) end - # DBR paginate_results = [] paginate_results << scope.limit(limit).offset(offset).uniq if present_count?(options) @@ -171,7 +170,6 @@ def paginate(scope, options) paginate_results -# [scope.limit(limit).offset(offset).uniq, scope.select("distinct #{scope.connection.quote_table_name options[:table_name]}.id").count] # as of Rails 3.2.5, uniq.count generates the wrong SQL. end def calculate_per_page(options) From 0c17357dc62de9242e37a9e280fc692a9807c26d Mon Sep 17 00:00:00 2001 From: David Brennan Date: Sun, 19 Apr 2015 21:10:44 +0200 Subject: [PATCH 3/3] Fixed typo --- lib/brainstem/presenter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/brainstem/presenter.rb b/lib/brainstem/presenter.rb index 4db3e29d..e86e133e 100644 --- a/lib/brainstem/presenter.rb +++ b/lib/brainstem/presenter.rb @@ -223,7 +223,7 @@ def exclude_count? self.class.exclude_count? end - # @!attribute [r] exclude_count + # @!attribute [r] allow_count # The boolean value set in the definition of this presenter to indicate if the count may # be included even if it has been excluded by default def allow_count?