rubypitaya 2.17.0 → 2.18.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
  SHA256:
3
- metadata.gz: 90b11b45f712986bf00e347425a7f4f237fd540ba4ab74c6cdb87b5a0fe795d2
4
- data.tar.gz: 58ab166182fe804946ac6f42a25f16ca1902ce969112b12ee716083226d4b7cb
3
+ metadata.gz: 38d15208a32190c01690735d3d8433bb0f8cc9b6f71a64f7897ba668c21e4e97
4
+ data.tar.gz: 7396c21b202d611ea5945fd9838b68323b4751777d3e154b20b31557ee470b7a
5
5
  SHA512:
6
- metadata.gz: c06fc55a0ec2749b56658aa3ab579329393e341d789a764966361877c04d46bcd1b48ca2677c8f692115f3f67913b74787264950c80ea3604c60354831d29186
7
- data.tar.gz: e5cbfa9e030ecfa0a41bbdd2604f559fd7d8370eae633d13f05857b9f5bcc556b0b9168a232b1a4f329ebad2596dfd46c6d336250832ff75514b688d11f4033c
6
+ metadata.gz: 6b70755f160f42aa9a145bf55c0709bb82ec92f1f2105874127439bdc286ea124e7f2093cdae34a377d595bb54e21e75af244d34cbd9c30f8feac08849db7d9a
7
+ data.tar.gz: 50df16ee2575fd5840b0af30cfa3aedb9a7e4b35d27291a3a484ac2233b09b41700618ef9a1d8b2223cc1dba3e0cc0d8c7fc42a168971e548bd0301e34b77e7d
@@ -1,6 +1,6 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- gem 'rubypitaya', '2.17.0'
3
+ gem 'rubypitaya', '2.18.0'
4
4
 
5
5
  group :development do
6
6
  gem 'pry', '0.14.0'
@@ -1,21 +1,3 @@
1
- GIT
2
- remote: https://gitlab.com/LucianoPC/ruby-pitaya
3
- revision: 9c28f2a16f3140d24f019164a254155f524f2593
4
- branch: ruby2.7.2
5
- specs:
6
- rubypitaya (2.17.0)
7
- activerecord (= 6.1.3)
8
- etcdv3 (= 0.10.2)
9
- eventmachine (= 1.2.7)
10
- nats (= 0.11.0)
11
- ostruct (= 0.3.3)
12
- pg (= 1.2.3)
13
- protobuf (= 3.10.0)
14
- rake (= 13.0.3)
15
- redis (= 4.2.5)
16
- sinatra (= 2.1.0)
17
- sinatra-contrib (= 2.1.0)
18
-
19
1
  GEM
20
2
  remote: https://rubygems.org/
21
3
  specs:
@@ -69,10 +51,10 @@ GEM
69
51
  grpc (~> 1.17)
70
52
  eventmachine (1.2.7)
71
53
  ffi (1.14.2)
72
- google-protobuf (3.15.3)
54
+ google-protobuf (3.15.3-x86_64-linux)
73
55
  googleapis-common-protos-types (1.0.6)
74
56
  google-protobuf (~> 3.14)
75
- grpc (1.36.0)
57
+ grpc (1.36.0-x86_64-linux)
76
58
  google-protobuf (~> 3.14)
77
59
  googleapis-common-protos-types (~> 1.0)
78
60
  i18n (1.8.9)
@@ -126,6 +108,18 @@ GEM
126
108
  rspec-support (~> 3.10.0)
127
109
  rspec-support (3.10.2)
128
110
  ruby2_keywords (0.0.4)
111
+ rubypitaya (2.18.0)
112
+ activerecord (= 6.1.3)
113
+ etcdv3 (= 0.10.2)
114
+ eventmachine (= 1.2.7)
115
+ nats (= 0.11.0)
116
+ ostruct (= 0.3.3)
117
+ pg (= 1.2.3)
118
+ protobuf (= 3.10.0)
119
+ rake (= 13.0.3)
120
+ redis (= 4.2.5)
121
+ sinatra (= 2.1.0)
122
+ sinatra-contrib (= 2.1.0)
129
123
  sinatra (2.1.0)
130
124
  mustermann (~> 1.0)
131
125
  rack (~> 2.2)
@@ -155,7 +149,7 @@ DEPENDENCIES
155
149
  listen (= 3.4.1)
156
150
  pry (= 0.14.0)
157
151
  rspec (= 3.10.0)
158
- rubypitaya!
152
+ rubypitaya (= 2.18.0)
159
153
 
