forest_liana 1.0.11 → 1.1.0
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 +4 -4
- data/app/controllers/forest_liana/application_controller.rb +6 -2
- data/app/controllers/forest_liana/associations_controller.rb +51 -0
- data/app/controllers/forest_liana/resources_controller.rb +4 -1
- data/app/serializers/forest_liana/serializer_factory.rb +9 -5
- data/app/services/forest_liana/has_many_getter.rb +51 -0
- data/app/services/forest_liana/operator_value_parser.rb +27 -0
- data/app/services/forest_liana/resources_getter.rb +11 -8
- data/app/services/forest_liana/search_query_builder.rb +68 -32
- data/app/services/forest_liana/stripe_cards_getter.rb +5 -1
- data/app/services/forest_liana/stripe_invoices_getter.rb +3 -2
- data/app/services/forest_liana/stripe_payments_getter.rb +1 -1
- data/config/routes.rb +5 -1
- data/lib/forest_liana/version.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 051a5e7bf351ed5dd2d28b37ea29b5192ad9c582
|
4
|
+
data.tar.gz: 651bdcb3580a39e12c11c2eee7972689ae63270e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d5dedba47b186325219c94bf60a097deeb3ba67636a95149ed95a348b51252a29642b180a7c4932309934c32a9c4ccf689784a73256e766e61d9a7a640190a60
|
7
|
+
data.tar.gz: 4c4744360e8503260df8c1d63bb43b456b89ef9841e97c6535dae58b496e217e268c04bb960df35dec3f9758e5b72f176da50788417d6e9952d58bf0a158dc80
|
@@ -27,8 +27,12 @@ module ForestLiana
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def authenticate_user_from_jwt
|
30
|
-
|
31
|
-
|
30
|
+
if request.headers['Authorization']
|
31
|
+
JWT.decode request.headers['Authorization'].split[1],
|
32
|
+
ForestLiana.jwt_signing_key
|
33
|
+
else
|
34
|
+
render nothing: true, status: 401
|
35
|
+
end
|
32
36
|
end
|
33
37
|
|
34
38
|
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module ForestLiana
|
2
|
+
class AssociationsController < ForestLiana::ApplicationController
|
3
|
+
|
4
|
+
before_filter :find_resource
|
5
|
+
before_filter :find_association
|
6
|
+
|
7
|
+
def index
|
8
|
+
getter = HasManyGetter.new(@resource, @association, params)
|
9
|
+
getter.perform
|
10
|
+
|
11
|
+
render json: serialize_models(getter.records,
|
12
|
+
include: includes,
|
13
|
+
count: getter.count,
|
14
|
+
params: params)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def find_resource
|
20
|
+
@resource = SchemaUtils.find_model_from_table_name(params[:collection])
|
21
|
+
|
22
|
+
if @resource.nil? || !@resource.ancestors.include?(ActiveRecord::Base)
|
23
|
+
render json: {status: 404}, status: :not_found
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def find_association
|
28
|
+
@association = @resource.reflect_on_association(
|
29
|
+
params[:association_name])
|
30
|
+
|
31
|
+
if @association.nil?
|
32
|
+
render json: {status: 404}, status: :not_found
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def resource_params
|
37
|
+
ResourceDeserializer.new(@resource, params[:resource]).perform
|
38
|
+
end
|
39
|
+
|
40
|
+
def includes
|
41
|
+
@association.klass
|
42
|
+
.reflect_on_all_associations
|
43
|
+
.select do |a|
|
44
|
+
[:belongs_to, :has_and_belongs_to_many].include?(a.macro) &&
|
45
|
+
!a.options[:polymorphic]
|
46
|
+
end
|
47
|
+
.map {|a| a.name.to_s }
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
@@ -64,7 +64,10 @@ module ForestLiana
|
|
64
64
|
def includes
|
65
65
|
@resource
|
66
66
|
.reflect_on_all_associations
|
67
|
-
.select
|
67
|
+
.select do |a|
|
68
|
+
[:belongs_to, :has_and_belongs_to_many].include?(a.macro) &&
|
69
|
+
!a.options[:polymorphic]
|
70
|
+
end
|
68
71
|
.map {|a| a.name.to_s }
|
69
72
|
end
|
70
73
|
|
@@ -36,7 +36,7 @@ module ForestLiana
|
|
36
36
|
include JSONAPI::Serializer
|
37
37
|
|
38
38
|
def self_link
|
39
|
-
"/forest#{super}"
|
39
|
+
"/forest#{super.underscore}"
|
40
40
|
end
|
41
41
|
|
42
42
|
def type
|
@@ -56,12 +56,16 @@ module ForestLiana
|
|
56
56
|
end
|
57
57
|
|
58
58
|
def relationship_related_link(attribute_name)
|
59
|
+
ret = {
|
60
|
+
href: "#{self_link}/#{format_name(attribute_name)}"
|
61
|
+
}
|
62
|
+
|
59
63
|
relationship_records = object.send(attribute_name)
|
60
|
-
|
64
|
+
if relationship_records.respond_to?(:each)
|
65
|
+
ret[:meta] = { count: relationship_records.count }
|
66
|
+
end
|
61
67
|
|
62
|
-
|
63
|
-
meta: { count: relationship_records.count }
|
64
|
-
}
|
68
|
+
ret
|
65
69
|
end
|
66
70
|
}
|
67
71
|
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module ForestLiana
|
2
|
+
class HasManyGetter
|
3
|
+
def initialize(resource, association, params)
|
4
|
+
@resource = resource
|
5
|
+
@association = association
|
6
|
+
@params = params
|
7
|
+
end
|
8
|
+
|
9
|
+
def perform
|
10
|
+
@records = @resource.find(@params[:id]).send(@params[:association_name])
|
11
|
+
|
12
|
+
@records
|
13
|
+
end
|
14
|
+
|
15
|
+
def records
|
16
|
+
@records.limit(limit).offset(offset)
|
17
|
+
end
|
18
|
+
|
19
|
+
def count
|
20
|
+
@records.to_a.length
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def offset
|
26
|
+
return 0 unless pagination?
|
27
|
+
|
28
|
+
number = @params[:page][:number]
|
29
|
+
if number && number.to_i > 0
|
30
|
+
(number.to_i - 1) * limit
|
31
|
+
else
|
32
|
+
0
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def limit
|
37
|
+
return 10 unless pagination?
|
38
|
+
|
39
|
+
if @params[:page][:size]
|
40
|
+
@params[:page][:size].to_i
|
41
|
+
else
|
42
|
+
10
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def pagination?
|
47
|
+
@params[:page] && @params[:page][:number]
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module ForestLiana
|
2
|
+
class OperatorValueParser
|
3
|
+
|
4
|
+
def self.parse(value)
|
5
|
+
operator = nil
|
6
|
+
|
7
|
+
if value.first == '!'
|
8
|
+
operator = '!='
|
9
|
+
value.slice!(0)
|
10
|
+
elsif value.first == '>'
|
11
|
+
operator = '>'
|
12
|
+
value.slice!(0)
|
13
|
+
elsif value.first == '<'
|
14
|
+
operator = '<'
|
15
|
+
value.slice!(0)
|
16
|
+
elsif value.include?('*')
|
17
|
+
operator = 'ILIKE'
|
18
|
+
value.gsub!('*', '%')
|
19
|
+
else
|
20
|
+
operator = '='
|
21
|
+
end
|
22
|
+
|
23
|
+
[operator, value]
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
@@ -6,8 +6,10 @@ module ForestLiana
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def perform
|
9
|
-
@
|
9
|
+
@records = search_query
|
10
10
|
@records = sort_query
|
11
|
+
|
12
|
+
@records
|
11
13
|
end
|
12
14
|
|
13
15
|
def records
|
@@ -15,13 +17,13 @@ module ForestLiana
|
|
15
17
|
end
|
16
18
|
|
17
19
|
def count
|
18
|
-
@
|
20
|
+
@records.to_a.count
|
19
21
|
end
|
20
22
|
|
21
23
|
private
|
22
24
|
|
23
25
|
def search_query
|
24
|
-
SearchQueryBuilder.new(@resource
|
26
|
+
SearchQueryBuilder.new(@resource, @params).perform
|
25
27
|
end
|
26
28
|
|
27
29
|
def sort_query
|
@@ -32,7 +34,8 @@ module ForestLiana
|
|
32
34
|
field = detect_reference(field)
|
33
35
|
|
34
36
|
association = @resource.reflect_on_association(field.to_sym)
|
35
|
-
if [:has_many, :has_and_belongs_to_many].include?(
|
37
|
+
if [:has_many, :has_and_belongs_to_many].include?(
|
38
|
+
association.try(:macro))
|
36
39
|
@records = has_many_sort(association, order)
|
37
40
|
else
|
38
41
|
@records = @records.order("#{field} #{order.upcase}")
|
@@ -52,11 +55,12 @@ module ForestLiana
|
|
52
55
|
def has_many_sort(association, order)
|
53
56
|
@records
|
54
57
|
.select("#{@resource.table_name}.*,
|
55
|
-
COUNT(#{association.table_name}.id)
|
58
|
+
COUNT(#{association.table_name}.id)
|
59
|
+
#{association.table_name}_has_many_count")
|
56
60
|
.joins(ArelHelpers.join_association(@resource, association.name,
|
57
61
|
Arel::Nodes::OuterJoin))
|
58
62
|
.group("#{@resource.table_name}.id")
|
59
|
-
.order("
|
63
|
+
.order("#{association.table_name}_has_many_count #{order.upcase}")
|
60
64
|
end
|
61
65
|
|
62
66
|
def detect_sort_order(field)
|
@@ -81,8 +85,7 @@ module ForestLiana
|
|
81
85
|
end
|
82
86
|
|
83
87
|
def includes
|
84
|
-
SchemaUtils.associations(@resource).
|
85
|
-
.map(&:name)
|
88
|
+
SchemaUtils.associations(@resource).map(&:name)
|
86
89
|
end
|
87
90
|
|
88
91
|
def offset
|
@@ -2,16 +2,16 @@ module ForestLiana
|
|
2
2
|
class SearchQueryBuilder
|
3
3
|
|
4
4
|
def initialize(resource, params)
|
5
|
-
@resource = resource
|
5
|
+
@resource = @records = resource
|
6
6
|
@params = params
|
7
7
|
end
|
8
8
|
|
9
9
|
def perform
|
10
|
-
search_param
|
11
|
-
filter_param
|
12
|
-
|
10
|
+
@records = search_param
|
11
|
+
@records = filter_param
|
12
|
+
@records = has_many_filter
|
13
13
|
|
14
|
-
@
|
14
|
+
@records
|
15
15
|
end
|
16
16
|
|
17
17
|
def search_param
|
@@ -28,49 +28,85 @@ module ForestLiana
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
-
@
|
31
|
+
@records = @resource.where(conditions.join(' OR '))
|
32
32
|
end
|
33
|
+
|
34
|
+
@records
|
33
35
|
end
|
34
36
|
|
35
37
|
def filter_param
|
36
38
|
if @params[:filter]
|
37
39
|
@params[:filter].each do |field, value|
|
40
|
+
next if association?(field)
|
38
41
|
|
39
|
-
operator =
|
40
|
-
|
41
|
-
operator = '!='
|
42
|
-
value.slice!(0)
|
43
|
-
elsif value.first == '>'
|
44
|
-
operator = '>'
|
45
|
-
value.slice!(0)
|
46
|
-
elsif value.first == '<'
|
47
|
-
operator = '<'
|
48
|
-
value.slice!(0)
|
49
|
-
elsif value.include?('*')
|
50
|
-
operator = 'ILIKE'
|
51
|
-
value.gsub!('*', '%')
|
52
|
-
else
|
53
|
-
operator = '='
|
54
|
-
end
|
55
|
-
|
56
|
-
@resource = @resource.where("#{field} #{operator} '#{value}'")
|
42
|
+
operator, value = OperatorValueParser.parse(value)
|
43
|
+
@records = @resource.where("#{field} #{operator} '#{value}'")
|
57
44
|
end
|
58
45
|
end
|
46
|
+
|
47
|
+
@records
|
48
|
+
end
|
49
|
+
|
50
|
+
def association?(field)
|
51
|
+
field = field.split(':').first if field.include?(':')
|
52
|
+
@resource.reflect_on_association(field.to_sym).present?
|
59
53
|
end
|
60
54
|
|
61
|
-
def
|
62
|
-
|
55
|
+
def has_many_association?(field)
|
56
|
+
field = field.split(':').first if field.include?(':')
|
57
|
+
association = @resource.reflect_on_association(field.to_sym)
|
58
|
+
|
59
|
+
association.try(:macro) === :has_many
|
60
|
+
end
|
63
61
|
|
64
|
-
|
65
|
-
|
62
|
+
def has_many_filter
|
63
|
+
if @params[:filter]
|
64
|
+
@params[:filter].each do |field, value|
|
65
|
+
next unless has_many_association?(field)
|
66
66
|
|
67
|
-
|
68
|
-
|
69
|
-
|
67
|
+
if field.include?(':')
|
68
|
+
@records = has_many_subfield_filter(field, value)
|
69
|
+
else
|
70
|
+
@records = has_many_field_filter(field, value)
|
71
|
+
end
|
70
72
|
end
|
71
73
|
end
|
74
|
+
|
75
|
+
@records
|
76
|
+
end
|
77
|
+
|
78
|
+
def has_many_field_filter(field, value)
|
79
|
+
association = @resource.reflect_on_association(field.to_sym)
|
80
|
+
return if association.blank?
|
81
|
+
|
82
|
+
operator, value = OperatorValueParser.parse(value)
|
83
|
+
|
84
|
+
@records = @records
|
85
|
+
.select("#{@resource.table_name}.*,
|
86
|
+
COUNT(#{association.table_name}.id)
|
87
|
+
#{association.table_name}_has_many_count")
|
88
|
+
.joins(ArelHelpers.join_association(@resource, association.name,
|
89
|
+
Arel::Nodes::OuterJoin))
|
90
|
+
.group("#{@resource.table_name}.id")
|
91
|
+
.having("COUNT(#{association.table_name}) #{operator} #{value}")
|
72
92
|
end
|
73
93
|
|
94
|
+
def has_many_subfield_filter(field, value)
|
95
|
+
field, subfield = field.split(':')
|
96
|
+
|
97
|
+
association = @resource.reflect_on_association(field.to_sym)
|
98
|
+
return if association.blank?
|
99
|
+
|
100
|
+
operator, value = OperatorValueParser.parse(value)
|
101
|
+
|
102
|
+
@records = @records
|
103
|
+
.select("#{@resource.table_name}.*,
|
104
|
+
COUNT(#{association.table_name}.id)
|
105
|
+
#{association.table_name}_has_many_count")
|
106
|
+
.joins(ArelHelpers.join_association(@resource, association.name,
|
107
|
+
Arel::Nodes::OuterJoin))
|
108
|
+
.group("#{@resource.table_name}.id, #{association.table_name}.#{subfield}")
|
109
|
+
.having("#{association.table_name}.#{subfield} #{operator} '#{value}'")
|
110
|
+
end
|
74
111
|
end
|
75
112
|
end
|
76
|
-
|
@@ -19,7 +19,11 @@ module ForestLiana
|
|
19
19
|
resource = @reference_model.find(reference_model_id)
|
20
20
|
customer = resource[@reference_field]
|
21
21
|
|
22
|
-
|
22
|
+
if customer.blank?
|
23
|
+
@records = []
|
24
|
+
else
|
25
|
+
fetch_cards(customer, params)
|
26
|
+
end
|
23
27
|
end
|
24
28
|
|
25
29
|
def fetch_cards(customer, params)
|
@@ -27,8 +27,9 @@ module ForestLiana
|
|
27
27
|
d.date = Time.at(d.date).to_datetime
|
28
28
|
d.period_start = Time.at(d.period_start).to_datetime
|
29
29
|
d.period_end = Time.at(d.period_end).to_datetime
|
30
|
-
d.subtotal /= 100
|
31
|
-
d.total /= 100
|
30
|
+
d.subtotal /= 100.00
|
31
|
+
d.total /= 100.00
|
32
|
+
d.amount_due /= 100.00
|
32
33
|
|
33
34
|
query = {}
|
34
35
|
query[@reference_field] = d.customer
|
data/config/routes.rb
CHANGED
@@ -1,14 +1,18 @@
|
|
1
1
|
ForestLiana::Engine.routes.draw do
|
2
|
+
# Stripe Integration
|
2
3
|
get 'stripe_payments' => 'stripe#payments'
|
3
4
|
post 'stripe_payments/refunds' => 'stripe#refund'
|
4
5
|
get 'stripe_cards' => 'stripe#cards'
|
5
6
|
get 'stripe_invoices' => 'stripe#invoices'
|
6
7
|
|
8
|
+
# CRUD
|
7
9
|
get '/' => 'apimaps#index'
|
8
10
|
get ':collection' => 'resources#index'
|
9
11
|
get ':collection/:id' => 'resources#show'
|
10
|
-
get ':collection/:id' => 'resources#show'
|
11
12
|
post ':collection' => 'resources#create'
|
12
13
|
put ':collection/:id' => 'resources#update'
|
13
14
|
delete ':collection/:id' => 'resources#destroy'
|
15
|
+
|
16
|
+
# Associations
|
17
|
+
get ':collection/:id/:association_name' => 'associations#index'
|
14
18
|
end
|
data/lib/forest_liana/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: forest_liana
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sandro Munda
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-10-
|
11
|
+
date: 2015-10-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -109,6 +109,7 @@ files:
|
|
109
109
|
- app/assets/stylesheets/scaffold.css
|
110
110
|
- app/controllers/forest_liana/apimaps_controller.rb
|
111
111
|
- app/controllers/forest_liana/application_controller.rb
|
112
|
+
- app/controllers/forest_liana/associations_controller.rb
|
112
113
|
- app/controllers/forest_liana/resources_controller.rb
|
113
114
|
- app/controllers/forest_liana/stripe_controller.rb
|
114
115
|
- app/deserializers/forest_liana/resource_deserializer.rb
|
@@ -119,6 +120,8 @@ files:
|
|
119
120
|
- app/serializers/forest_liana/stripe_card_serializer.rb
|
120
121
|
- app/serializers/forest_liana/stripe_invoice_serializer.rb
|
121
122
|
- app/serializers/forest_liana/stripe_payment_serializer.rb
|
123
|
+
- app/services/forest_liana/has_many_getter.rb
|
124
|
+
- app/services/forest_liana/operator_value_parser.rb
|
122
125
|
- app/services/forest_liana/resource_getter.rb
|
123
126
|
- app/services/forest_liana/resources_getter.rb
|
124
127
|
- app/services/forest_liana/schema_adapter.rb
|