forest_liana 1.9.8 → 2.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9ce5ea697e568c0b4a0e09ab82d43f3282ca521d
4
- data.tar.gz: 3c2f2d65713d2eebd007e8b43bbdbdc0566835ae
3
+ metadata.gz: 3afa4336e04821ea77f04fca3e91dee2151dfa58
4
+ data.tar.gz: 3260318c1d5da96ff29a4fac1fd6e1b4b28d101e
5
5
  SHA512:
6
- metadata.gz: 27cfc6f40884c10ff33f1e8880ebdc8d834f5b627f5095093b56301e4ac30f4b9f8d9cd64ce33a687139229e58687a741829c95b7de6bbba50645c4cf870a524
7
- data.tar.gz: 3fbb9eea9f7a0d75edd6eea0a037f66c2e43d99e31028b54e78bbed564a8d826a9ca0a8b89757a6e9d9120ef5aba6645f7d476b8698a077801d1452db220fb94
6
+ metadata.gz: 79e39acc9781c653d474631f89f09bd1570821b972f6a37c84ba3e8be829f8b4a7f3c67516944a5ae65ee654f4a2d047ee6d58dbbaddafc6699d9185686da02d
7
+ data.tar.gz: 551c111d11d8fbba8f00f7a115aae474fb35d950f3ef8f529c21c420e3c6eacc1d2b2f4e17cfd7a2ff8ccdbec5bfc3b0c0729c0e015816833d9c18c11a0eb678
@@ -14,7 +14,7 @@ module ForestLiana
14
14
 
15
15
  respond_to do |format|
16
16
  format.json { render_jsonapi(getter) }
17
- format.csv { render_csv(getter, @association) }
17
+ format.csv { render_csv(getter, @association.klass) }
18
18
  end
19
19
  end
20
20
 
@@ -71,8 +71,18 @@ module ForestLiana
71
71
  ResourceDeserializer.new(@resource, params[:resource], true).perform
72
72
  end
73
73
 
74
+ def is_sti_model?
75
+ @is_sti_model ||= (@association.klass.inheritance_column.present? &&
76
+ @association.klass.columns.any? { |column| column.name == @association.klass.inheritance_column })
77
+ end
78
+
79
+ def get_record record
80
+ is_sti_model? ? record.becomes(@association.klass) : record
81
+ end
82
+
74
83
  def render_jsonapi getter
75
- render serializer: nil, json: serialize_models(getter.records,
84
+ records = getter.records.map { |record| get_record(record) }
85
+ render serializer: nil, json: serialize_models(records,
76
86
  include: getter.includes, count: getter.count, params: params)
77
87
  end
78
88
  end
@@ -28,7 +28,7 @@ module ForestLiana
28
28
  getter.perform
29
29
 
30
30
  render serializer: nil, json:
31
- serialize_model(getter.record, include: includes(getter))
31
+ serialize_model(get_record(getter.record), include: includes(getter))
32
32
  end
33
33
 
34
34
  def create
@@ -40,7 +40,7 @@ module ForestLiana
40
40
  creator.errors), status: 400
41
41
  elsif creator.record.valid?
42
42
  render serializer: nil,
43
- json: serialize_model(creator.record, include: record_includes)
43
+ json: serialize_model(get_record(creator.record), include: record_includes)
44
44
  else
45
45
  render serializer: nil, json: JSONAPI::Serializer.serialize_errors(
46
46
  creator.record.errors), status: 400
@@ -56,7 +56,7 @@ module ForestLiana
56
56
  updater.errors), status: 400
57
57
  elsif updater.record.valid?
58
58
  render serializer: nil,
59
- json: serialize_model(updater.record, include: record_includes)
59
+ json: serialize_model(get_record(updater.record), include: record_includes)
60
60
  else
61
61
  render serializer: nil, json: JSONAPI::Serializer.serialize_errors(
62
62
  updater.record.errors), status: 400