160
154
  BUNDLED WITH
161
155
  2.1.4
@@ -1,11 +1,11 @@
1
1
  class PlayerBLL
2
2
 
3
3
  def create_new_player(setup, config)
4
- name = config['initial_player']['name']
4
+ name = config['initial_player'][:name]
5
5
  gold = setup['initial_player.wallet.gold']
6
6
 
7
7
  player = Player.new(name: name, gold: gold, user: User.new)
8
- player.save
8
+ player.save!
9
9
  player
10
10
  end
11
11
  end
@@ -17,7 +17,7 @@ class PlayerHandler < RubyPitaya::HandlerBase
17
17
  # Given you have the following file "app/config/initial_player.json"
18
18
  # And this json content is {'name': 'Guest'}
19
19
  # And you can get the initial player name
20
- # Then you can run the following code: @config['initial_player']['name']
20
+ # Then you can run the following code: @config['initial_player'][:name]
21
21
  #
22
22
  # - @params
23
23
  # - info: Special hash with the request parameters
@@ -1,18 +1,21 @@
1
1
  FROM ruby:2.7.2
2
2
 
3
- RUN apt update
4
- RUN apt install -y git vim postgresql-client docker.io --no-install-recommends
3
+ ENV LANG=C.UTF-8
4
+ ENV LC_ALL=C.UTF-8
5
5
 
