coaster 1.3.17 → 1.3.19

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: ab2eb8291386db2096f9972b5094c8377337cf1ba33741222dc748959e9eb6c8
4
- data.tar.gz: 599d8e3771f71618d5cd93b111bc04b68b61cd632bedb212e8070d61758462ae
3
+ metadata.gz: 027776edeff41584c83bf80bc821af255f2315c3b0710cd1e4f86feae9489de6
4
+ data.tar.gz: 369e0b1ca5e3def035a66a9ba163954fb5541718af7be9164616c04d1588f131
5
5
  SHA512:
6
- metadata.gz: 6700f6a695c28ca3d4eda360ccf651a5a35aa30568ad38f41e0e0992aeb3edd9cee94d23beab7e1f79e03f378553a7b09efbc278ce7090511dee9c046394e916
7
- data.tar.gz: da224933981d1593c1ddf6318829ca63a6610dcf75535bd49a3c043a32ef604a074292c50da53e8ff5790e690ddc851bf6a9ea3e251ee2afcb6e0b3308b52be4
6
+ metadata.gz: b1bbc8f1f40e6da9ed89c7b71150d7beab5c8296e6209a57bb029a8c5fa1ac43d19a40f407cb6f0287ff722d965a345ed21ce7c5b32a7a1a98b07fd916a0ad8d
7
+ data.tar.gz: 9dc7568d12aef21c1afee7c469d26313cded69c90c36c81d9e905fd72cf0a765f89b7410527e8525647fad95cc919bd1026e1d2f26936e6f2520d710b510e56a
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Coaster
4
+ # +ActiveRecord::AttributeMethods::Serialization#serialize+ 적용시 YAML
5
+ # 시리얼라이저로 지정한다. 다음과 같은 특징이 있다.
6
+ # * 안전한 YAML(+Psych.safe_load+ 가능한 YAML)로 시리얼라이즈한다.
7
+ # * +Hash+ 만 지원한다.
8
+ # * YAML 데이터가 nil 인 경우 +load+ 하면 빈 해시를 반환한다.
9
+ # * +load+ 는 +ActiveSupport::HashWithIndifferentAccess+ 를 반환한다.
10
+ # ==== 주의
11
+ # * 해시 값에 지정된 객체는 기본 타입(String으로 변환된다
12
+ #
13
+ # ==== Example
14
+ # class User < ApplicationRecord
15
+ # serialize :data, SafeYamlSerializer
16
+ # end
17
+ class SafeYamlSerializer
18
+ class << self
19
+ def dump(obj)
20
+ return if obj.nil?
21
+ YAML.dump(JSON.load(obj.to_json))
22
+ end
23
+
24
+ def _load_hash(yaml)
25
+ return {} if yaml.nil?
26
+ return yaml unless yaml.is_a?(String) && yaml.start_with?("---")
27
+
28
+ if Rails.env.production?
29
+ YAML.load(yaml)
30
+ else
31
+ begin
32
+ YAML.safe_load(yaml, [], [], true) || {}
33
+ rescue Psych::DisallowedClass => e
34
+ # Rails.logger.warn e.inspect
35
+ # Rails.logger.warn e.backtrace.join("\n")
36
+ YAML.load(yaml) || {}
37
+ end
38
+ end
39
+ end
40
+
41
+ # @return [HashWithIndifferentAccess]
42
+ def load(yaml)
43
+ (_load_hash(yaml) || {}).with_indifferent_access
44
+ end
45
+ end
46
+ end
47
+ end
@@ -143,6 +143,7 @@ module Coaster
143
143
  define_method key.to_sym do
144
144
  hsh = send(serialize_column.to_sym)
145
145
  hsh[key.to_s] ||= default.dup
146
+ hsh[key.to_s]
146
147
  end
147
148
  end
148
149
  else
data/lib/coaster/util.rb CHANGED
@@ -1,18 +1,22 @@
1
1
  module Coaster
2
2
  module Util
3
3
  FLATTEN_HASH_DELIMITER = '.'.freeze
4
+ ARRAY_START = 0
4
5
 
5
6
  class << self
6
- def flatten_hashify(object, delimiter: FLATTEN_HASH_DELIMITER, breadcrumbs: [], include_array: nil)
7
+ # array_start가 0이면 array를 {'0'=>'blah', '1'=>'vlah'}
8
+ # array_start가 1이면 array를 {'1'=>'blah', '2'=>'vlah'}
9
+ # array_start가 nil이면 그대로 ['blah', 'vlah'] 로 처리
10
+ def flatten_hashify(object, delimiter: FLATTEN_HASH_DELIMITER, breadcrumbs: [], array_start: nil)
7
11
  case object
8
12
  when Hash
9
13
  object.each_with_object({}) do |(key, value), memo|
