hightop 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7bfda8167d2141d8bd0be9678f1f285fe8417d0deecac5a04cee44f50efcf876
4
- data.tar.gz: 0414c92e5702679fc169dbecb03d754e79461968e97a39cd2cca15d94ec4daa3
3
+ metadata.gz: 3e2fc0f11b1504620f8989548410fb965f5399f10a2a160f8911c72e1ee9be73
4
+ data.tar.gz: b9a4289ebbd844162263c513bfcc93ebcb1a7c97f27b7ec8bee511729d7b0d37
5
5
  SHA512:
6
- metadata.gz: baad6fa1e6f4f404fd2f33448a971412ea9bf50257f5dd69531e341aa0a3afb69c816ac3191a9988ed8f30b19cce2c1d0837fb077e78fe589a7975b0283ec6d7
7
- data.tar.gz: a66db10388aff6057d63f9ae977a700c0065d222a52dd04df0e7ea4bbd87f5ee51a145ff875aea5b9042dbbbaff2a10543f612519b3c65ec525852728aef5f82
6
+ metadata.gz: 4bb15ebfacc0e6383ca32f46cca4839d8f8a69180154ddf2a6a9fca65b5fe11cfbdcf087b3ec767d21fabfa75db197c4b7b1d1f68bd332e030076f1ea5c8f0e2
7
+ data.tar.gz: 5659dc207fb18a98d70febfbd51f28a5155672365ed9b9a8e06dceff27d0c640abbb99461c1410f6209571f4e283201724383d82fd732c7ddab49cbcc665a66d
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## 0.2.2
2
+
3
+ - Added support for Mongoid
4
+
1
5
  ## 0.2.1
2
6
 
3
7
  - Added support for arrays and hashes
data/README.md CHANGED
@@ -4,23 +4,16 @@ A nice shortcut for group count queries
4
4
 
5
5
  ```ruby
6
6
  Visit.top(:browser)
7
+ # {
8
+ # "Chrome" => 63,
9
+ # "Safari" => 50,
10
+ # "Firefox" => 34
11
+ # }
7
12
  ```
8
13
 
9
- instead of
14
+ Works with Active Record, Mongoid, arrays and hashes
10
15
 
11
- ```ruby
12
- Visit.group(:browser).where("browser IS NOT NULL").order("count_all DESC, browser").count
13
- ```
14
-
15
- Be sure to [sanitize user input](https://rails-sqli.org/) like you must with `group`
16
-
17
- Also works with arrays and hashes
18
-
19
- ```ruby
20
- ["up", "up", "down"].top(1)
21
- ```
22
-
23
- [![Build Status](https://travis-ci.org/ankane/hightop.svg)](https://travis-ci.org/ankane/hightop)
16
+ [![Build Status](https://travis-ci.org/ankane/hightop.svg?branch=master)](https://travis-ci.org/ankane/hightop)
24
17
 
25
18
  ## Installation
26
19
 
@@ -68,6 +61,19 @@ And min count
68
61
  Visit.top(:city, min: 10)
69
62
  ```
70
63
 
64
+ ## User Input
65
+
66
+ If passing user input as the column, be sure to sanitize it first [like you must](https://rails-sqli.org/) with `group`.
67
+
68
+ ```ruby
69
+ column = params[:column]
70
+
71
+ # check against permitted columns
72
+ raise "Unpermitted column" unless ["column_a", "column_b"].include?(column)
73
+
74
+ User.top(column)
75
+ ```
76
+
71
77
  ## Arrays and Hashes
72
78
 
73
79
  Arrays
data/lib/hightop.rb CHANGED
@@ -3,9 +3,14 @@ require "active_support"
3
3
 
4
4
  # modules
5
5
  require "hightop/enumerable"
6
- require "hightop/kicks"
7
6
  require "hightop/version"
8
7
 
9
8
  ActiveSupport.on_load(:active_record) do
9
+ require "hightop/kicks"
10
10
  extend Hightop::Kicks
11
11
  end
12
+
13
+ ActiveSupport.on_load(:mongoid) do
14
+ require "hightop/mongoid"
15
+ Mongoid::Document::ClassMethods.include(Hightop::Mongoid)
16
+ end
@@ -1,6 +1,6 @@
1
1
  module Enumerable
2
2
  def top(*args, &block)
3
- if block || !respond_to?(:scoping)
3
+ if block || !(respond_to?(:scoping) || respond_to?(:with_scope))
4
4
  limit, options, _ = args
5
5
  if limit.is_a?(Hash) && args.size == 1
6
6
  options = limit
@@ -19,8 +19,10 @@ module Enumerable
19
19
  arr = counts.sort_by { |_, v| -v }
20
20
  arr = arr[0...limit] if limit
21
21
  Hash[arr]
22
- else
22
+ elsif respond_to?(:scoping)
23
23
  scoping { @klass.send(:top, *args, &block) }
24
+ else
25
+ with_scope(self) { klass.send(:top, *args, &block) }
24
26
  end
25
27
  end
26
28
  end
@@ -0,0 +1,52 @@
1
+ module Hightop
2
+ module Mongoid
3
+ # super helpful article
4
+ # https://maximomussini.com/posts/mongoid-aggregation-dsl/
5
+ def top(column, limit = nil, distinct: nil, uniq: nil, min: nil, nil: nil)
6
+ distinct ||= uniq
7
+
8
+ relation = all
9
+
10
+ # terribly named option
11
+ unless binding.local_variable_get(:nil)
12
+ (column.is_a?(Array) ? column : [column]).each do |c|
13
+ relation = relation.and(c.ne => nil)
14
+ end
15
+ end
16
+
17
+ ids = {}
18
+ Array(column).each_with_index do |c, i|
19
+ ids["c#{i}"] = "$#{c}"
20
+ end
21
+
22
+ if distinct
23
+ # group with distinct column first, then group without it
24
+ # https://stackoverflow.com/questions/24761266/select-group-by-count-and-distinct-count-in-same-mongodb-query/24770233#24770233
25
+ distinct_ids = ids.merge("c#{ids.size}" => "$#{distinct}")
26
+ relation = relation.group(_id: distinct_ids, count: {"$sum" => 1})
27
+ ids.each_key do |k|
28
+ ids[k] = "$_id.#{k}"
29
+ end
30
+ end
31
+
32
+ relation = relation.group(_id: ids, count: {"$sum" => 1})
33
+
34
+ if min
35
+ relation.pipeline.push("$match" => {"count" => {"$gte" => min}})
36
+ end
37
+
38
+ relation = relation.desc(:count)
39
+ if limit
40
+ relation = relation.limit(limit)
41
+ end
42
+
43
+ result = {}
44
+ collection.aggregate(relation.pipeline).each do |doc|
45
+ key = doc["_id"].values
46
+ key = key[0] if key.size == 1
47
+ result[key] = doc["count"]
48
+ end
49
+ result
50
+ end
51
+ end
52
+ end
@@ -1,3 +1,3 @@
1
1
  module Hightop
2
- VERSION = "0.2.1"
2
+ VERSION = "0.2.2"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hightop
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-08-05 00:00:00.000000000 Z
11
+ date: 2019-08-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -92,6 +92,7 @@ files:
92
92
  - lib/hightop.rb
93
93
  - lib/hightop/enumerable.rb
94
94
  - lib/hightop/kicks.rb
95
+ - lib/hightop/mongoid.rb
95
96
  - lib/hightop/version.rb
96
97
  homepage: https://github.com/ankane/hightop
97
98
  licenses: