Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions lib/brainstem/presenter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Brainstem still needs to support 1.9, so kwargs can't be used quite yet unfortunately.

[@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.
Expand Down Expand Up @@ -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] 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?
self.class.allow_count?
end

# @!attribute [r] sort_orders
# The sort orders that were declared in the definition of this presenter.
def sort_orders
Expand Down
29 changes: 27 additions & 2 deletions lib/brainstem/presenter_collection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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!
Expand Down Expand Up @@ -154,7 +160,16 @@ 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.
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

end

def calculate_per_page(options)
Expand Down Expand Up @@ -387,6 +402,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.
Expand Down
27 changes: 27 additions & 0 deletions spec/brainstem/presenter_collection_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down