@@ -65,7 +65,6 @@ module ForestLiana
65
65
 
66
66
  def destroy
67
67
  @resource.destroy(params[:id])
68
-
69
68
  head :no_content
70
69
  end
71
70
 
@@ -94,8 +93,18 @@ module ForestLiana
94
93
  head :not_found
95
94
  end
96
95
 
96
+ def is_sti_model?
97
+ @is_sti_model ||= (@resource.inheritance_column.present? &&
98
+ @resource.columns.any? { |column| column.name == @resource.inheritance_column })
99
+ end
100
+
101
+ def get_record record
102
+ is_sti_model? ? record.becomes(@resource) : record
103
+ end
104
+
97
105
  def render_jsonapi getter
98
- render serializer: nil, json: serialize_models(getter.records,
106
+ records = getter.records.map { |record| get_record(record) }
107
+ render serializer: nil, json: serialize_models(records,
99
108
  include: includes(getter), count: getter.count, params: params)
100
109
  end
101
110
  end
@@ -1,8 +1,7 @@
1
1
  class ForestLiana::Router
2
2
  def call(env)
3
3
  params = env['action_dispatch.request.path_parameters']
4
- resource = ForestLiana::SchemaUtils.find_model_from_collection_name(
5
- params[:collection])
4
+ resource = ForestLiana::SchemaUtils.find_model_from_collection_name(params[:collection])
6
5
 
7
6
  begin
8
7
  class_name = ForestLiana.name_for(resource).classify
@@ -6,7 +6,9 @@ class ForestLiana::Model::Collection
6
6
 
7
7
  attr_accessor :name, :fields, :actions, :segments, :only_for_relationships,
8
8
  :is_virtual, :is_read_only, :is_searchable, :display_name, :icon,
9
- :integration, :pagination_type, :search_fields
9
+ :integration, :pagination_type, :search_fields,
10
+ # TODO: Remove once lianas prior to 2.0.0 are not supported anymore.
11
+ :name_old
10
12
 
11
13
  def initialize(attributes = {})
12
14
  @actions = []
@@ -4,6 +4,7 @@ class ForestLiana::CollectionSerializer
4
4
  include JSONAPI::Serializer
5
5
 
6
6
  attribute :name
7
+ attribute :name_old # TODO: Remove once lianas prior to 2.0.0 are not supported anymore.
7
8
  attribute :display_name
8
9
  attribute :icon
9
10
  attribute :integration
@@ -1,9 +1,7 @@
1
1
  module ForestLiana
2
2
  class BaseGetter
3
- def get_current_collection(table_name)
4
- ForestLiana.apimap.find do |collection|
5
- collection.name.to_s == table_name
6
- end
3
+ def get_collection(collection_name)
4
+ ForestLiana.apimap.find { |collection| collection.name.to_s == collection_name }
7
5
  end
8
6
 
9
7
  def get_resource
@@ -5,7 +5,7 @@ module ForestLiana
5
5
  @association = association
6
6
  @params = params
7
7
  @field_names_requested = field_names_requested
8
- @current_collection = get_current_collection(ForestLiana.name_for(model_association))
8
+ @collection = get_collection(ForestLiana.name_for(model_association))
9
9
  end
10
10
 
11
11
  def perform
@@ -19,8 +19,7 @@ module ForestLiana
19
19
 
20
20
  def search_query
21
21
  includesSymbols = includes.map { |association| association.to_sym }
22
- SearchQueryBuilder.new(@records, @params,
23
- includesSymbols, @current_collection).perform
22
+ SearchQueryBuilder.new(@records, @params, includesSymbols, @collection).perform
24
23
  end
25
24
 
26
25
  def includes
@@ -4,7 +4,8 @@ module ForestLiana
4
4
  @resource = resource
5
5
  @params = params
6
6
  @count_needs_includes = false
7
- @current_collection = get_current_collection(@resource.table_name)
7
+ @collection_name = ForestLiana.name_for(@resource)
8
+ @collection = get_collection(@collection_name)
8
9
  @field_names_requested = field_names_requested
9
10
  get_segment()
10
11
  end
@@ -49,8 +50,8 @@ module ForestLiana
49
50
  .map(&:name)
50
51
  includes_for_smart_search = []
51
52
 
52
- if @current_collection && @current_collection.search_fields
53
- includes_for_smart_search = @current_collection.search_fields
53
+ if @collection && @collection.search_fields
54
+ includes_for_smart_search = @collection.search_fields
54
55
  .select { |field| field.include? '.' }
55
56
  .map { |field| field.split('.').first.to_sym }
56
57
 
@@ -72,15 +73,14 @@ module ForestLiana
72
73
 
73
74
  def get_segment
74
75
  if @params[:segment]
75
- @segment = @current_collection.segments.find do |segment|
76
+ @segment = @collection.segments.find do |segment|
76
77
  segment.name == @params[:segment]
77
78
  end
78
79
  end
79
80
  end
80
81
 
81
82
  def field_names_requested
82
- collection_name = ForestLiana.name_for(@resource)
83
- return nil unless @params[:fields] && @params[:fields][collection_name]
83
+ return nil unless @params[:fields] && @params[:fields][@collection_name]
84
84
 
85
85
  associations_for_query = []
86
86
 
@@ -100,12 +100,12 @@ module ForestLiana
100
100
  associations_for_query << @params[:sort].split('.').first.to_sym
101
101
  end
102
102
 
103
- field_names = @params[:fields][collection_name].split(',').map { |name| name.to_sym }
103
+ field_names = @params[:fields][@collection_name].split(',').map { |name| name.to_sym }
104
104
  field_names | associations_for_query
105
105
  end
106
106
 
107
107
  def search_query
108
- SearchQueryBuilder.new(@records, @params, includes, @current_collection).perform
108
+ SearchQueryBuilder.new(@records, @params, includes, @collection).perform
109
109
  end
110
110
 
111
111
  def sort_query
@@ -42,6 +42,20 @@ module ForestLiana
42
42
  end
43
43
  end
44
44
 
45
+ # NOTICE: Define an automatic segment for each STI child model.
46
+ if is_sti_parent?
47
+ column_type = @model.inheritance_column
48
+ @model.descendants.each do |submodel_sti|
49
+ type = submodel_sti.sti_name
50
+ name = type.pluralize
51
+ collection.segments << ForestLiana::Model::Segment.new({
52
+ id: name,
53
+ name: name,
54
+ where: lambda { { column_type => type } }
55
+ })
56
+ end
57
+ end
58
+
45
59
  collection
46
60
  end
47
61
 
@@ -49,13 +63,15 @@ module ForestLiana
49
63
 
50
64
  def collection
51
65
  @collection ||= begin
52
- collection = ForestLiana.apimap.find do |x|
53
- x.name.to_s == ForestLiana.name_for(@model)
66
+ collection = ForestLiana.apimap.find do |object|
67
+ object.name.to_s == ForestLiana.name_for(@model)
54
68
  end
55
69
 
56
70
  if collection.blank?
57
71
  collection = ForestLiana::Model::Collection.new({
58
72
  name: ForestLiana.name_for(@model),
73
+ # TODO: Remove once lianas prior to 2.0.0 are not supported anymore.
74
+ name_old: ForestLiana.name_old_for(@model),
59
75
  fields: []
60
76
  })
61
77
 
@@ -73,7 +89,9 @@ module ForestLiana
73
89
 
74
90
  def add_columns
75
91
  @model.columns.each do |column|
76
- collection.fields << get_schema_for_column(column)
92
+ unless is_sti_column_of_child_model?(column)
93
+ collection.fields << get_schema_for_column(column)
94
+ end
77
95
  end
78
96
 
79
97
  # NOTICE: Add Intercom fields
@@ -193,7 +211,7 @@ module ForestLiana
193
211
  # NOTICE: The foreign key exists, so it's a belongsTo relationship.
194
212
  elsif (field = column_association(collection, association)) &&
195
213
  [:has_one, :belongs_to].include?(association.macro)
196
- field[:reference] = get_ref_for(association)
214
+ field[:reference] = get_reference_for(association)
197
215
  field[:field] = association.name
198
216
  field[:inverseOf] = inverse_of(association)
199
217
  # NOTICE: Create the fields of hasOne, HasMany, … relationships.
@@ -297,6 +315,17 @@ module ForestLiana
297
315
  column.name == @model.inheritance_column) || column.name == 'type'