10
- memo.merge!(flatten_hashify(value, delimiter: delimiter, breadcrumbs: breadcrumbs + [key], include_array: include_array))
14
+ memo.merge!(flatten_hashify(value, delimiter: delimiter, breadcrumbs: breadcrumbs + [key], array_start: array_start))
11
15
  end
12
16
  when Array
13
- if include_array
14
- object.each.with_index(1).with_object({}) do |(element, ix), memo|
15
- memo.merge!(flatten_hashify(element, delimiter: delimiter, breadcrumbs: breadcrumbs + [ix], include_array: include_array))
17
+ if array_start
18
+ object.each.with_index(array_start).with_object({}) do |(element, ix), memo|
19
+ memo.merge!(flatten_hashify(element, delimiter: delimiter, breadcrumbs: breadcrumbs + [ix], array_start: array_start))
16
20
  end
17
21
  else
18
22
  {breadcrumbs.join(delimiter) => object}
@@ -21,6 +25,43 @@ module Coaster
21
25
  {breadcrumbs.join(delimiter) => object}
22
26
  end
23
27
  end
28
+
29
+ # 숫자로 된 키는 무조건 array로 처리함
30
+ # array_start는 nil일 경우 기본값은 Util::ARRAY_START = 0
31
+ def roughen_hashify(object, delimiter: FLATTEN_HASH_DELIMITER, array_start: nil)
32
+ array_start ||= ARRAY_START
33
+
34
+ step1 = object.each_with_object({}) do |(key, value), memo|
35
+ sp_keys = key.split(delimiter)
36
+ k = sp_keys.shift
37
+ if sp_keys.present?
38
+ memo[k] ||= {}
39
+ memo[k][sp_keys.join(delimiter)] = value
40
+ else
41
+ memo[k] = value
42
+ end
43
+ end
44
+
45
+ step2 = step1.each_with_object({}) do |(key, value), memo|
46
+ case value
47
+ when Hash
48
+ memo[key] = roughen_hashify(value, delimiter: delimiter, array_start: array_start)
49
+ else
50
+ memo[key] = value
51
+ end
52
+ end
53
+
54
+ array_keys = (array_start...(step2.keys.size+array_start)).to_a
55
+ if array_keys == step2.keys.map(&:to_i).sort
56
+ step3 = []
57
+ array_keys.map(&:to_s).each do |k|
58
+ step3 << step2[k]
59
+ end
60
+ step3
61
+ else
62
+ step2
63
+ end
64
+ end
24
65
  end
25
66
  end
26
67
  end
@@ -1,3 +1,3 @@
1
1
  module Coaster
2
- VERSION = '1.3.17'
2
+ VERSION = '1.3.19'
3
3
  end
@@ -0,0 +1,14 @@
1
+ require 'coaster/serialized_properties'
2
+ require 'coaster/safe_yaml_serializer'
3
+
4
+ class User < ActiveRecord::Base
5
+ serialize :data, Coaster::SafeYamlSerializer
6
+ extend Coaster::SerializedProperties
7
+ serialized_column :data
8
+ serialized_property :data, :appendix, default: {}
9
+
10
+ def init_appendix
11
+ appendix['test_key1'] ||= 0
12
+ appendix['test_key2'] ||= 0
13
+ end
14
+ end
@@ -0,0 +1,11 @@
1
+ ActiveRecord::Schema.define do
2
+ create_table :users do |t|
3
+ t.string :key
4
+ t.string :name
5
+ t.integer :age
6
+ t.datetime :last_login
7
+ t.text :data
8
+ t.timestamps
9
+ end
10
+
11
+ end
data/test/test_helper.rb CHANGED
@@ -8,6 +8,12 @@ require 'bundler/setup'
8
8
  require 'coaster'
9
9
  require 'logger'
10
10
 
11
+ require 'active_record'
12
+ ActiveRecord::Base.establish_connection adapter: 'sqlite3', database: ":memory:"
13
+ load File.expand_path('../support/schema.rb', __FILE__)
14
+ load File.expand_path('../support/models.rb', __FILE__)
15
+ require 'rails'
16
+
11
17
  class Raven
12
18
  def self.capture_exception(*args)
13
19
  end
@@ -0,0 +1,19 @@
1
+ require 'test_helper'
2
+ require 'minitest/autorun'
3
+
4
+ module Coaster
5
+ class TestSerializedProperty < Minitest::Test
6
+ def setup
7
+ end
8
+
9
+ def teardown
10
+ end
11
+
12
+ def test_serialized
13
+ user = User.create(name: 'abc')
14
+ user.init_appendix
15
+ assert_equal 0, user.appendix['test_key1']
16
+ assert_equal 0, user.appendix['test_key2']
17
+ end
18
+ end
19
+ end
data/test/test_util.rb CHANGED
@@ -11,19 +11,32 @@ module Coaster
11
11
  end
12
12
 
13
13
  def test_flatten_hashify
