coaster 1.3.17 → 1.3.19

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
  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