active_hash_relation 0.0.1 → 0.0.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
  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