14
- res = Util.flatten_hashify({a: [1], b: {aa: 1, bb: [2, 1]}})
14
+ a = {'a'=>[1], 'b'=>{'aa'=>1, 'bb'=>[2, 1]}}
15
+ res = Util.flatten_hashify(a)
15
16
  assert_equal({"a"=>[1], "b.aa"=>1, "b.bb"=>[2, 1]}, res)
16
- res = Util.flatten_hashify({a: [1], b: {aa: 1, bb: [2, 1]}}, include_array: true)
17
+ b = Util.roughen_hashify(res)
18
+ assert_equal(a, b)
19
+ res = Util.flatten_hashify(a, array_start: 1)
17
20
  assert_equal({"a.1"=>1, "b.aa"=>1, "b.bb.1"=>2, "b.bb.2"=>1}, res)
21
+ b = Util.roughen_hashify(res, array_start: 1)
22
+ assert_equal(a, b)
23
+ res = Util.flatten_hashify(a, array_start: 0)
24
+ assert_equal({"a.0"=>1, "b.aa"=>1, "b.bb.0"=>2, "b.bb.1"=>1}, res)
25
+ b = Util.roughen_hashify(res)
26
+ assert_equal(a, b)
27
+
18
28
  res = Util.flatten_hashify([{a: 1}, 22, [33, 44], {b: {c: [33, {d: 4}]}}])
19
29
  assert_equal({""=>[{:a=>1}, 22, [33, 44], {:b=>{:c=>[33, {:d=>4}]}}]}, res) # no meaning result
20
- res = Util.flatten_hashify([{a: 1}, 22, [33, 44], {b: {c: [33, {d: 4}]}}], include_array: true)
30
+ res = Util.flatten_hashify([{a: 1}, 22, [33, 44], {b: {c: [33, {d: 4}]}}], array_start: 1)
21
31
  assert_equal({"1.a"=>1, "2"=>22, "3.1"=>33, "3.2"=>44, "4.b.c.1"=>33, "4.b.c.2.d"=>4}, res)
22
32
  end
23
33
 
24
34
  def test_flatten_hashify_delimiter
25
- res = Util.flatten_hashify([{a: 1}, 22, [33, 44], {b: {c: [33, {d: 4}]}}], include_array: true, delimiter: '/')
35
+ a = [{'a'=>1}, 22, [33, 44], {'b'=>{'c'=>[33, {'d'=>4}]}}]
36
+ res = Util.flatten_hashify(a, array_start: 1, delimiter: '/')
26
37
  assert_equal({"1/a"=>1, "2"=>22, "3/1"=>33, "3/2"=>44, "4/b/c/1"=>33, "4/b/c/2/d"=>4}, res)
38
+ b = Util.roughen_hashify(res, array_start: 1, delimiter: '/')
39
+ assert_equal(a, b)
27
40
  end
28
41
  end
29
42
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: coaster
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.17
4
+ version: 1.3.19
5
5
  platform: ruby
6
6
  authors:
7
7
  - buzz jung
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-08-10 00:00:00.000000000 Z
11
+ date: 2022-10-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: i18n
@@ -136,6 +136,34 @@ dependencies:
136
136
  - - ">="
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: rails
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: sqlite3
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
139
167
  description: Ruby Core Extensions
140
168
  email: buzz@frograms.com
141
169
  executables: []
@@ -157,14 +185,18 @@ files:
157
185
  - lib/coaster/core_ext/standard_error/sentry.rb
158
186
  - lib/coaster/rails_ext.rb
159
187
  - lib/coaster/rails_ext/backtrace_cleaner.rb
188
+ - lib/coaster/safe_yaml_serializer.rb
160
189
  - lib/coaster/serialized_properties.rb
161
190
  - lib/coaster/util.rb
162
191
  - lib/coaster/version.rb
163
192
  - test/locales/en.yml
193
+ - test/support/models.rb
194
+ - test/support/schema.rb
164
195
  - test/test_backtrace.rb
165
196
  - test/test_helper.rb
166
197
  - test/test_month.rb
167
198
  - test/test_object_translation.rb
199
+ - test/test_serialized_property.rb
168
200
  - test/test_standard_error.rb
169
201
  - test/test_util.rb
170
202
  homepage: http://github.com/frograms/coaster
@@ -192,9 +224,12 @@ specification_version: 4
192
224
  summary: A little convenient feature for standard library
193
225
  test_files:
194
226
  - test/locales/en.yml
227
+ - test/support/models.rb
228
+ - test/support/schema.rb
195
229
  - test/test_backtrace.rb
196
230
  - test/test_helper.rb
197
231
  - test/test_month.rb
198
232
  - test/test_object_translation.rb
233
+ - test/test_serialized_property.rb
199
234
  - test/test_standard_error.rb
200
235
  - test/test_util.rb