forest_liana 1.9.8 → 2.0.0

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: 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',