active_hash_relation 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4b491ebb86ce76c8bd1380597b0c1fcba6c787b5
4
- data.tar.gz: 59ce2d3323cfe3b85aa5fc50b9fc81c9414cd666
3
+ metadata.gz: 60eec7b209bc819b5c4c678f9350022252ddb7f8
4
+ data.tar.gz: 157845010e5961cdc7f12adf04fadb40f5369541
5
5
  SHA512:
6
- metadata.gz: 6580c8a889a299e994b2af5dd32d937281afce27c9583838fc793b0d93c0ef9638f7ea0e89bb283bd2bb699aae8fe1dc804953e6e7ef284890b5da0c063c220c
7
- data.tar.gz: e63134ea30cec6c28cc92dfbf46bd0689465464542c6b2d87d36d90c7fe5a57491ea0211fc3f948a17530589baa8a809af0a0191413fb1179528494ca2b236e0
6
+ metadata.gz: c357b72169fff0f28b4d9cb4b4a61941d8ebc478b80676a161ad176dbe741583b96582af699421389569816397a6487a589c070109ed4d9ab747db029b19fd52
7
+ data.tar.gz: f614659c194e246c597a9dd4a780ac13f6eb2370101a0a0239191baa09275caacee53eddea951212560738ab6eeb0b3aefc6d372aa13f0ae9c1d94984dd77683
data/README.md CHANGED
@@ -13,7 +13,15 @@ or even filter a resource based on it's associations' associations:
13
13
  ```ruby
14
14
  apply_filters(resource, {updated_at: { geq: "2014-11-2 14:25:04"}, unit: {id: 9, areas: {id: 22} }})
15
15
  ```
