coaster 0.4.7 → 0.5.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: 87a3bfb2be6aec0a47f770b352bcd01988627bb3
4
- data.tar.gz: b610ad99c8a1933e7baf37d88e9267daa1cccb7c
3
+ metadata.gz: 3f3443395e8b26f474e4d170c1dd1e3edea41cf9
4
+ data.tar.gz: 482a7957080674361a16c29a6284e7f819c8248e
5
5
  SHA512:
6
- metadata.gz: abf2b202fb7f15967a44a4f8ccfcae931fd910aebb3ccf28253d7497877b538fe2297f4e64edc6915e87a3d341797a104b52d1159966c619fcc969814ed0c28a
7
- data.tar.gz: bafd012b8095e7a7fe93884503ffc52902b7e2b8d2e08b48f683159abce813f80196719beedb66900da285ee6751ed581990432c3e60ce9612228e05adc5fbe6
6
+ metadata.gz: 27ff86f49682b3bfc97c2e9f335fb1a01921b524541b7d7c5f11c283f5bd6afb50a798bcfa4748d4bbf4c457707705e2826f2c5fd4d4c431017c7f4e02bb5eb3
7
+ data.tar.gz: a109aefbd31130b58d721a92a365f3b726b4afe0854ef7a4b94872545f20332fe6f589629eb6d1952f474f30891b79d93c894204a5df503977e1b29fafac3bf7
@@ -0,0 +1,11 @@
1
+ class Array
2
+ def toggle(value)
3
+ if include?(value)
4
+ delete(value)
5
+ false
6
+ else
7
+ self << value
8
+ true
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,5 @@
1
+ class Date
2
+ def to_time_range
3
+ beginning_of_day...(self + 1.day).beginning_of_day
4
+ end
5
+ end
@@ -0,0 +1,108 @@
1
+ require 'attr_extras' # gem
2
+
3
+ class Month
4
+ vattr_initialize :year, :month
5
+
6
+ class << self
7
+ def from(object)
8
+ case object
9
+ when Month then object
10
+ when String then Month.parse(object)
11
+ when Array then Month.new(object[0], object[1])
12
+ else new(object.year, object.month)
13
+ end
14
+ end
15
+
16
+ # Month.parse('201601')
17
+ # Month.parse('2016-01')
18
+ def parse(str)
19
+ date = Date.parse(str)
20
+ from(date)
21
+ rescue ArgumentError => e
22
+ if str.instance_variable_get(:@_gsub_)
23
+ raise e, str: str.instance_variable_get(:@_gsub_)
24
+ elsif e.message != 'invalid date'
25
+ raise e, str: str
26
+ end
27
+ str_gsub = str.gsub(/[^\d]/, '')
28
+ str_gsub.insert(4, '0') if str_gsub.length == 5
29
+ str_gsub += '01'
30
+ str_gsub.instance_variable_set(:@_gsub_, str_gsub)
31
+ parse(str_gsub)
32
+ end
33
+
34
+ def current
35
+ from(Date.current)
36
+ end
37
+
38
+ def now
39
+ from(Time.zone.now)
40
+ end
41
+ end
42
+
43
+ def year
44
+ Integer(@year)
45
+ end
46
+
47
+ def month
48
+ Integer(@month)
49
+ end
50
+
51
+ def first_date
52
+ Date.new(year, month, 1)
53
+ end
54
+
55
+ def last_date
56
+ Date.new(year, month, -1)
57
+ end
58
+
59
+ def first_day
60
+ first_date.day
61
+ end
62
+
63
+ def last_day
64
+ last_date.day
65
+ end
66
+
67
+ def beginning_of_month
68
+ first_date.beginning_of_day
69
+ end
70
+
71
+ def end_of_month
72
+ last_date.end_of_day
73
+ end
74
+
75
+ def date_for_day(number)
76
+ Date.new(year, month, number)
77
+ end
78
+
79
+ def to_time_range
80
+ beginning_of_month...(later.beginning_of_month)
81
+ end
82
+
83
+ def previous
84
+ self.class.from(first_date - 1)
85
+ end
86
+
87
+ def later
88
+ self.class.from(last_date + 1)
89
+ end
90
+
91
+ def to_s
92
+ "#{year}-#{month}"
93
+ end
94
+ alias_method :inspect, :to_s
95
+
96
+ def -(time)
97
+ first_date - time
98
+ end
99
+
100
+ def +(time)
101
+ first_date + time
102
+ end
103
+
104
+ include Comparable
105
+ def <=>(other)
106
+ first_date <=> Month.from(other).first_date
107
+ end
108
+ end
@@ -1,2 +1,5 @@
1
+ require_relative 'core_ext/array'
2
+ require_relative 'core_ext/date'
3
+ require_relative 'core_ext/month'
1
4
  require_relative 'core_ext/object_translation'