298
316
  end
299
317
 
318
+ def is_sti_parent?
319
+ return false unless @model.try(:table_exists?)
320
+
321
+ @model.inheritance_column &&
322
+ @model.columns.find { |column| column.name == @model.inheritance_column }
323
+ end
324
+
325
+ def is_sti_column_of_child_model?(column)
326
+ sti_column?(column) && @model.descendants.empty?
327
+ end
328
+
300
329
  def add_default_value(column_schema, column)
301
330
  # TODO: detect/introspect the attribute default value with Rails 5
302
331
  # ex: attribute :email, :string, default: 'arnaud@forestadmin.com'
@@ -398,11 +427,11 @@ module ForestLiana
398
427
  column_schema
399
428
  end
400
429
 
401
- def get_ref_for(association)
430
+ def get_reference_for(association)
402
431
  if association.options[:polymorphic] == true
403
432
  '*.id'
404
433
  else
405
- "#{ForestLiana.name_for(association.klass).underscore}.id"
434
+ "#{ForestLiana.name_for(association.klass)}.id"
406
435
  end
407
436
  end
408
437
 
@@ -20,19 +20,23 @@ module ForestLiana
20
20
  end
21
21
 
22
22
  def self.find_model_from_collection_name(collection_name)
23
- model = nil
24
-
25
- ForestLiana.models.each do |subclass|
26
- if subclass.abstract_class?
27
- model = self.find_model_from_abstract_class(subclass, collection_name)
28
- elsif ForestLiana.name_for(subclass) == collection_name
29
- model = subclass.base_class
23
+ model_found = nil
24
+
25
+ ForestLiana.models.each do |model|
26
+ if model.abstract_class?
27
+ model_found = self.find_model_from_abstract_class(model, collection_name)
28
+ elsif ForestLiana.name_for(model) == collection_name
29
+ if self.sti_child?(model)
30
+ model_found = model
31
+ else
32
+ model_found = model.base_class
33
+ end
30
34
  end