6
- WORKDIR /app/rubypitaya/
6
+ RUN apt update && \
7
+ apt install -y --no-install-recommends \
8
+ docker.io \
9
+ postgresql-client \
10
+ && rm -rf /var/lib/apt/lists/*
7
11
 
8
12
  COPY Gemfile Gemfile.lock ./
9
13
 
10
14
  RUN bundle install
11
15
 
12
- COPY . .
16
+ WORKDIR /app/rubypitaya/
13
17
 
14
- ENV LANG=C.UTF-8
15
- ENV LC_ALL=C.UTF-8
18
+ COPY . .
16
19
 
17
20
  ENTRYPOINT ["./docker/entrypoint.sh"]
18
21
 
@@ -1,36 +1,35 @@
1
1
  FROM ruby:2.7.2 as builder
2
2
 
3
- WORKDIR /app/rubypitaya/
3
+ RUN apt update && \
4
+ apt install -y --no-install-recommends \
5
+ curl \
6
+ && rm -rf /var/lib/apt/lists/*
4
7
 
5
8
  COPY Gemfile Gemfile.lock ./
6
9
 
7
- ENV BUNDLER_WITHOUT development test
8
- RUN bundle install
10
+ RUN bundle config --local without "development test" && \
11
+ bundle install
9
12
 
10
- COPY . .
13
+ RUN curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl
11
14
 
12
15
  FROM ruby:2.7.2-slim
13
16
 
14
- RUN apt update && apt install -y postgresql-client curl python3 bash vim --no-install-recommends
15
- RUN rm -rf /var/lib/apt/lists/*
17
+ ENV LANG=C.UTF-8
18
+ ENV LC_ALL=C.UTF-8
16
19
 
17
- RUN curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl
18
- RUN chmod +x ./kubectl
19
- RUN mv ./kubectl /usr/local/bin
20
+ RUN apt update && \
21
+ apt install -y --no-install-recommends \
22
+ postgresql-client \
23
+ && rm -rf /var/lib/apt/lists/*
20
24
 
21
- COPY --from=builder /usr/local/etc /usr/local/etc
22
25
  COPY --from=builder /usr/local/bundle /usr/local/bundle
23
- COPY --from=builder /usr/local/bin/ruby /usr/local/bin/ruby
24
- COPY --from=builder /usr/local/lib/ruby/gems/2.7.0 /usr/local/lib/ruby/gems/2.7.0
25
-
26
- COPY --from=builder /app/rubypitaya /app/rubypitaya
26
+ COPY --from=builder /kubectl /usr/local/bin/kubectl
27
+
28
+ RUN chmod +x /usr/local/bin/kubectl
27
29
 
28
30
  WORKDIR /app/rubypitaya/
29
31
 
30
- RUN rm -rf vendor/
31
-
32
- ENV LANG=C.UTF-8
33
- ENV LC_ALL=C.UTF-8
32
+ COPY . .
34
33
 
35
34
  ENTRYPOINT ["./docker/entrypoint.sh"]
36
35
 
@@ -4,11 +4,10 @@ module RubyPitaya
4
4
 
5
5
  class Config
6
6
 
7
- attr_writer :config_core_override
8
-
9
7
  def initialize
10
8
  @config_core = ConfigCore.new
11
9
  @config_core_override = nil
10
+ @has_config_core_override = false
12
11
 
13
12
  @result_cache = {}
14
13
  end
@@ -17,10 +16,13 @@ module RubyPitaya
17
16
  result = @result_cache[key]
18
17
  return result unless result.nil?
19
18
 
20
- result = @config_core_override[key] unless @config_core_override.nil?
21
- result = @config_core[key] if result.nil?
19
+ if @has_config_core_override
20
+ result = @config_core_override[key]
21
+ else
22
+ result = @config_core[key]
23
+ end
22
24
 
23
- @result_cache[key] = result
25
+ @result_cache[key] = result.deep_symbolize_keys
24
26
 
25
27
  result
26
28
  end
@@ -33,5 +35,10 @@ module RubyPitaya
33
35
  def clear_cache
34
36
  @result_cache.clear
35
37
  end
38
+
39
+ def config_core_override=(value)
40
+ @config_core_override = value
41
+ @has_config_core_override = !value.nil?
42
+ end
36
43
  end
37
44
  end
@@ -17,8 +17,7 @@ module RubyPitaya
17
17
  end
18
18
 
19
19
  def [](key)
20
- split_key = key.split('/')
21
- @config.dig(*split_key)
20
+ @config[key]
22
21
  end
23
22
 
24
23
  def auto_reload
@@ -42,12 +41,11 @@ module RubyPitaya
42
41
 
43
42
  def load_config_file(configs_folder_path, file_path)
44
43
  config_text = File.open(file_path, &:read)
45
- config_hash = JSON.parse(config_text)
44
+ config_hash = JSON.parse(config_text, symbolize_names: true)
46
45
 
47
- path_array = file_path.sub(/^#{configs_folder_path}/, '')[0..-6]
48
- .split('/')
46
+ file_name = file_path.sub(/^#{configs_folder_path}/, '')[0..-6]
49
47
 
50
- set_config_value(path_array, config_hash)
48
+ @config[file_name] = config_hash
51
49
 
52
50
  rescue Exception => error
53
51
  puts "ERROR: #{error}"
@@ -69,20 +67,5 @@ module RubyPitaya
69
67
  puts "MODIFIED @config: #{path}"
70
68
  end
71
69
  end
72
-
73
- def set_config_value(keys, value)
74
- config = @config
75
-
76
- keys.each_with_index do |key, index|
77
- is_last_index = index == keys.size - 1
78
-
79
- if is_last_index
80
- config[key] = value
81
- else
82
- config[key] = {} unless config.key?(key)
83
- config = config[key]
84
- end
85
- end
86
- end
87
70
  end
88
71
  end
@@ -144,7 +144,7 @@ module RubyPitaya
144
144
  start_time_seconds = Time.now.to_f
145
145
 
146
146
  message_route = request[:msg][:route]
147
- message_data = request[:msg][:data]
147
+ message_data = request[:msg][:data] || {}
148
148
  message_data = JSON.parse(message_data) if message_data.class == String
149
149
 
150
150
  params = Parameters.new(message_data)
@@ -1,4 +1,5 @@
1
1
  require 'date'
2
+ require 'yaml'
2
3
  require 'bigdecimal'
3
4
  require 'stringio'
4
5
 
@@ -9,12 +10,36 @@ require 'active_support/core_ext/array/wrap'
9
10
  module RubyPitaya
10
11
 
11
12
  class ParameterMissing < IndexError
12
- attr_reader :param
13
+ attr_reader :param, :keys
13
14
 
14
- def initialize(param)
15
+ def initialize(param, keys = nil)
15
16
  @param = param
17
+ @keys = keys
16
18
  super("param is missing or the value is empty: #{param}")
17
19
  end
20
+
21
+ class Correction
22
+ def initialize(error)
23
+ @error = error
24
+ end
25
+
26
+ def corrections
27
+ if @error.param && @error.keys
28
+ maybe_these = @error.keys
29
+
30
+ maybe_these.sort_by { |n|
31
+ DidYouMean::Jaro.distance(@error.param.to_s, n)
32
+ }.reverse.first(4)
33
+ else
34
+ []
35
+ end
36
+ end
37
+ end
38
+
39
+ # We may not have DYM, and DYM might not let us register error handlers
40
+ if defined?(DidYouMean) && DidYouMean.respond_to?(:correct_error)
41
+ DidYouMean.correct_error(self, Correction)
42
+ end
18
43
  end
19
44
 
20
45
  class UnpermittedParameters < IndexError
@@ -26,26 +51,98 @@ module RubyPitaya
26
51
  end
27
52
  end
28
53
 
29
- class Parameters < ActiveSupport::HashWithIndifferentAccess
30
- attr_accessor :permitted
31
- alias :permitted? :permitted
54
+ class UnfilteredParameters < ArgumentError
55
+ def initialize # :nodoc:
56
+ super("unable to convert unpermitted parameters to hash")
57
+ end
58
+ end
59
+
60
+ class Parameters
61
+ cattr_accessor :permit_all_parameters, instance_accessor: false, default: false
62
+ cattr_accessor :action_on_unpermitted_parameters, instance_accessor: false
63
+
64
+ delegate :keys, :key?, :has_key?, :member?, :values, :has_value?, :value?, :empty?, :include?,
65
+ :as_json, :to_s, :each_key, to: :@parameters
66
+
67
+ cattr_accessor :always_permitted_parameters, default: %w( controller action )
68
+
69
+ class << self
70
+ def nested_attribute?(key, value) # :nodoc:
71
+ /\A-?\d+\z/.match?(key) && (value.is_a?(Hash) || value.is_a?(Parameters))
72
+ end
73
+ end
32
74
 
33
- cattr_accessor :action_on_unpermitted_parameters, :instance_accessor => false
75
+ def initialize(parameters = {})
76
+ @parameters = parameters.with_indifferent_access
77
+ @permitted = self.class.permit_all_parameters
78
+ end
34
79
 
35
- # Never raise an UnpermittedParameters exception because of these params
36
- # are present. They are added by Rails and it's of no concern.
37
- NEVER_UNPERMITTED_PARAMS = %w( controller action )
80
+ def ==(other)
81
+ if other.respond_to?(:permitted?)
82
+ permitted? == other.permitted? && parameters == other.parameters
83
+ else
84
+ @parameters == other
85
+ end
86
+ end
87
+ alias eql? ==
38
88
 
39
- def initialize(attributes = nil)
40
- super(attributes)
41
- @permitted = false
89
+ def hash
90
+ [@parameters.hash, @permitted].hash
91
+ end
92
+
93
+ def to_h
94
+ if permitted?
95
+ convert_parameters_to_hashes(@parameters, :to_h)
96
+ else
97
+ raise UnfilteredParameters
98
+ end
99
+ end
100
+
101
+ def to_hash
102
+ to_h.to_hash
103
+ end
104
+
105
+ def to_query(*args)
106
+ to_h.to_query(*args)
107
+ end
108
+ alias_method :to_param, :to_query
109
+
110
+ def to_unsafe_h
111
+ convert_parameters_to_hashes(@parameters, :to_unsafe_h)
112
+ end
113
+ alias_method :to_unsafe_hash, :to_unsafe_h
114
+
115
+ def each_pair(&block)
116
+ return to_enum(__callee__) unless block_given?
117
+ @parameters.each_pair do |key, value|
118
+ yield [key, convert_hashes_to_parameters(key, value)]
119
+ end
120
+
121
+ self
122
+ end
123
+ alias_method :each, :each_pair
124
+
125
+ def each_value(&block)
126
+ return to_enum(:each_value) unless block_given?
127
+ @parameters.each_pair do |key, value|
128
+ yield convert_hashes_to_parameters(key, value)
129
+ end
130
+
131
+ self
132
+ end
133
+
134
+ def converted_arrays
135
+ @converted_arrays ||= Set.new
136
+ end
137
+
138
+ def permitted?
139
+ @permitted
42
140
  end
43
141
 
44
142
  def permit!
45
143
  each_pair do |key, value|
46
- value = convert_hashes_to_parameters(key, value)
47
- Array.wrap(value).each do |_|
48
- _.permit! if _.respond_to? :permit!
144
+ Array.wrap(value).flatten.each do |v|
145
+ v.permit! if v.respond_to? :permit!
49
146
  end
50
147
  end
51
148
 
@@ -54,7 +151,13 @@ module RubyPitaya
54
151
  end
55
152
 
56
153
  def require(key)
57
- self[key].presence || raise(ParameterMissing.new(key))
154
+ return key.map { |k| require(k) } if key.is_a?(Array)
155
+ value = self[key]
156
+ if value.present? || value == false
157
+ value
158
+ else
159
+ raise ParameterMissing.new(key, @parameters.keys)
160
+ end
58
161
  end
59
162
 
60
163
  alias :required :require
@@ -66,7 +169,7 @@ module RubyPitaya
66
169
  case filter
67
170
  when Symbol, String
68
171
  permitted_scalar_filter(params, filter)
69
- when Hash then
172
+ when Hash
70
173
  hash_filter(params, filter)
71
174
  end
72
175
  end
@@ -77,169 +180,377 @@ module RubyPitaya
77
180
  end
78
181
 
79
182
  def [](key)
80
- convert_hashes_to_parameters(key, super)
183
+ convert_hashes_to_parameters(key, @parameters[key])
184
+ end
185
+
186
+ def []=(key, value)
187
+ @parameters[key] = value
81
188
  end
82
189
 
83
190
  def fetch(key, *args)
84
- convert_hashes_to_parameters(key, super, false)
85
- rescue KeyError, IndexError
86
- raise ParameterMissing.new(key)
191
+ convert_value_to_parameters(
192
+ @parameters.fetch(key) {
193
+ if block_given?
194
+ yield
195
+ else
196
+ args.fetch(0) { raise ActionController::ParameterMissing.new(key, @parameters.keys) }
197
+ end
198
+ }
199
+ )
200
+ end
201
+
202
+ def dig(*keys)
203
+ convert_hashes_to_parameters(keys.first, @parameters[keys.first])
204
+ @parameters.dig(*keys)
205
+ end
206
+
207
+ def slice!(*keys)
208
+ @parameters.slice!(*keys)
209
+ self
210
+ end
211
+
212
+ def except(*keys)
213
+ new_instance_with_inherited_permitted_status(@parameters.except(*keys))
214
+ end
215
+
216
+ def extract!(*keys)
217
+ new_instance_with_inherited_permitted_status(@parameters.extract!(*keys))
218
+ end
219
+
220
+ def transform_values
221
+ return to_enum(:transform_values) unless block_given?
222
+ new_instance_with_inherited_permitted_status(
223
+ @parameters.transform_values { |v| yield convert_value_to_parameters(v) }
224
+ )
225
+ end
226
+
227
+ def transform_values!
228
+ return to_enum(:transform_values!) unless block_given?
229
+ @parameters.transform_values! { |v| yield convert_value_to_parameters(v) }
230
+ self
231
+ end
232
+
233
+ def transform_keys(&block)
234
+ return to_enum(:transform_keys) unless block_given?
235
+ new_instance_with_inherited_permitted_status(
236
+ @parameters.transform_keys(&block)
237
+ )
238
+ end
239
+
240
+ def transform_keys!(&block)
241
+ return to_enum(:transform_keys!) unless block_given?
242
+ @parameters.transform_keys!(&block)
243
+ self
244
+ end
245
+
246
+ def deep_transform_keys(&block)
247
+ new_instance_with_inherited_permitted_status(
248
+ @parameters.deep_transform_keys(&block)
249
+ )
250
+ end
251
+
252
+ def deep_transform_keys!(&block)
253
+ @parameters.deep_transform_keys!(&block)
254
+ self
255
+ end
256
+
257
+ def delete(key, &block)
258
+ convert_value_to_parameters(@parameters.delete(key, &block))
259
+ end
260
+
261
+ def select(&block)
262
+ new_instance_with_inherited_permitted_status(@parameters.select(&block))
87
263
  end
88
264
 
89
- def slice(*keys)
90
- self.class.new(super).tap do |new_instance|
91
- new_instance.instance_variable_set :@permitted, @permitted
265
+ def select!(&block)
266
+ @parameters.select!(&block)
267
+ self
268
+ end
269
+ alias_method :keep_if, :select!
270
+
271
+ def reject(&block)
272
+ new_instance_with_inherited_permitted_status(@parameters.reject(&block))
273
+ end
274
+
275
+ def reject!(&block)
276
+ @parameters.reject!(&block)
277
+ self
278
+ end
279
+ alias_method :delete_if, :reject!
280
+
281
+ def compact
282
+ new_instance_with_inherited_permitted_status(@parameters.compact)
283
+ end
284
+
285
+ def compact!
286
+ self if @parameters.compact!
287
+ end
288
+
289
+ def compact_blank
290
+ reject { |_k, v| v.blank? }
291
+ end
292
+
293
+ def compact_blank!
294
+ reject! { |_k, v| v.blank? }
295
+ end
296
+
297
+ def values_at(*keys)
298
+ convert_value_to_parameters(@parameters.values_at(*keys))
299
+ end
300
+
301
+ def merge(other_hash)
302
+ new_instance_with_inherited_permitted_status(
303
+ @parameters.merge(other_hash.to_h)
304
+ )
305
+ end
306
+
307
+ def merge!(other_hash)
308
+ @parameters.merge!(other_hash.to_h)
309
+ self
310
+ end
311
+
312
+ def reverse_merge(other_hash)
313
+ new_instance_with_inherited_permitted_status(
314
+ other_hash.to_h.merge(@parameters)
315
+ )
316
+ end
317
+ alias_method :with_defaults, :reverse_merge
318
+
319
+ def reverse_merge!(other_hash)
320
+ @parameters.merge!(other_hash.to_h) { |key, left, right| left }
321
+ self
322
+ end
323
+ alias_method :with_defaults!, :reverse_merge!
324
+
325
+ def stringify_keys
326
+ dup
327
+ end
328
+
329
+ def inspect
330
+ "#<#{self.class} #{@parameters} permitted: #{@permitted}>"
331
+ end
332
+
333
+ def self.hook_into_yaml_loading
334
+ YAML.load_tags["!ruby/hash-with-ivars:ActionController::Parameters"] = name
335
+ YAML.load_tags["!ruby/hash:ActionController::Parameters"] = name
336
+ end
337
+ hook_into_yaml_loading
338
+
339
+ def init_with(coder)
340
+ case coder.tag
341
+ when "!ruby/hash:ActionController::Parameters"
342
+ @parameters = coder.map.with_indifferent_access
343
+ @permitted = false
344
+ when "!ruby/hash-with-ivars:ActionController::Parameters"
345
+ @parameters = coder.map["elements"].with_indifferent_access
346
+ @permitted = coder.map["ivars"][:@permitted]
347
+ when "!ruby/object:ActionController::Parameters"
348
+ @parameters, @permitted = coder.map["parameters"], coder.map["permitted"]
92
349
  end
93
350
  end
94
351
 
95
- def dup
96
- self.class.new(self).tap do |duplicate|
97
- duplicate.default = default
98
- duplicate.instance_variable_set :@permitted, @permitted
352
+ def deep_dup
353
+ self.class.new(@parameters.deep_dup).tap do |duplicate|
354
+ duplicate.permitted = @permitted
99
355
  end
100
356
  end
101
357
 
102
358
  protected
103
- def convert_value(value, conversion = nil)
104
- if value.class == Hash
105
- Parameters.new(value)
106
- elsif value.is_a?(Array)
107
- value.dup.replace(value.map { |e| convert_value(e) })
108
- else
109
- value
110
- end
111
- end
359
+
360
+ attr_reader :parameters
361
+
362
+ attr_writer :permitted
363
+
364
+ def nested_attributes?
365
+ @parameters.any? { |k, v| Parameters.nested_attribute?(k, v) }
366
+ end
367
+
368
+ def each_nested_attribute
369
+ hash = self.class.new
370
+ self.each { |k, v| hash[k] = yield v if Parameters.nested_attribute?(k, v) }
371
+ hash
372
+ end
112
373
 
113
374
  private
114
375
 
115
- def convert_hashes_to_parameters(key, value, assign_if_converted=true)
116
- converted = convert_value_to_parameters(value)
117
- self[key] = converted if assign_if_converted && !converted.equal?(value)
376
+ def new_instance_with_inherited_permitted_status(hash)
377
+ self.class.new(hash).tap do |new_instance|
378
+ new_instance.permitted = @permitted
379
+ end
380
+ end
381
+
382
+ def convert_parameters_to_hashes(value, using)
383
+ case value
384
+ when Array
385
+ value.map { |v| convert_parameters_to_hashes(v, using) }
386
+ when Hash
387
+ value.transform_values do |v|
388
+ convert_parameters_to_hashes(v, using)
389
+ end.with_indifferent_access
390
+ when Parameters
391
+ value.send(using)
392
+ else
393
+ value
394
+ end
395
+ end
396
+
397
+ def convert_hashes_to_parameters(key, value)
398
+ converted = convert_value_to_parameters(value)
399
+ @parameters[key] = converted unless converted.equal?(value)
400
+ converted
401
+ end
402
+
403
+ def convert_value_to_parameters(value)
404
+ case value
405
+ when Array
406
+ return value if converted_arrays.member?(value)
407
+ converted = value.map { |_| convert_value_to_parameters(_) }
408
+ converted_arrays << converted
118
409
  converted
410
+ when Hash
411
+ self.class.new(value)
412
+ else
413
+ value
119
414
  end
415
+ end
120
416
 
121
- def convert_value_to_parameters(value)
122
- if value.is_a?(Array)
123
- value.map { |_| convert_value_to_parameters(_) }
124
- elsif value.is_a?(Parameters) || !value.is_a?(Hash)
125
- value
417
+ def each_element(object, &block)
418
+ case object
419
+ when Array
420
+ object.grep(Parameters).map { |el| yield el }.compact
421
+ when Parameters
422
+ if object.nested_attributes?
423
+ object.each_nested_attribute(&block)
126
424
  else
127
- self.class.new(value)
425
+ yield object
128
426
  end
129
427
  end
428
+ end
130
429
 
131
- #
132
- # --- Filtering ----------------------------------------------------------
133
- #
134
-
135
- # This is a white list of permitted scalar types that includes the ones
136
- # supported in XML and JSON requests.
137
- #
138
- # This list is in particular used to filter ordinary requests, String goes
139
- # as first element to quickly short-circuit the common case.
140
- #
141
- # If you modify this collection please update the README.
142
- PERMITTED_SCALAR_TYPES = [
143
- String,
144
- Symbol,
145
- NilClass,
146
- Numeric,
147
- TrueClass,
148
- FalseClass,
149
- Date,
150
- Time,
151
- # DateTimes are Dates, we document the type but avoid the redundant check.
152
- StringIO,
153
- IO,
154
- ]
155
-
156
- def permitted_scalar?(value)
157
- PERMITTED_SCALAR_TYPES.any? {|type| value.is_a?(type)}
158
- end
159
-
160
- def array_of_permitted_scalars?(value)
161
- if value.is_a?(Array)
162
- value.all? {|element| permitted_scalar?(element)}
430
+ def unpermitted_parameters!(params)
431
+ unpermitted_keys = unpermitted_keys(params)
432
+ if unpermitted_keys.any?
433
+ case self.class.action_on_unpermitted_parameters
434
+ when :log
435
+ name = "unpermitted_parameters.action_controller"
436
+ ActiveSupport::Notifications.instrument(name, keys: unpermitted_keys)
437
+ when :raise
438
+ raise ActionController::UnpermittedParameters.new(unpermitted_keys)
163
439
  end
164
440
  end
441
+ end
165
442
 
166
- def permitted_scalar_filter(params, key)
167
- if has_key?(key) && permitted_scalar?(self[key])
168
- params[key] = self[key]
169
- end
443
+ def unpermitted_keys(params)
444
+ keys - params.keys - always_permitted_parameters
445
+ end
170
446
 
171
- keys.grep(/\A#{Regexp.escape(key.to_s)}\(\d+[if]?\)\z/).each do |key|
172
- if permitted_scalar?(self[key])
173
- params[key] = self[key]
174
- end
175
- end
447
+ PERMITTED_SCALAR_TYPES = [
448
+ String,
449
+ Symbol,
450
+ NilClass,
451
+ Numeric,
452
+ TrueClass,
453
+ FalseClass,
454
+ Date,
455
+ Time,
456
+ # DateTimes are Dates, we document the type but avoid the redundant check.
457
+ StringIO,
458
+ IO,
459
+ ]
460
+
461
+ def permitted_scalar?(value)
462
+ PERMITTED_SCALAR_TYPES.any? { |type| value.is_a?(type) }
463
+ end
464
+
465
+ def permitted_scalar_filter(params, permitted_key)
466
+ permitted_key = permitted_key.to_s
467
+
468
+ if has_key?(permitted_key) && permitted_scalar?(self[permitted_key])
469
+ params[permitted_key] = self[permitted_key]
176
470
  end
177
471
 
178
- def array_of_permitted_scalars_filter(params, key, hash = self)
179
- if hash.has_key?(key) && array_of_permitted_scalars?(hash[key])
180
- params[key] = hash[key]
181
- end
472
+ each_key do |key|
473
+ next unless key =~ /\(\d+[if]?\)\z/
474
+ next unless $~.pre_match == permitted_key
475
+
476
+ params[key] = self[key] if permitted_scalar?(self[key])
477
+ end
478
+ end
479
+
480
+ def array_of_permitted_scalars?(value)
481
+ if value.is_a?(Array) && value.all? { |element| permitted_scalar?(element) }
482
+ yield value
182
483
  end
484
+ end
183
485
 
184
- def hash_filter(params, filter)
185
- filter = filter.with_indifferent_access
486
+ def non_scalar?(value)
487
+ value.is_a?(Array) || value.is_a?(Parameters)
488
+ end
186
489
 
187
- # Slicing filters out non-declared keys.
188
- slice(*filter.keys).each do |key, value|
189
- next unless value
490
+ EMPTY_ARRAY = []
491
+ EMPTY_HASH = {}
492
+ def hash_filter(params, filter)
493
+ filter = filter.with_indifferent_access
190
494
 
191
- if filter[key] == []
192
- # Declaration {:comment_ids => []}.
193
- array_of_permitted_scalars_filter(params, key)
194
- else
195
- # Declaration {:user => :name} or {:user => [:name, :age, {:adress => ...}]}.
196
- params[key] = each_element(value) do |element, index|
197
- if element.is_a?(Hash)
198
- element = self.class.new(element) unless element.respond_to?(:permit)
199
- element.permit(*Array.wrap(filter[key]))
200
- elsif filter[key].is_a?(Hash) && filter[key][index] == []
201
- array_of_permitted_scalars_filter(params, index, value)
202
- end
203
- end
495
+ # Slicing filters out non-declared keys.
496
+ slice(*filter.keys).each do |key, value|
497
+ next unless value
498
+ next unless has_key? key
499
+
500
+ if filter[key] == EMPTY_ARRAY
501
+ # Declaration { comment_ids: [] }.
502
+ array_of_permitted_scalars?(self[key]) do |val|
503
+ params[key] = val
504
+ end
505
+ elsif filter[key] == EMPTY_HASH
506
+ # Declaration { preferences: {} }.
507
+ if value.is_a?(Parameters)
508
+ params[key] = permit_any_in_parameters(value)
509
+ end
510
+ elsif non_scalar?(value)
511
+ # Declaration { user: :name } or { user: [:name, :age, { address: ... }] }.
512
+ params[key] = each_element(value) do |element|
513
+ element.permit(*Array.wrap(filter[key]))
204
514
  end
205
515
  end
206
516
  end
517
+ end
207
518
 
208
- def each_element(value)
209
- if value.is_a?(Array)
210
- value.map { |el| yield el }.compact
211
- # fields_for on an array of records uses numeric hash keys.
212
- elsif fields_for_style?(value)
213
- hash = value.class.new
214
- value.each { |k,v| hash[k] = yield(v, k) }
215
- hash
216
- else
217
- yield value
519
+ def permit_any_in_parameters(params)
520
+ self.class.new.tap do |sanitized|
521
+ params.each do |key, value|
522
+ case value
523
+ when ->(v) { permitted_scalar?(v) }
524
+ sanitized[key] = value
525
+ when Array
526
+ sanitized[key] = permit_any_in_array(value)
527
+ when Parameters
528
+ sanitized[key] = permit_any_in_parameters(value)
529
+ else
530
+ # Filter this one out.
531
+ end
218
532
  end
219
533
  end
534
+ end
220
535
 
221
- def fields_for_style?(object)
222
- object.is_a?(Hash) && object.all? { |k, v| k =~ /\A-?\d+\z/ && v.is_a?(Hash) }
223
- end
224
-
225
- def unpermitted_parameters!(params)
226
- return unless self.class.action_on_unpermitted_parameters
227
-
228
- unpermitted_keys = unpermitted_keys(params)
229
-
230
- if unpermitted_keys.any?
231
- case self.class.action_on_unpermitted_parameters
232
- when :log
233
- name = "unpermitted_parameters.action_controller"
234
- ActiveSupport::Notifications.instrument(name, :keys => unpermitted_keys)
235
- when :raise
236
- raise UnpermittedParameters.new(unpermitted_keys)
536
+ def permit_any_in_array(array)
537
+ [].tap do |sanitized|
538
+ array.each do |element|
539
+ case element
540
+ when ->(e) { permitted_scalar?(e) }
541
+ sanitized << element
542
+ when Parameters
543
+ sanitized << permit_any_in_parameters(element)
544
+ else
545
+ # Filter this one out.
237
546
  end
238
547
  end
239
548
  end
549
+ end
240
550
 
241
- def unpermitted_keys(params)
242
- self.keys - params.keys - NEVER_UNPERMITTED_PARAMS
243
- end
551
+ def initialize_copy(source)
552
+ super
553
+ @parameters = @parameters.dup
554
+ end
244
555
  end
245
556
  end
@@ -1,3 +1,3 @@
1
1
  module RubyPitaya
2
- VERSION = '2.17.0'
2
+ VERSION = '2.18.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubypitaya
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.17.0
4
+ version: 2.18.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luciano Prestes Cavalcanti
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-02-28 00:00:00.000000000 Z
11
+ date: 2021-03-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pg