16
- and the list could go on.. Basically your whole db is exposed there. It's perfect for filtering a collection of resources on APIs.
16
+ and the list could go on.. Basically your whole db is exposed\* there. It's perfect for filtering a collection of resources on APIs.
17
+
18
+ It should be noted that `apply_filters` calls `ActiveHashRelation::FilterApplier` class
19
+ underneath with the same params.
20
+
21
+ _\*Actually nothing is exposed, but a user could retrieve resources based
22
+ on unknown attributes (attributes not returned from the API) by brute forcing
23
+ which might or might not be a security issue. If you don't like that check
24
+ [whitelisting](https://github.com/kollegorna/active_hash_relation#whitelisting)._
17
25
 
18
26
  ## Installation
19
27
 
@@ -82,6 +90,19 @@ You can apply an incensitive matching filter (currently working only for Postgre
82
90
 
83
91
  The above filter will search all records that include `test` in the `example_column` field. A better would be nice here, for instance, setting the search sensitive or insensitive, start or end with a string etch
84
92
 
93
+ ### Limit
94
+ A limit param defines the number of returned resources. For instance:
95
+ * `{limit: 10}`
96
+
97
+ However I would strongly advice you to use a pagination gem like Kaminari, and use `page` and `per_page` params.
98
+
99
+
100
+ ### Sorting
101
+ You can apply sorting using the `property` and `order` attributes. For instance:
102
+ * `{property: 'created_at', order: 'desc'}`
103
+
104
+ If there is no column named after the property value, sorting is skipped.
105
+
85
106
 
86
107
  ### Associations
87
108
  If the association is a `belongs_to` or `has_one`, then the hash key name must be in singular. If the association is `has_many` the attribute must be in plural reflecting the association type. When you have, in your hash, filters for an association, the sub-hash is passed in the association's model. For instance, let's say a user has many microposts and the following filter is applied (could be through an HTTP GET request on controller's index method):
@@ -103,6 +124,27 @@ will run the `.planned` scope on the resource.
103
124
  ### Whitelisting
104
125
  If you don't want to allow a column/association/scope just remove it from the params hash.
105
126
 
127
+ #### Filter Classes
128
+ Sometimes, especially on larger projects, you have specific classes that handle
129
+ the input params outside the controllers. You can configure the gem to look for
130
+ those classes and call `apply_filters` which will apply the necessary filters when
131
+ iterating over associations.
132
+
133
+ In an initializer:
134
+ ```ruby
135
+ #config/initializers/active_hash_relation.rb
136
+ ActiveHashRelation.configure do |config|
137
+ config.has_filter_classes = true
138
+ config.filter_class_prefix = 'Api::V1::'
139
+ config.filter_class_suffix = 'Filter'
140
+ end
141
+ ```
142
+ With the above settings, when the association name is `resource`,
143
+ `Api::V1::ResourceFilter.new(resource, params[resource]).apply_filters` will be
144
+ called to apply the filters in resource association.
145
+
146
+
147
+
106
148
  ## Contributing
107
149
 
108
150
  1. Fork it ( https://github.com/[my-github-username]/active_hash_relation/fork )
@@ -2,10 +2,27 @@ require "active_record/scope_names"
2
2
  require "active_hash_relation/version"
3
3
  require "active_hash_relation/column_filters"
4
4
  require "active_hash_relation/scope_filters"
5
+ require "active_hash_relation/sort_filters"
6
+ require "active_hash_relation/limit_filters"
5
7
  require "active_hash_relation/association_filters"
6
8
  require "active_hash_relation/filter_applier"
7
9
 
8
10
  module ActiveHashRelation
11
+ class << self
12
+ attr_accessor :configuration
13
+ end
14
+
15
+ def self.configure
16
+ self.configuration
17
+ yield(configuration)
18
+ end
19
+
20
+ def self.configuration
21
+ @configuration ||= Configuration.new do
22
+ self.has_filter_classes = false
23
+ end
24
+ end
25
+
9
26
  def apply_filters(resource, params, include_associations: false, model: nil)
10
27
  FilterApplier.new(
11
28
  resource,
@@ -14,4 +31,9 @@ module ActiveHashRelation
14
31
  model: model
15
32
  ).apply_filters
16
33
  end
34
+
35
+ class Configuration
36
+ attr_accessor :has_filter_classes, :filter_class_prefix, :filter_class_suffix
37
+ end
38
+
17
39
  end
@@ -7,11 +7,19 @@ module ActiveHashRelation::AssociationFilters
7
7
  model.reflect_on_all_associations.map(&:name).each do |association|
8
8
  if params[association]
9
9
  association_name = association.to_s.titleize.split.join
10
- association_filters = ActiveHashRelation::FilterApplier.new(
11
- association_name.singularize.constantize.all,
12
- params[association],
13
- include_associations: true
14
- ).apply_filters
10
+ if self.configuration.has_filter_classes
11
+ puts self.filter_class(association_name)
12
+ association_filters = self.filter_class(association_name).new(
13
+ association_name.singularize.constantize.all,
14
+ params[association]
15
+ ).apply_filters
16
+ else
17
+ association_filters = ActiveHashRelation::FilterApplier.new(
18
+ association_name.singularize.constantize.all,
19
+ params[association],
20
+ include_associations: true
21
+ ).apply_filters
22
+ end
15
23
  resource = resource.joins(association).merge(association_filters)
16
24
  end
17
25
  end
@@ -63,13 +63,13 @@ module ActiveHashRelation::ColumnFilters
63
63
  if param[:leq]
64
64
  resource = resource.where("#{table_name}.#{column} <= ?", param[:leq])
65
65
  elsif param[:le]
66
- resource = resource.where("#{table_name}.#{column} < ?", param[:leq])
66
+ resource = resource.where("#{table_name}.#{column} < ?", param[:le])
67
67
  end
68
68
 
69
69
  if param[:geq]
70
70
  resource = resource.where("#{table_name}.#{column} >= ?", param[:geq])
71
71
  elsif param[:ge]
72
- resource = resource.where("#{table_name}.#{column} > ?", param[:geq])
72
+ resource = resource.where("#{table_name}.#{column} > ?", param[:ge])
73
73
  end
74
74
 
75
75
  return resource
@@ -3,8 +3,13 @@ module ActiveHashRelation
3
3
  include ColumnFilters
4
4
  include AssociationFilters
5
5
  include ScopeFilters
6
+ include SortFilters
7
+ include LimitFilters
6
8
 
7
- def initialize(resource, params, include_associations: false, model: nil)
9
+ attr_reader :configuration
10
+
11
+ def initialize(resource, params, include_associations: true, model: nil)
12
+ @configuration = Module.nesting.last.configuration
8
13
  @resource = resource
9
14
  @params = HashWithIndifferentAccess.new(params)
10
15
  @include_associations = include_associations
@@ -20,7 +25,18 @@ module ActiveHashRelation
20
25
  @model.columns.each do |c|
21
26
  next if @params[c.name.to_s].nil?
22
27
 
23
- @resource = filter_primary(@resource, c.name, @params[c.name]) and next if c.primary
28
+ if c.respond_to?(:primary)
29
+ if c.primary
30
+ @resource = filter_primary(@resource, c.name, @params[c.name])
31
+ next
32
+ end
33
+ else #rails 4.2
34
+ if @model.primary_key == c.name
35
+ @resource = filter_primary(@resource, c.name, @params[c.name])
36
+ next
37
+ end
38
+ end
39
+
24
40
  case c.type
25
41
  when :integer
26
42
  @resource = filter_integer(@resource, c.name, table_name, @params[c.name])
@@ -41,10 +57,15 @@ module ActiveHashRelation
41
57
 
42
58
 
43
59
  @resource = filter_scopes(@resource, @params[:scopes]) if @params.include?(:scopes)
44
- @resource = filter_associations(@resource, @params)
60
+ @resource = filter_associations(@resource, @params) if @include_associations
61
+ @resource = apply_limit(@resource, @params[:limit]) if @params.include?(:limit)
62
+ @resource = apply_sort(@resource, @params[:sort], @model) if @params.include?(:sort)
45
63
 
46
64
  return @resource
47
65
  end
48
66
 
67
+ def filter_class(resource_name)
68
+ "#{configuration.filter_class_prefix}#{resource_name.pluralize}#{configuration.filter_class_suffix}".constantize
69
+ end
49
70
  end
50
71
  end
@@ -0,0 +1,5 @@
1
+ module ActiveHashRelation::LimitFilters
2
+ def apply_limit(resource, limit)
3
+ return resource.limit(limit)
4
+ end
5
+ end
@@ -0,0 +1,9 @@
1
+ module ActiveHashRelation::SortFilters
2
+ def apply_sort(resource, params, model = nil)
3
+ if model.columns.map(&:name).include?(params[:property])
4
+ resource = resource.order(params[:property] => (params[:order] || :desc) )
5
+ end
6
+
7
+ return resource
8
+ end
9
+ end
@@ -1,3 +1,3 @@
1
1
  module ActiveHashRelation
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_hash_relation
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Filippos Vasilakis
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-26 00:00:00.000000000 Z
11
+ date: 2015-05-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -56,7 +56,9 @@ files:
56
56
  - lib/active_hash_relation/association_filters.rb
57
57
  - lib/active_hash_relation/column_filters.rb
58
58
  - lib/active_hash_relation/filter_applier.rb
59
+ - lib/active_hash_relation/limit_filters.rb
59
60
  - lib/active_hash_relation/scope_filters.rb
61
+ - lib/active_hash_relation/sort_filters.rb
60
62
  - lib/active_hash_relation/version.rb
61
63
  - lib/active_record/scope_names.rb
62
64
  homepage: https://www.kollegorna.se