31
35
 
32
- break if model
36
+ break if model_found
33
37
  end
34
38
 
35
- model
39
+ model_found
36
40
  end
37
41
 
38
42
  def self.tables_names
@@ -74,11 +78,12 @@ module ForestLiana
74
78
  def self.sti_child?(model)
75
79
  begin
76
80
  parent = model.try(:superclass)
81
+ return false unless parent.try(:table_name)
77
82
 
78
83
  if ForestLiana.name_for(parent)
79
- inheritance_column = parent.columns.find do |c|
80
- (parent.inheritance_column && c.name == parent.inheritance_column)\
81
- || c.name == 'type'
84
+ inheritance_column = parent.columns.find do |column|
85
+ (parent.inheritance_column && column.name == parent.inheritance_column)\
86
+ || column.name == 'type'
82
87
  end
83
88
 
84
89
  return inheritance_column.present?
@@ -21,6 +21,8 @@ module ForestLiana
21
21
  mattr_accessor :included_models
22
22
  mattr_accessor :user_class_name
23
23
  mattr_accessor :names_overriden
24
+ # TODO: Remove once lianas prior to 2.0.0 are not supported anymore.
25
+ mattr_accessor :names_old_overriden
24
26
 
25
27
  self.apimap = []
26
28
  self.allowed_users = []
