glue_gun_dsl 0.1.21 → 0.1.23

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
  SHA256:
3
- metadata.gz: 1757d5bf22062e71a309eb62fd4b55aa830d36a7e7cde695f8525b960d5a0a89
4
- data.tar.gz: 8f591ab19ba6b88118834b65aa210166408bc127afba0551bb2792505e7abc64
3
+ metadata.gz: e38dfcee3bde86f31b597d6dccf5138fb7200050a05904a055b7d8f201192ab0
4
+ data.tar.gz: 9b031f91fd59f57d8a10edef069d0ec656e04b8440d55af1354dda0cbfa124e4
5
5
  SHA512:
6
- metadata.gz: c25769bebf3f9e450970506b45fa13c82281d223f3da07f1d3e667597678903da636422c24924525456f1063b4d142722729fc9bb240eec9801a6d67a1a5fae9
7
- data.tar.gz: 13e57e0b3cc63e2ed15e26d480d0622e6413476dae3fff9ba8bf1686fc6fa4c314baad22452b157982cd10699cbb6f6574c84130168d83874d817aef0dbc98e9
6
+ metadata.gz: b25d5acc5cc955c9c3b20147c6bbf81c2911860f7e7f32b48b4f21273bf7c1f992f05c6b21ed2e6353b3ace8ac39023f87dcbd100fc9041731bea3a62b5bdf2b
7
+ data.tar.gz: 69736bb98acb9e1365879c0f68f7c401cc6b675e4c7c21af9fee87c0ea074dc76fc103413a386b5b76b1c8e44534f2c3e2f163ed2242389e14dc80fc7c02e923
@@ -12,7 +12,7 @@ module GlueGun
12
12
  value
13
13
  end
14
14
 
15
- result[key] = compacted unless compacted.blank?
15
+ result[key] = compacted unless compacted.is_a?(String) && compacted.blank?
16
16
  end
17
17
  end
18
18
  end
data/lib/glue_gun/dsl.rb CHANGED
@@ -1,8 +1,11 @@
1
+ require_relative "shared"
1
2
  module GlueGun
2
3
  module DSL
3
4
  extend ActiveSupport::Concern
4
5
 
5
6
  included do
7
+ include GlueGun::Shared
8
+
6
9
  unless ancestors.include?(ActiveRecord::Base)
7
10
  include ActiveModel::Model
8
11
  include ActiveModel::Attributes
@@ -77,6 +80,8 @@ module GlueGun
77
80
  end
78
81
 
79
82
  module ClassMethods
83
+ extend GlueGun::Shared
84
+
80
85
  DEFAULT_TYPE = if ActiveModel.version >= Gem::Version.new("7")
81
86
  nil
82
87
  elsif ActiveModel.version >= Gem::Version.new("5")
@@ -156,7 +161,7 @@ module GlueGun
156
161
  end
157
162
 
158
163
  def detect_root_dir
159
- base_path = Module.const_source_location(name)&.first || ""
164
+ base_path = Module.const_source_location(self.class.name)&.first || ""
160
165
  File.dirname(base_path)
161
166
  end
162
167
  end
@@ -165,11 +170,6 @@ module GlueGun
165
170
  @initialized == true
166
171
  end
167
172
 
168
- def detect_root_dir
169
- base_path = Module.const_source_location(self.class.name)&.first || ""
170
- File.dirname(base_path)
171
- end
172
-
173
173
  def initialize_dependencies(attributes)
174
174
  self.class.dependency_definitions.each do |component_type, definition|
175
175
  value = attributes[component_type] || self.class.hardcoded_dependencies[component_type]
@@ -438,8 +438,13 @@ module GlueGun
438
438
  def determine_option_name(init_args, instance)
439
439
  option_name = nil
440
440
 