2
5
  require_relative 'core_ext/standard_error'
@@ -0,0 +1,193 @@
1
+ module Coaster
2
+ module SerializedProperties
3
+ class DuplicatedProperty < StandardError; end
4
+ class InvalidProperty < StandardError; end
5
+
6
+ def serialized_property_settings
7
+ @serialized_property_settings ||= {}
8
+ end
9
+
10
+ def serialized_property_setting(key)
11
+ serialized_property_settings[key.to_sym]
12
+ end
13
+
14
+ def serialized_column(serialize_column)
15
+ define_method serialize_column.to_sym do
16
+ return read_attribute(serialize_column.to_sym) if read_attribute(serialize_column.to_sym)
17
+ write_attribute(serialize_column.to_sym, {})
18
+ read_attribute(serialize_column)
19
+ end
20
+ end
21
+
22
+ def serialized_property_comment(key)
23
+ cm = serialized_property_settings[key.to_sym] &&
24
+ serialized_property_settings[key.to_sym][:comment]
25
+ cm || key.to_s
26
+ end
27
+
28
+ def serialized_property(serialize_column, key, type: nil, comment: nil, getter: nil, setter: nil, setter_callback: nil, default: nil)
29
+ raise DuplicatedProperty, "#{self.name}##{key} duplicated\n#{caller[0..5].join("\n")}" if serialized_property_settings[key.to_sym]
30
+ serialized_property_settings[key.to_sym] = {type: type, comment: comment, getter: getter, setter: setter, setter_callback: setter_callback, default: default}
31
+ _typed_serialized_property(serialize_column, key, type: type, getter: getter, setter: setter, setter_callback: setter_callback, default: default)
32
+ end
33
+
34
+ def serialized_properties(serialize_column, *keys, type: nil, getter: nil, setter: nil, setter_callback: nil, default: nil)
35
+ keys.flatten.each do |key|
36
+ key_name = key
37
+ prop_hash = {type: type, getter: getter, setter: setter, setter_callback: setter_callback, default: default}
38
+ if key.is_a? Hash
39
+ key_name = key[:key]
40
+ prop_hash = {type: type, getter: getter, setter: setter, setter_callback: setter_callback, default: default}.merge(key)
41
+ prop_hash.delete(:key)
42
+ end
43
+ serialized_property(serialize_column, key_name, prop_hash)
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ def _typed_serialized_property(serialize_column, key, type: nil, getter: nil, setter: nil, setter_callback: nil, default: nil)
50
+ case type
51
+ when String then
52
+ # String은 나중에 eval해서 가져옴,
53
+ # type에서 다른 객체를 참조할 경우, 순환참조가 발생할 수 있기 때문에
54
+ Rails.configuration.after_initialize {
55
+ if type.is_a?(String)
56
+ begin
57
+ type = eval(type)
58
+ raise InvalidProperty, "#{self.name}##{key} type string is return string #{type}" if type.is_a?(String)
59
+ rescue InvalidProperty => e
60
+ raise
61
+ rescue => e
62
+ raise InvalidProperty, "#{self.name}##{key} eval failed: type:[#{type}] [#{e.class.name}] #{e.message}"
63
+ end
64
+ serialized_property_setting(key.to_sym)[:type] = type
65
+ _typed_serialized_property serialize_column, key, type: type, getter: getter, setter: setter, setter_callback: setter_callback, default: default
66
+ end
67
+ }
68
+ when Array then
69
+ _define_serialized_property serialize_column, key,
70
+ setter: proc { |val|
71
+ raise InvalidProperty, "#{self.name}##{key} must be one of #{type}" unless type.include?(val)
72
+ val
73
+ },
74
+ getter: proc { |val|
75
+ type.include?(val) ? val : nil
76
+ }
77
+ else
78
+ if type == Time
79
+ _define_serialized_property serialize_column, key,
80
+ getter: Proc.new { |val| val.nil? ? nil : Time.zone.parse(val) },
81
+ setter: Proc.new { |val| val.is_a?(Time) ? val.to_s(:default_tz) : nil}
82
+ elsif type == Integer
83
+ _define_serialized_property serialize_column, key,
84
+ setter: proc { |val|
85
+ val = val.blank? ? nil : Integer(val)
86
+ val = setter.call(val) if setter
87
+ val
88
+ }
89
+ elsif type == Array
90
+ _define_serialized_property(serialize_column, key, default: [])
91
+ elsif type && type < ActiveRecord::Base
92
+ _define_serialized_property serialize_column, "#{key}_id"
93
+
94
+ define_method key.to_sym do
95
+ instance_val = instance_variable_get("@#{key}".to_sym)
96
+ return instance_val if instance_val
97
+ key_id = send("#{key}_id".to_sym)
98
+ if key_id.nil?
99
+ instance_val = nil
100
+ else
101
+ instance_val = type.find(key_id) rescue nil
102
+ instance_variable_set("@#{key}".to_sym, instance_val)
103
+ end
104
+ instance_val = getter.call(instance_val) if getter
105
+ instance_val
106
+ end
107
+
108
+ define_method "#{key}=".to_sym do |val|
109
+ val = setter.call(val) if setter
110
+
111
+ if val.nil?
112
+ instance_variable_set("@#{key}".to_sym, nil)
113
+ send("#{key}_id=".to_sym, nil)
114
+ else
115
+ unless val.is_a?(type)
116
+ raise ActiveRecord::AssociationTypeMismatch, "#{type}(##{type.object_id}) expected, got #{val.class.name}(#{val.class.object_id})"
117
+ end
118
+ instance_variable_set("@#{key}".to_sym, val)
119
+ send("#{key}_id=".to_sym, (Integer(val.id) rescue val.id))
120
+ end
121
+
122
+ if setter_callback
123
+ setter_callback.call(val)
124
+ else
125
+ val
126
+ end
127
+ end
128
+ else
129
+ _define_serialized_property serialize_column, key, getter: getter, setter: setter, setter_callback: setter_callback, default: default
130
+ end
131
+ end
132
+ end
133
+
134
+ def _define_serialized_property(serialize_column, key, getter: nil, setter: nil, setter_callback: nil, default: nil)
135
+ if default
136
+ if getter
137
+ define_method key.to_sym do
138
+ hsh = send(serialize_column.to_sym)
139
+ hsh[key.to_s] ||= default.dup
140
+ getter.call(hsh[key.to_s])
141
+ end
142
+ else
143
+ define_method key.to_sym do
144
+ hsh = send(serialize_column.to_sym)
145
+ hsh[key.to_s] ||= default.dup
146
+ end
147
+ end
148
+ else
149
+ if getter
150
+ define_method key.to_sym do
151
+ hsh = send(serialize_column.to_sym)
152
+ getter.call(hsh[key.to_s])
153
+ end
154
+ else
155
+ define_method key.to_sym do
156
+ hsh = send(serialize_column.to_sym)
157
+ hsh[key.to_s]
158
+ end
159
+ end
160
+ end
161
+
162
+ if setter
163
+ define_method "#{key}_without_callback=".to_sym do |val|
164
+ if val.nil?
165
+ send(serialize_column.to_sym).delete(key.to_s)
166
+ else
167
+ val = setter.call(val) if setter
168
+ send(serialize_column.to_sym)[key.to_s] = val
169
+ end
170
+ end
171
+ else
172
+ define_method "#{key}_without_callback=".to_sym do |val|
173
+ if val.nil?
174
+ send(serialize_column.to_sym).delete(key.to_s)
175
+ else
176
+ send(serialize_column.to_sym)[key.to_s] = val
177
+ end
178
+ end
179
+ end
180
+
181
+ if setter_callback
182
+ define_method "#{key}=".to_sym do |val|
183
+ send("#{key}_without_callback=".to_sym, val)
184
+ setter_callback.call(val)
185
+ end
186
+ else
187
+ define_method "#{key}=".to_sym do |val|
188
+ send("#{key}_without_callback=".to_sym, val)
189
+ end
190
+ end
191
+ end
192
+ end
193
+ end
@@ -1,3 +1,3 @@
1
1
  module Coaster