@@ -30,14 +32,22 @@ module ForestLiana
30
32
  self.user_class_name = nil
31
33
  self.names_overriden = {}
32
34
 
35
+ # TODO: Remove once lianas prior to 2.0.0 are not supported anymore.
36
+ self.names_old_overriden = {}
37
+
33
38
  def self.schema_for_resource resource
34
39
  self.apimap.find do |collection|
35
40
  SchemaUtils.find_model_from_collection_name(collection.name)
36
- .try(:table_name) == resource.table_name
41
+ .try(:name) == resource.name
37
42
  end
38
43
  end
39
44
 
40
45
  def self.name_for(model)
41
- self.names_overriden[model] || model.try(:table_name)
46
+ self.names_overriden[model] || model.try(:name)
47
+ end
48
+
49
+ # TODO: Remove once lianas prior to 2.0.0 are not supported anymore.
50
+ def self.name_old_for(model)
51
+ self.names_old_overriden[model] || model.try(:table_name)
42
52
  end
43
53
  end
@@ -32,9 +32,15 @@ module ForestLiana
32
32
 
33
33
  private
34
34
 
35
+ def is_sti_parent_model?(model)
36
+ return false unless model.try(:table_exists?)
37
+
38
+ model.inheritance_column && model.columns.find { |column| column.name == model.inheritance_column }
39
+ end
40
+
35
41
  def analyze_model?(model)
36
42
  model && model.table_exists? && !SchemaUtils.habtm?(model) &&
37
- SchemaUtils.model_included?(model) && !SchemaUtils.sti_child?(model)
43
+ SchemaUtils.model_included?(model)
38
44
  end
39
45
 
40
46
  def fetch_models
@@ -46,6 +52,10 @@ module ForestLiana
46
52
  if model.abstract_class?
47
53
  model.descendants.each { |submodel| fetch_model(submodel) }
48
54
  else
55
+ if is_sti_parent_model?(model)
56
+ model.descendants.each { |submodel_sti| fetch_model(submodel_sti) }
57
+ end
58
+
49
59
  if analyze_model?(model)
50
60
  ForestLiana.models << model
51
61
  end
@@ -105,15 +115,18 @@ module ForestLiana
105
115
 
106
116
  def namespace_duplicated_models
107
117
  ForestLiana.models
108
- .group_by {|model| model.table_name}
109
- .select {|table_name, models| models.length > 1}
118
+ .group_by { |model| model.table_name }
119
+ .select { |table_name, models| models.length > 1 }
110
120
  .try(:each) do |table_name, models|
111
121
  models.each do |model|
112
- ForestLiana.names_overriden[model] =
122
+ unless model.name.deconstantize.blank?
123
+ ForestLiana.names_overriden[model] = model.name.gsub('::', '__')
124
+ end
125
+ # TODO: Remove once lianas prior to 2.0.0 are not supported anymore.
126
+ ForestLiana.names_old_overriden[model] =
113
127
  "#{model.name.deconstantize.downcase}__#{model.table_name}"
114
128
  end
115
129
  end
116
-
117
130
  end
118
131
 
119
132
  def create_apimap
@@ -149,7 +162,7 @@ module ForestLiana
149
162
  "Can you check on Forest that you copied it properly in the " \
150
163
  "forest_liana initializer?"
151
164
  else