441
- # Use when block if defined
442
- if when_block
441
+ user_specified_option = init_args.is_a?(Hash) && init_args.keys.size == 1
442
+ user_specified_valid_option = user_specified_option && option_configs.key?(init_args.keys.first)
443
+
444
+ if user_specified_valid_option
445
+ option_name = init_args.keys.first
446
+ init_args = init_args[option_name] # Extract the inner value
447
+ elsif when_block.present?
443
448
  result = instance.instance_exec(init_args, &when_block)
444
449
  if result.is_a?(Hash) && result[:option]
445
450
  option_name = result[:option]
@@ -448,24 +453,6 @@ module GlueGun
448
453
  end
449
454
  end
450
455
 
451
- # Detect option from user input
452
- if option_name.nil? && (init_args.is_a?(Hash) && init_args.keys.size == 1)
453
- if option_configs.key?(init_args.keys.first)
454
- option_name = init_args.keys.first
455
- init_args = init_args[option_name] # Extract the inner value
456
- else
457
- default_option = get_option(default_option_name)
458
- unless default_option.only?
459
- raise ArgumentError,
460
- "Unknown #{component_type} option: #{init_args.keys.first}."
461
- end
462
- unless default_option.attributes.keys.include?(init_args.keys.first)
463
- raise ArgumentError, "#{default_option.class_name} does not respond to #{init_args.keys.first}"
464
- end
465
- end
466
- end
467
-
468
- # Use default option if none determined
469
456
  option_name ||= default_option_name
470
457
 
471
458
  [option_name, init_args]
@@ -1,8 +1,11 @@
1
+ require_relative "shared"
1
2
  module GlueGun
2
3
  module Model
3
4
  extend ActiveSupport::Concern
4
5
 
5
6
  included do
7
+ include GlueGun::Shared
8
+
6
9
  before_save :serialize_service_object
7
10
  after_find :deserialize_service_object
8
11
 
@@ -24,30 +27,74 @@ module GlueGun
24
27
  raise ArgumentError, "You must provide a service class, factory, or a block to resolve the service class."
25
28
  end
26
29
  end
30
+
31
+ def find_or_create_by!(attributes)
32
+ attributes = attributes.deep_symbolize_keys
33
+ db_attributes = extract_db_attributes(attributes)
34
+ attributes.except(*db_attributes.keys)
35
+
36
+ record = where(db_attributes).first_or_initialize(attributes)
37
+
38
+ if record.new_record?
39
+ record.save!
40
+ else
41
+ record.send(:build_service_object, attributes)
42
+ end
43
+ yield record if block_given?
44
+
45
+ record
46
+ end
47
+
48
+ def find_or_create_by(attributes)
49
+ attributes = attributes.deep_symbolize_keys
50
+ db_attributes = extract_db_attributes(attributes)
51
+ attributes.except(*db_attributes.keys)
52
+
53
+ record = where(db_attributes).first_or_initialize(attributes)
54
+
55
+ if record.new_record?
56
+ record.save
57
+ else
58
+ record.send(:build_service_object, attributes)
59
+ end
60
+ yield record if block_given?
61
+
62
+ record
63
+ end
64
+
65
+ def extract_db_attributes(attributes)
66
+ # Extract attributes that correspond to database columns or associations
67
+ column_names = self.column_names.map(&:to_sym)
68
+ association_names = reflect_on_all_associations.map(&:name)
69
+
70
+ attributes.slice(*(column_names + association_names))
71
+ end
27
72
  end
28
73
 
29
74
  def initialize(attributes = {})
75
+ attributes[:root_dir] = detect_root_dir
30
76
  attributes = attributes.deep_symbolize_keys
31
- db_attributes = extract_db_attributes(attributes)
77
+ db_attributes = self.class.extract_db_attributes(attributes)
32
78
  super(db_attributes)
33
- self.class.send(:attr_reader, service_attribute_name)
34
79
  build_service_object(attributes)
35
80
  end
36
81
 
37
82
  private
38
83
 