2
- VERSION = '0.4.7'
2
+ VERSION = '0.5.0'
3
3
  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: 0.4.7
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - buzz jung
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-11-14 00:00:00.000000000 Z
11
+ date: 2017-12-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: i18n
@@ -64,6 +64,20 @@ dependencies:
64
64
  - - "<"
65
65
  - !ruby/object:Gem::Version
66
66
  version: '8.0'
67
+ - !ruby/object:Gem::Dependency
68
+ name: attr_extras
69
+ requirement: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ type: :runtime
75
+ prerelease: false
76
+ version_requirements: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
67
81
  - !ruby/object:Gem::Dependency
68
82
  name: bundler
69
83
  requirement: !ruby/object:Gem::Requirement
@@ -188,9 +202,13 @@ files:
188
202
  - lib/coaster.rb
189
203
  - lib/coaster/backtrace_cleaner.rb
190
204
  - lib/coaster/core_ext.rb
205
+ - lib/coaster/core_ext/array.rb
206
+ - lib/coaster/core_ext/date.rb
207
+ - lib/coaster/core_ext/month.rb
191
208
  - lib/coaster/core_ext/object_translation.rb
192
209
  - lib/coaster/core_ext/standard_error.rb
193
210
  - lib/coaster/core_ext/standard_error/raven.rb
211
+ - lib/coaster/serialized_properties.rb
194
212
  - lib/coaster/version.rb
195
213
  - test/locales/en.yml
196
214
  - test/test_helper.rb