152
- json = JSONAPI::Serializer.serialize(ForestLiana.apimap, {
165
+ apimap = JSONAPI::Serializer.serialize(ForestLiana.apimap, {
153
166
  is_collection: true,
154
167
  include: ['actions', 'segments'],
155
168
  meta: {
@@ -168,7 +181,7 @@ module ForestLiana
168
181
  http.use_ssl = true if forest_url.start_with?('https')
169
182
  http.start do |client|
170
183
  request = Net::HTTP::Post.new(uri.path)
171
- request.body = json.to_json
184
+ request.body = apimap.to_json
172
185
  request['Content-Type'] = 'application/json'
173
186
  request['forest-secret-key'] = ForestLiana.env_secret
174
187
  response = client.request(request)
@@ -206,10 +219,13 @@ module ForestLiana
206
219
 
207
220
  def setup_intercom_integration(collection_name)
208
221
  model_name = ForestLiana.name_for(collection_name.constantize)
222
+ # TODO: Remove once lianas prior to 2.0.0 are not supported anymore.
223
+ model_name_old = ForestLiana.name_old_for(collection_name.constantize)
209
224
  collection_display_name = collection_name.capitalize
210
225
 
211
226
  ForestLiana.apimap << ForestLiana::Model::Collection.new({
212
227
  name: "#{model_name}_intercom_conversations",
228
+ name_old: "#{model_name_old}_intercom_conversations",
213
229
  display_name: collection_display_name + ' Conversations',
214
230
  icon: 'intercom',
215
231
  integration: 'intercom',
@@ -227,6 +243,7 @@ module ForestLiana
227
243
 
228
244
  ForestLiana.apimap << ForestLiana::Model::Collection.new({
229
245
  name: "#{model_name}_intercom_attributes",
246
+ name_old: "#{model_name_old}_intercom_attributes",
230
247
  display_name: collection_display_name + ' Attributes',
231
248
  icon: 'intercom',
232
249
  integration: 'intercom',
@@ -270,10 +287,13 @@ module ForestLiana
270
287
  def setup_stripe_integration(collection_name_and_field)
271
288
  collection_name = collection_name_and_field.split('.')[0]
272
289
  model_name = ForestLiana.name_for(collection_name.constantize)
290
+ # TODO: Remove once lianas prior to 2.0.0 are not supported anymore.
291
+ model_name_old = ForestLiana.name_old_for(collection_name.constantize)
273
292
  collection_display_name = model_name.capitalize
274
293
 
275
294
  ForestLiana.apimap << ForestLiana::Model::Collection.new({
276
295
  name: "#{model_name}_stripe_payments",
296
+ name_old: "#{model_name_old}_stripe_payments",
277
297
  display_name: collection_display_name + ' Payments',
278
298
  icon: 'stripe',
279
299
  integration: 'stripe',
@@ -307,6 +327,7 @@ module ForestLiana
307
327
 
308
328
  ForestLiana.apimap << ForestLiana::Model::Collection.new({
309
329
  name: "#{model_name}_stripe_invoices",
330
+ name_old: "#{model_name_old}_stripe_invoices",
310
331
  display_name: collection_display_name + ' Invoices',
311
332
  icon: 'stripe',
312
333
  integration: 'stripe',
@@ -341,6 +362,7 @@ module ForestLiana
341
362
 
342
363
  ForestLiana.apimap << ForestLiana::Model::Collection.new({
343
364
  name: "#{model_name}_stripe_cards",
365
+ name_old: "#{model_name_old}_stripe_cards",
344
366
  display_name: collection_display_name + ' Cards',
345
367
  icon: 'stripe',
346
368
  integration: 'stripe',
@@ -376,6 +398,7 @@ module ForestLiana
376
398
 
377
399
  ForestLiana.apimap << ForestLiana::Model::Collection.new({
378
400
  name: "#{model_name}_stripe_subscriptions",
401
+ name_old: "#{model_name_old}_stripe_subscriptions",
379
402
  display_name: collection_display_name + ' Subscriptions',
380
403
  icon: 'stripe',
381
404
  integration: 'stripe',
@@ -409,6 +432,7 @@ module ForestLiana
409
432
 
410
433
  ForestLiana.apimap << ForestLiana::Model::Collection.new({
411
434
  name: "#{model_name}_stripe_bank_accounts",
435
+ name_old: "#{model_name_old}_stripe_bank_accounts",
412
436
  display_name: collection_display_name + ' Bank Accounts',
413
437
  icon: 'stripe',
414
438
  integration: 'stripe',