39
- def extract_db_attributes(attributes)
40
- # Extract attributes that correspond to database columns or associations
41
- column_names = self.class.column_names.map(&:to_sym)
42
- association_names = self.class.reflect_on_all_associations.map(&:name)
43
-
44
- attributes.slice(*(column_names + association_names))
45
- end
46
-
47
84
  def build_service_object(attributes)
85
+ self.class.send(:attr_reader, service_attribute_name)
48
86
  service_class = resolve_service_class(attributes)
87
+ raise "Unable to find service class for #{self.class} given #{attributes}" unless service_class.present?
88
+
49
89
  service_attributes = extract_service_attributes(attributes, service_class)
50
- service_instance = service_class.new(service_attributes)
90
+ begin
91
+ service_instance = service_class.new(service_attributes)
92
+ rescue StandardError => e
93
+ ap %(Error building service object #{service_class}:)
94
+ ap e.message
95
+ ap e.backtrace
96
+ raise e
97
+ end
51
98
  instance_variable_set("@#{service_attribute_name}", service_instance)
52
99
  end
53
100
 
@@ -116,16 +163,36 @@ module GlueGun
116
163
  }
117
164
  end
118
165
  end
119
- json = attrs.merge(deps.deep_compact).deep_symbolize_keys
166
+ json = serializable!(attrs.merge(deps.deep_compact).deep_symbolize_keys)
120
167
  write_attribute(:configuration, json.to_json)
121
168
  end
122
169
 
170
+ def serializable!(json)
171
+ regular_args = json.slice(*allowed_names(json.keys))
172
+ assoc_names = self.class.reflect_on_all_associations.map(&:name)
173
+ found_associations = assoc_names & json.keys
174
+ found_associations.each do |association|
175
+ regular_args[association] = true
176
+ end
177
+ regular_args
178
+ end
179
+
180
+ def deserialize_associations(json)
181
+ assoc_names = self.class.reflect_on_all_associations.map(&:name)
182
+ found_associations = assoc_names & json.keys
183
+ found_associations.each do |association|
184
+ json[association] = send(association)
185
+ end
186
+ json
187
+ end
188
+
123
189
  def deserialize_service_object
124
190
  serialized_data = JSON.parse(read_attribute(:configuration) || "{}")
125
191
  serialized_data.deep_symbolize_keys!
126
192
  service_class = resolve_service_class(serialized_data)
193
+ serialized_data = deserialize_associations(serialized_data)
127
194
  serialized_data = service_class.deserialize(serialized_data) if service_class.respond_to?(:deserialize)
128
- service_instance = service_class.new(serialized_data)
195
+ service_instance = build_service_object(serialized_data)
129
196
  instance_variable_set("@#{service_attribute_name}", service_instance)
130
197
  end
131
198
 
@@ -134,23 +201,11 @@ module GlueGun
134
201
  [names.map(&:to_sym) - assoc_names.map(&:to_sym)].flatten
135
202
  end
136
203
 
137
- def serialize
138
- dataset_service.attributes
139
- write_attribute(:configuration, json.to_json)
140
- end
141
-
142
- def deserialize
143
- options = JSON.parse(read_attribute(:configuration))
144
- options.deep_symbolize_keys!
145
-
146
- build_dataset_service(options)
147
- end
148
-
149
- def method_missing(method_name, *args, &block)
204
+ def method_missing(method_name, *args, **kwargs, &block)
150
205
  service_object = instance_variable_get("@#{service_attribute_name}")
151
206
 
152
207
  if service_object && service_object.respond_to?(method_name)
153
- service_object.send(method_name, *args, &block)
208
+ service_object.send(method_name, *args, **kwargs, &block)
154
209
  else
155
210
  super
156
211
  end
@@ -0,0 +1,8 @@
1
+ module GlueGun
2
+ module Shared
3
+ def detect_root_dir
4
+ base_path = Module.const_source_location(self.class.name)&.first || ""
5
+ File.dirname(base_path)
6
+ end
7
+ end
8
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GlueGun
4
- VERSION = "0.1.21"
4
+ VERSION = "0.1.23"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: glue_gun_dsl
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.21
4
+ version: 0.1.23
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brett Shollenberger
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-10-22 00:00:00.000000000 Z
11
+ date: 2024-10-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -70,6 +70,20 @@ dependencies:
70
70
  - - "<"
71
71
  - !ruby/object:Gem::Version
72
72
  version: '8'
73
+ - !ruby/object:Gem::Dependency
74
+ name: awesome_print
75
+ requirement: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ type: :runtime
81
+ prerelease: false
82
+ version_requirements: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
73
87
  - !ruby/object:Gem::Dependency
74
88
  name: appraisal
75
89
  requirement: !ruby/object:Gem::Requirement
@@ -194,7 +208,7 @@ files:
194
208
  - lib/glue_gun/core_ext/hash_extensions.rb
195
209
  - lib/glue_gun/dsl.rb
196
210
  - lib/glue_gun/model.rb
197
- - lib/glue_gun/my_model.rb
211
+ - lib/glue_gun/shared.rb
198
212
  - lib/glue_gun/types.rb
199
213
  - lib/glue_gun/types/array_type.rb
200
214
  - lib/glue_gun/types/date_time_type.rb
@@ -1,73 +0,0 @@
1
- module EasyML
2
- class Dataset < ActiveRecord::Base
3
- before_save :serialize
4
- after_find :deserialize
5
-
6
- validates :name, presence: true
7
- belongs_to :datasource,
8
- foreign_key: :datasource_id,
9
- class_name: "EasyML::Datasource"
10
-
11
- def initialize(options = {})
12
- super(EasyML::DbOptions.parse(options, self))
13
- build_dataset_service(options)
14
- end
15
-
16
- attr_accessor :dataset_service
17
-
18
- private
19
-
20
- def build_dataset_service(options)
21
- options.deep_symbolize_keys!
22
- service_klass = EasyML::Data::Dataset
23
-
24
- allowed_attr_names = service_klass.dependency_definitions.keys.concat(
25
- service_klass.attribute_definitions.keys
26
- )
27
-
28
- allowed_attrs = options.slice(*allowed_attr_names)
29
- @dataset_service = service_klass.new(allowed_attrs)
30
- define_dataset_service_delegators(allowed_attr_names)
31
- end
32
-
33
- def define_dataset_service_delegators(attr_names)
34
- allowed_names(attr_names).each do |attr_name|
35
- define_singleton_method(attr_name) do
36
- dataset_service.send(attr_name)
37
- end
38
- end
39
- end
40
-
41
- def allowed_names(names)
42
- assoc_names = self.class.reflect_on_all_associations.map(&:name)
43
- [names.map(&:to_sym) - assoc_names.map(&:to_sym)].flatten
44
- end
45
-
46
- def serialize
47
- attrs = dataset_service.attributes
48
- deps = allowed_names(dataset_service.dependency_definitions.keys).inject({}) do |hash, dep|
49
- hash.tap do
50
- this_dep = dataset_service.send(dep)
51
- next unless this_dep.present?
52
-
53
- opts = dataset_service.dependency_definitions[dep].option_configs
54
- selected_option = opts.detect do |_k, v|
55
- this_dep.class == v.class_name
56
- end.first
57
- hash[dep] = {
58
- selected_option => dataset_service.send(dep).attributes
59
- }
60
- end
61
- end
62
- json = attrs.merge(deps).deep_symbolize_keys.deep_compact
63
- write_attribute(:configuration, json.to_json)
64
- end
65
-
66
- def deserialize
67
- options = JSON.parse(read_attribute(:configuration))
68
- options.deep_symbolize_keys!
69
-
70
- build_dataset_service(options)
71
- end
72
- end
73
- end