coaster 1.4.27 → 1.4.30
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 +4 -4
- data/bin/bundle +114 -0
- data/lib/coaster/core_ext/css_hash_string.rb +43 -0
- data/lib/coaster/core_ext/deep_key_count.rb +44 -0
- data/lib/coaster/core_ext/hash.rb +2 -0
- data/lib/coaster/core_ext/memory_size.rb +85 -0
- data/lib/coaster/core_ext.rb +1 -0
- data/lib/coaster/rails_ext/action_view/template/error.rb +12 -0
- data/lib/coaster/rails_ext.rb +3 -0
- data/lib/coaster/serialized_properties.rb +48 -1
- data/lib/coaster/version.rb +1 -1
- data/test/support/models.rb +1 -1
- data/test/test_action_view.rb +27 -0
- data/test/test_css_hash_string.rb +25 -0
- data/test/test_deep_key_count.rb +36 -0
- data/test/test_memory_size.rb +36 -0
- data/test/test_serialized_property.rb +7 -0
- data/test/test_standard_error.rb +7 -8
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d39beeaee29be2896e13ec86ba9e0a9c581a424d8886757e3478fe7283350276
|
4
|
+
data.tar.gz: dec06f3400a4e5be9f95987fddca45d04ed41cdc991070455361bb2463d91cb0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 384a1e5564c587f06901aecceb71de37b70fb51353f205067b966cd525dfda3b16c81a7bbd3830740da68c448a3b0c756f117e372d0343bc8f871e5b8192c204
|
7
|
+
data.tar.gz: ac1b741ff50422d42335e96ba32e6c2362571452c5c425d27b27bb72822c9f99932540eacb37f19e908b51c3f160cf3fe9d8b2300ad3deb651a6b8c100cdb881
|
data/bin/bundle
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'bundle' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "rubygems"
|
12
|
+
|
13
|
+
m = Module.new do
|
14
|
+
module_function
|
15
|
+
|
16
|
+
def invoked_as_script?
|
17
|
+
File.expand_path($0) == File.expand_path(__FILE__)
|
18
|
+
end
|
19
|
+
|
20
|
+
def env_var_version
|
21
|
+
ENV["BUNDLER_VERSION"]
|
22
|
+
end
|
23
|
+
|
24
|
+
def cli_arg_version
|
25
|
+
return unless invoked_as_script? # don't want to hijack other binstubs
|
26
|
+
return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update`
|
27
|
+
bundler_version = nil
|
28
|
+
update_index = nil
|
29
|
+
ARGV.each_with_index do |a, i|
|
30
|
+
if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN
|
31
|
+
bundler_version = a
|
32
|
+
end
|
33
|
+
next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/
|
34
|
+
bundler_version = $1
|
35
|
+
update_index = i
|
36
|
+
end
|
37
|
+
bundler_version
|
38
|
+
end
|
39
|
+
|
40
|
+
def gemfile
|
41
|
+
gemfile = ENV["BUNDLE_GEMFILE"]
|
42
|
+
return gemfile if gemfile && !gemfile.empty?
|
43
|
+
|
44
|
+
File.expand_path("../Gemfile", __dir__)
|
45
|
+
end
|
46
|
+
|
47
|
+
def lockfile
|
48
|
+
lockfile =
|
49
|
+
case File.basename(gemfile)
|
50
|
+
when "gems.rb" then gemfile.sub(/\.rb$/, gemfile)
|
51
|
+
else "#{gemfile}.lock"
|
52
|
+
end
|
53
|
+
File.expand_path(lockfile)
|
54
|
+
end
|
55
|
+
|
56
|
+
def lockfile_version
|
57
|
+
return unless File.file?(lockfile)
|
58
|
+
lockfile_contents = File.read(lockfile)
|
59
|
+
return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/
|
60
|
+
Regexp.last_match(1)
|
61
|
+
end
|
62
|
+
|
63
|
+
def bundler_requirement
|
64
|
+
@bundler_requirement ||=
|
65
|
+
env_var_version || cli_arg_version ||
|
66
|
+
bundler_requirement_for(lockfile_version)
|
67
|
+
end
|
68
|
+
|
69
|
+
def bundler_requirement_for(version)
|
70
|
+
return "#{Gem::Requirement.default}.a" unless version
|
71
|
+
|
72
|
+
bundler_gem_version = Gem::Version.new(version)
|
73
|
+
|
74
|
+
requirement = bundler_gem_version.approximate_recommendation
|
75
|
+
|
76
|
+
return requirement unless Gem.rubygems_version < Gem::Version.new("2.7.0")
|
77
|
+
|
78
|
+
requirement += ".a" if bundler_gem_version.prerelease?
|
79
|
+
|
80
|
+
requirement
|
81
|
+
end
|
82
|
+
|
83
|
+
def load_bundler!
|
84
|
+
ENV["BUNDLE_GEMFILE"] ||= gemfile
|
85
|
+
|
86
|
+
activate_bundler
|
87
|
+
end
|
88
|
+
|
89
|
+
def activate_bundler
|
90
|
+
gem_error = activation_error_handling do
|
91
|
+
gem "bundler", bundler_requirement
|
92
|
+
end
|
93
|
+
return if gem_error.nil?
|
94
|
+
require_error = activation_error_handling do
|
95
|
+
require "bundler/version"
|
96
|
+
end
|
97
|
+
return if require_error.nil? && Gem::Requirement.new(bundler_requirement).satisfied_by?(Gem::Version.new(Bundler::VERSION))
|
98
|
+
warn "Activating bundler (#{bundler_requirement}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_requirement}'`"
|
99
|
+
exit 42
|
100
|
+
end
|
101
|
+
|
102
|
+
def activation_error_handling
|
103
|
+
yield
|
104
|
+
nil
|
105
|
+
rescue StandardError, LoadError => e
|
106
|
+
e
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
m.load_bundler!
|
111
|
+
|
112
|
+
if m.invoked_as_script?
|
113
|
+
load Gem.bin_path("bundler", "bundle")
|
114
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Coaster
|
2
|
+
module CssHashString
|
3
|
+
module HashToStyle
|
4
|
+
def to_css_style(**defaults)
|
5
|
+
to_css_hash(**defaults).map do |k, v|
|
6
|
+
k = k.gsub(/_/, '-')
|
7
|
+
v.present? ? "#{k}:#{v}" : nil
|
8
|
+
end.compact.join(';')
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_css_hash(**defaults)
|
12
|
+
defaults = defaults.map do |k, v|
|
13
|
+
k = k.to_s.gsub(/_/, '-')
|
14
|
+
v.present? ? [k, v] : nil
|
15
|
+
end.compact.to_h
|
16
|
+
h = self.map do |k, v|
|
17
|
+
k = k.to_s.gsub(/_/, '-')
|
18
|
+
v.present? ? [k, v] : nil
|
19
|
+
end.compact.to_h
|
20
|
+
defaults.merge(h)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
::Hash.send(:include, HashToStyle)
|
24
|
+
::ActiveSupport::HashWithIndifferentAccess.send(:include, HashToStyle)
|
25
|
+
|
26
|
+
module StringToStyle
|
27
|
+
def to_css_style(**defaults)
|
28
|
+
return self unless defaults.present?
|
29
|
+
to_css_hash(**defaults).to_css_style
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_css_hash(**defaults)
|
33
|
+
defaults.with_indifferent_access.merge(
|
34
|
+
self.split(';').map do |pair|
|
35
|
+
k, v = pair.split(':')
|
36
|
+
[k.strip, v.strip]
|
37
|
+
end.to_h
|
38
|
+
)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
::String.send(:include, StringToStyle)
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Coaster
|
2
|
+
module DeepKeyCount
|
3
|
+
module HashCnt
|
4
|
+
def deep_key_count(**options)
|
5
|
+
keys.size + values.sum do |v|
|
6
|
+
case v
|
7
|
+
when Hash
|
8
|
+
v.deep_key_count(**options)
|
9
|
+
when Array
|
10
|
+
if options[:array_is_element]
|
11
|
+
0
|
12
|
+
else
|
13
|
+
v.deep_key_count(**options)
|
14
|
+
end
|
15
|
+
else
|
16
|
+
0
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
::Hash.send(:include, HashCnt)
|
22
|
+
::ActiveSupport::HashWithIndifferentAccess.send(:include, HashCnt)
|
23
|
+
|
24
|
+
module ArrayCnt
|
25
|
+
def deep_key_count(**options)
|
26
|
+
sum do |v|
|
27
|
+
case v
|
28
|
+
when Hash
|
29
|
+
v.deep_key_count(**options)
|
30
|
+
when Array
|
31
|
+
if options[:array_is_element]
|
32
|
+
1
|
33
|
+
else
|
34
|
+
v.deep_key_count(**options)
|
35
|
+
end
|
36
|
+
else
|
37
|
+
1
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
::Array.send(:include, ArrayCnt)
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'objspace'
|
2
|
+
|
3
|
+
class Object
|
4
|
+
def memory_size(depth: 2, object_ids: [])
|
5
|
+
res = {nil => ObjectSpace.memsize_of(self)}
|
6
|
+
instance_variables.each do |var|
|
7
|
+
iv = instance_variable_get(var)
|
8
|
+
if object_ids.include?(iv.object_id)
|
9
|
+
res[var] = nil
|
10
|
+
else
|
11
|
+
object_ids << iv.object_id
|
12
|
+
if depth > 0
|
13
|
+
res[var] = iv.memory_size(depth: depth - 1, object_ids:)
|
14
|
+
else
|
15
|
+
res[var] = iv.memory_size_total(object_ids:)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
res
|
20
|
+
end
|
21
|
+
|
22
|
+
def memory_size_total(object_ids: [])
|
23
|
+
sum = 0
|
24
|
+
memory_size(depth: 0, object_ids:).each do |k, v|
|
25
|
+
case v
|
26
|
+
when Hash, Array then sum += v._memory_size_total
|
27
|
+
when nil then next
|
28
|
+
else sum += v
|
29
|
+
end
|
30
|
+
end
|
31
|
+
sum
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class Array
|
36
|
+
def memory_size(depth: 2, object_ids: [])
|
37
|
+
res = {nil => super}
|
38
|
+
each_with_index do |item, x|
|
39
|
+
if depth > 0
|
40
|
+
res[x] = item.memory_size(depth: depth - 1, object_ids:)
|
41
|
+
else
|
42
|
+
res[x] = item.memory_size_total(object_ids:)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
res
|
46
|
+
end
|
47
|
+
|
48
|
+
def _memory_size_total
|
49
|
+
sum = 0
|
50
|
+
each do |item|
|
51
|
+
case item
|
52
|
+
when Hash, Array then sum += item._memory_size_total
|
53
|
+
when nil then next
|
54
|
+
else sum += item
|
55
|
+
end
|
56
|
+
end
|
57
|
+
sum
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class Hash
|
62
|
+
def memory_size(depth: 2, object_ids: [])
|
63
|
+
res = {nil => super}
|
64
|
+
each do |k, v|
|
65
|
+
if depth > 0
|
66
|
+
res[k] = [k.memory_size(depth: depth - 1, object_ids:), v.memory_size(depth: depth - 1, object_ids:)]
|
67
|
+
else
|
68
|
+
res[k] = k.memory_size_total(object_ids:) + v.memory_size_total(object_ids:)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
res
|
72
|
+
end
|
73
|
+
|
74
|
+
def _memory_size_total
|
75
|
+
sum = 0
|
76
|
+
each do |k, v|
|
77
|
+
case v
|
78
|
+
when Hash, Array then sum += v._memory_size_total
|
79
|
+
when nil then next
|
80
|
+
else sum += v
|
81
|
+
end
|
82
|
+
end
|
83
|
+
sum
|
84
|
+
end
|
85
|
+
end
|
data/lib/coaster/core_ext.rb
CHANGED
data/lib/coaster/rails_ext.rb
CHANGED
@@ -2,3 +2,6 @@ require 'coaster/rails_ext/active_support/backtrace_cleaner'
|
|
2
2
|
ActiveSupport.on_load(:active_record, yield: true) do
|
3
3
|
require 'coaster/rails_ext/active_record/errors'
|
4
4
|
end
|
5
|
+
ActiveSupport.on_load(:action_view, yield: true) do
|
6
|
+
require "coaster/rails_ext/action_view/template/error"
|
7
|
+
end
|
@@ -3,6 +3,33 @@ module Coaster
|
|
3
3
|
class DuplicatedProperty < StandardError; end
|
4
4
|
class InvalidProperty < StandardError; end
|
5
5
|
|
6
|
+
def self.extended(base)
|
7
|
+
base.class_eval do
|
8
|
+
def sprop_changes = self.class.serialized_property_changes(changes)
|
9
|
+
def sprop_change(key) = sprop_changes[key.to_s]
|
10
|
+
def sprop_changed?(key) = sprop_change(key).present?
|
11
|
+
def sprop_was(key) = (ch = sprop_change(key)).present? ? ch[0] : nil
|
12
|
+
|
13
|
+
def sprop_saved_changes = self.class.serialized_property_changes(saved_changes)
|
14
|
+
def sprop_saved_change(key) = sprop_saved_changes[key.to_s]
|
15
|
+
|
16
|
+
def sprop_previous_changes = self.class.serialized_property_changes(previous_changes)
|
17
|
+
def sprop_previous_change(key) = sprop_previous_changes[key.to_s]
|
18
|
+
def sprop_previously_changed?(key) = sprop_previous_change(key).present?
|
19
|
+
def sprop_previously_was(key) = (ch = sprop_previous_change(key)).present? ? ch[0] : nil
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def serialized_property_changes(changes)
|
24
|
+
serialized_property_settings.each_with_object({}) do |(key, prop), result|
|
25
|
+
prop_ch = changes[prop[:column].to_s]
|
26
|
+
next if prop_ch.blank?
|
27
|
+
before = prop_ch[0] && prop_ch[0][key.to_s]
|
28
|
+
after = prop_ch[1] && prop_ch[1][key.to_s]
|
29
|
+
result[key.to_s] = [before, after] if before != after
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
6
33
|
def serialized_property_settings
|
7
34
|
@serialized_property_settings ||= {}
|
8
35
|
end
|
@@ -27,7 +54,7 @@ module Coaster
|
|
27
54
|
|
28
55
|
def serialized_property(serialize_column, key, type: nil, comment: nil, getter: nil, setter: nil, setter_callback: nil, default: nil, rescuer: nil)
|
29
56
|
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, rescuer: rescuer}
|
57
|
+
serialized_property_settings[key.to_sym] = {column: serialize_column.to_sym, type: type, comment: comment, getter: getter, setter: setter, setter_callback: setter_callback, default: default, rescuer: rescuer}
|
31
58
|
_typed_serialized_property(serialize_column, key, type: type, getter: getter, setter: setter, setter_callback: setter_callback, default: default, rescuer: rescuer)
|
32
59
|
end
|
33
60
|
|
@@ -118,6 +145,7 @@ module Coaster
|
|
118
145
|
elsif type.respond_to?(:serialized_property_serializer) && (serializer = type.serialized_property_serializer)
|
119
146
|
_define_serialized_property(serialize_column, key, getter: serializer[:getter], setter: serializer[:setter], setter_callback: serializer[:setter_callback], default: default)
|
120
147
|
elsif (type.is_a?(Symbol) && (t = type.to_s.constantize rescue nil)) || (type.is_a?(Class) && type < ActiveRecord::Base && (t = type))
|
148
|
+
serialized_property_settings["#{key}_id".to_sym] = serialized_property_settings.delete(key.to_sym) # rename key from setting
|
121
149
|
_define_serialized_property serialize_column, "#{key}_id", default: default
|
122
150
|
|
123
151
|
define_method key.to_sym do
|
@@ -218,6 +246,25 @@ module Coaster
|
|
218
246
|
send("#{key}_without_callback=".to_sym, val)
|
219
247
|
end
|
220
248
|
end
|
249
|
+
|
250
|
+
define_method "#{key}_change".to_sym do
|
251
|
+
send("sprop_change", key)
|
252
|
+
end
|
253
|
+
define_method "#{key}_changed?".to_sym do
|
254
|
+
send("sprop_changed?", key)
|
255
|
+
end
|
256
|
+
define_method "#{key}_was".to_sym do
|
257
|
+
send("sprop_was", key)
|
258
|
+
end
|
259
|
+
define_method "#{key}_previous_change".to_sym do
|
260
|
+
send("sprop_previous_change", key)
|
261
|
+
end
|
262
|
+
define_method "#{key}_previously_changed?".to_sym do
|
263
|
+
send("sprop_previously_changed?", key)
|
264
|
+
end
|
265
|
+
define_method "#{key}_previously_was".to_sym do
|
266
|
+
send("sprop_previously_was", key)
|
267
|
+
end
|
221
268
|
end
|
222
269
|
end
|
223
270
|
end
|
data/lib/coaster/version.rb
CHANGED
data/test/support/models.rb
CHANGED
@@ -2,7 +2,7 @@ require 'coaster/serialized_properties'
|
|
2
2
|
require 'coaster/safe_yaml_serializer'
|
3
3
|
|
4
4
|
class User < ActiveRecord::Base
|
5
|
-
serialize :data, Coaster::SafeYamlSerializer
|
5
|
+
serialize :data, coder: Coaster::SafeYamlSerializer
|
6
6
|
extend Coaster::SerializedProperties
|
7
7
|
serialized_column :data
|
8
8
|
serialized_property :data, :appendix, default: {}
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "minitest/autorun"
|
4
|
+
require "test_helper"
|
5
|
+
require "action_view"
|
6
|
+
require "coaster/rails_ext/action_view/template/error"
|
7
|
+
|
8
|
+
module Coaster
|
9
|
+
class BadRequest < StandardError
|
10
|
+
def self.http_status = 400
|
11
|
+
end
|
12
|
+
|
13
|
+
class TestActionView < Minitest::Test
|
14
|
+
def test_http_status
|
15
|
+
begin
|
16
|
+
raise BadRequest
|
17
|
+
rescue BadRequest => e
|
18
|
+
template = ActionView::Template.new("Hello, World!", "test", ActionView::Template::Handlers::Raw, locals: [])
|
19
|
+
err = ActionView::Template::Error.new(template)
|
20
|
+
|
21
|
+
assert_equal err.cause, e
|
22
|
+
assert_equal err.http_status, e.http_status
|
23
|
+
assert_equal err.http_status, 400
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'minitest/autorun'
|
3
|
+
require 'coaster/core_ext/css_hash_string'
|
4
|
+
|
5
|
+
module Coaster
|
6
|
+
class TestCssHashString < Minitest::Test
|
7
|
+
def setup
|
8
|
+
end
|
9
|
+
|
10
|
+
def teardown
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_hash_to_style
|
14
|
+
assert_equal "font-size:12px;color:red", {"font-size" => '12px', color: 'red'}.to_css_style
|
15
|
+
assert_equal "font-size:12px;color:red", {font_size: '12px', color: 'red'}.to_css_style
|
16
|
+
assert_equal "font-size:12px;color:red", {font_size: '12px', color: 'red'}.with_indifferent_access.to_css_style
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_string_to_css_hash
|
20
|
+
assert_equal({"font-size" => '12px', "color" => 'red'}, "font-size: 12px; color: red".to_css_hash)
|
21
|
+
assert_equal({"font-size" => '12px', "color" => 'red'}, "font-size: 12px".to_css_hash(color: 'red'))
|
22
|
+
assert_equal({"font-size" => '12px', "color" => 'blue'}, "font-size: 12px; color: blue".to_css_hash(color: 'red'))
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'minitest/autorun'
|
3
|
+
require 'coaster/core_ext/deep_key_count'
|
4
|
+
|
5
|
+
module Coaster
|
6
|
+
class TestDeepKeyCount < Minitest::Test
|
7
|
+
def test_deep_key_count
|
8
|
+
assert_equal 0, {}.deep_key_count
|
9
|
+
assert_equal 1, {a: 1}.deep_key_count
|
10
|
+
assert_equal 2, {a: {b: 1}}.deep_key_count
|
11
|
+
assert_equal 3, {a: {b: 1, c: 2}}.deep_key_count
|
12
|
+
assert_equal 6, {a: {b: 1, c: 2, d: [1, 2]}}.deep_key_count
|
13
|
+
|
14
|
+
assert_equal 0, [].deep_key_count
|
15
|
+
assert_equal 1, [1].deep_key_count
|
16
|
+
assert_equal 2, [1, 2].deep_key_count
|
17
|
+
assert_equal 2, [1, {b: 2}].deep_key_count
|
18
|
+
assert_equal 3, [1, {b: 2}, 3].deep_key_count
|
19
|
+
assert_equal 4, [1, {b: 2}, 3, {c: 4}].deep_key_count
|
20
|
+
assert_equal 5, [1, {b: 2}, 3, [{c: 4}, 5]].deep_key_count
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_deep_key_count_array_is_element
|
24
|
+
assert_equal 1, {a: [1, 2]}.deep_key_count(array_is_element: true)
|
25
|
+
assert_equal 1, {a: [1, {b: 2}]}.deep_key_count(array_is_element: true)
|
26
|
+
|
27
|
+
assert_equal 2, [1, 2].deep_key_count(array_is_element: true)
|
28
|
+
assert_equal 2, [1, {b: 2}].deep_key_count(array_is_element: true)
|
29
|
+
|
30
|
+
assert_equal 3, [1, {b: 2}, 3].deep_key_count(array_is_element: true)
|
31
|
+
|
32
|
+
assert_equal 3, [1, {b: 2, c: [1, 2]}].deep_key_count(array_is_element: true)
|
33
|
+
assert_equal 3, [1, {b: 2}, [3, 4]].deep_key_count(array_is_element: true)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'minitest/autorun'
|
3
|
+
require 'coaster/core_ext/memory_size'
|
4
|
+
|
5
|
+
module Coaster
|
6
|
+
class TestMemorySize < Minitest::Test
|
7
|
+
class Some
|
8
|
+
attr_accessor :aa, :bb, :cc
|
9
|
+
end
|
10
|
+
|
11
|
+
def setup
|
12
|
+
end
|
13
|
+
|
14
|
+
def teardown
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_memory_size
|
18
|
+
h = {"aa" => 1, "bb" => [2, 3], "cc" => {"dd" => 4}}
|
19
|
+
# assert_equal 10, {"aa" => 1, "bb" => [2, 3], "cc" => {"dd" => 4}}.memory_size
|
20
|
+
assert_equal({nil => {nil => 160}, "aa" => 40, "bb" => 80, "cc" => 240}, h.memory_size(depth: 0))
|
21
|
+
assert_equal 520, h.memory_size_total
|
22
|
+
some = Some.new
|
23
|
+
some.aa = h
|
24
|
+
some.bb = [1, 2, 3]
|
25
|
+
some.cc = {"dd" => 4, "ee" => [5, 6]}
|
26
|
+
depth_0 = some.memory_size(depth: 0)
|
27
|
+
depth_1 = some.memory_size(depth: 1)
|
28
|
+
assert_equal({nil => 40, "@aa": 520, "@bb": 40, "@cc": 280}, depth_0)
|
29
|
+
assert_equal({nil => 40,
|
30
|
+
"@aa": {nil => {nil => 160}, "aa" => 40, "bb" => 80, "cc" => 240},
|
31
|
+
"@bb": {nil => {nil => 40}, 0 => 0, 1 => 0, 2 => 0},
|
32
|
+
"@cc": {nil => {nil => 160}, "dd" => 40, "ee" => 80}}, depth_1)
|
33
|
+
assert_equal 880, some.memory_size_total
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -11,6 +11,7 @@ module Coaster
|
|
11
11
|
|
12
12
|
def test_serialized
|
13
13
|
user = User.create(name: 'abc')
|
14
|
+
assert_equal([:appendix, :father_id, :mother_id], User.serialized_property_settings.keys)
|
14
15
|
user.init_appendix
|
15
16
|
assert_equal 0, user.appendix['test_key1']
|
16
17
|
assert_equal 0, user.appendix['test_key2']
|
@@ -23,7 +24,13 @@ module Coaster
|
|
23
24
|
assert_equal mother, user.mother
|
24
25
|
assert_equal mother.id, user.mother_id
|
25
26
|
assert_equal({"appendix"=>{"test_key1"=>0, "test_key2"=>0}, "father_id"=>father.id, "mother_id"=>mother.id}, user.data)
|
27
|
+
assert_equal({"appendix" => [nil, {"test_key1" => 0, "test_key2" => 0}], "father_id" => [nil, 2], "mother_id" => [nil, 3]}, user.sprop_changes)
|
28
|
+
assert_equal(true, user.mother_id_changed?)
|
29
|
+
assert_equal(nil, user.mother_id_was)
|
26
30
|
user.save!
|
31
|
+
assert_equal(false, user.mother_id_changed?)
|
32
|
+
assert_equal(true, user.mother_id_previously_changed?)
|
33
|
+
assert_equal(nil, user.mother_id_previously_was)
|
27
34
|
user = User.find(user.id)
|
28
35
|
assert_equal({"appendix"=>{"test_key1"=>0, "test_key2"=>0}, "father_id"=>father.id, "mother_id"=>mother.id}, user.data)
|
29
36
|
assert_equal mother, user.mother
|
data/test/test_standard_error.rb
CHANGED
@@ -211,25 +211,24 @@ module Coaster
|
|
211
211
|
detail_front = <<-LOG
|
212
212
|
[Coaster::TestStandardError::ExampleError] status:20
|
213
213
|
MESSAGE: Test example error (Coaster::TestStandardError::ExampleError) cause{Test sample error (Coaster::TestStandardError::SampleError)}
|
214
|
-
@attributes: {\"frog\"
|
214
|
+
@attributes: {\"frog\" => \"rams\", \"wat\" => \"cha\"}
|
215
215
|
@coaster: true
|
216
216
|
@digest_backtrace: #{e.digest_backtrace}
|
217
217
|
@digest_message: a8c7c1
|
218
218
|
@fingerprint: ["a8c7c1"]
|
219
|
-
@ins_var: [\"Coaster::TestStandardError::SampleError\", {\"h\"=>1}]
|
220
|
-
@ins_varr: {\"dd\"=>true}
|
219
|
+
@ins_var: [\"Coaster::TestStandardError::SampleError\", {\"h\" => 1}]
|
220
|
+
@ins_varr: {\"dd\" => true}
|
221
221
|
@level: \"error\"
|
222
222
|
@raven: {}
|
223
223
|
@tags: {}
|
224
224
|
@tkey: nil
|
225
225
|
BACKTRACE:
|
226
|
-
#{__FILE__}:193:in
|
227
|
-
#{__FILE__}:187:in `test_to_detail'
|
226
|
+
#{__FILE__}:193:in 'Coaster::TestStandardError#test_to_detail'
|
228
227
|
LOG
|
229
228
|
detail_cause_front = <<-LOG
|
230
229
|
CAUSE: [Coaster::TestStandardError::SampleError] status:10
|
231
230
|
MESSAGE: Test sample error (Coaster::TestStandardError::SampleError)
|
232
|
-
@attributes: {"frog"=>"rams"}
|
231
|
+
@attributes: {"frog" => "rams"}
|
233
232
|
@coaster: true
|
234
233
|
@digest_backtrace: #{e.cause.digest_backtrace}
|
235
234
|
@digest_message: cbe233
|
@@ -239,7 +238,7 @@ CAUSE: [Coaster::TestStandardError::SampleError] status:10
|
|
239
238
|
@tags: {}
|
240
239
|
@tkey: nil
|
241
240
|
BACKTRACE:
|
242
|
-
#{__FILE__}:188:in
|
241
|
+
#{__FILE__}:188:in 'Coaster::TestStandardError#test_to_detail'
|
243
242
|
LOG
|
244
243
|
assert detail.start_with?(detail_front)
|
245
244
|
cause_ix = (detail =~ /CAUSE/)
|
@@ -331,7 +330,7 @@ LOG
|
|
331
330
|
assert_equal 999999, e.to_hash['status']
|
332
331
|
assert_equal 500, e.to_hash['http_status']
|
333
332
|
assert_equal "standard error translation (#{e.digest_message} #{bt})", e.user_message
|
334
|
-
assert_match(/undefined local variable or method
|
333
|
+
assert_match(/undefined local variable or method 'aa'/, e.to_hash['message'])
|
335
334
|
end
|
336
335
|
|
337
336
|
def test_descriptions
|
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.4.
|
4
|
+
version: 1.4.30
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- buzz jung
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-06-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: oj
|
@@ -188,12 +188,17 @@ files:
|
|
188
188
|
- LICENSE
|
189
189
|
- README.md
|
190
190
|
- Rakefile
|
191
|
+
- bin/bundle
|
191
192
|
- bin/coaster
|
192
193
|
- lib/coaster.rb
|
193
194
|
- lib/coaster/cmd_options.rb
|
194
195
|
- lib/coaster/core_ext.rb
|
195
196
|
- lib/coaster/core_ext/array.rb
|
197
|
+
- lib/coaster/core_ext/css_hash_string.rb
|
196
198
|
- lib/coaster/core_ext/date.rb
|
199
|
+
- lib/coaster/core_ext/deep_key_count.rb
|
200
|
+
- lib/coaster/core_ext/hash.rb
|
201
|
+
- lib/coaster/core_ext/memory_size.rb
|
197
202
|
- lib/coaster/core_ext/month.rb
|
198
203
|
- lib/coaster/core_ext/object_translation.rb
|
199
204
|
- lib/coaster/core_ext/require_more.rb
|
@@ -207,6 +212,7 @@ files:
|
|
207
212
|
- lib/coaster/git/options.rb
|
208
213
|
- lib/coaster/git/repository.rb
|
209
214
|
- lib/coaster/rails_ext.rb
|
215
|
+
- lib/coaster/rails_ext/action_view/template/error.rb
|
210
216
|
- lib/coaster/rails_ext/active_record/errors.rb
|
211
217
|
- lib/coaster/rails_ext/active_support/backtrace_cleaner.rb
|
212
218
|
- lib/coaster/safe_yaml_serializer.rb
|
@@ -216,12 +222,16 @@ files:
|
|
216
222
|
- test/locales/en.yml
|
217
223
|
- test/support/models.rb
|
218
224
|
- test/support/schema.rb
|
225
|
+
- test/test_action_view.rb
|
219
226
|
- test/test_backtrace.rb
|
227
|
+
- test/test_css_hash_string.rb
|
220
228
|
- test/test_date.rb
|
229
|
+
- test/test_deep_key_count.rb
|
221
230
|
- test/test_git.rb
|
222
231
|
- test/test_git_options.rb
|
223
232
|
- test/test_git_repository.rb
|
224
233
|
- test/test_helper.rb
|
234
|
+
- test/test_memory_size.rb
|
225
235
|
- test/test_month.rb
|
226
236
|
- test/test_object_translation.rb
|
227
237
|
- test/test_serialized_property.rb
|
@@ -257,12 +267,16 @@ test_files:
|
|
257
267
|
- test/locales/en.yml
|
258
268
|
- test/support/models.rb
|
259
269
|
- test/support/schema.rb
|
270
|
+
- test/test_action_view.rb
|
260
271
|
- test/test_backtrace.rb
|
272
|
+
- test/test_css_hash_string.rb
|
261
273
|
- test/test_date.rb
|
274
|
+
- test/test_deep_key_count.rb
|
262
275
|
- test/test_git.rb
|
263
276
|
- test/test_git_options.rb
|
264
277
|
- test/test_git_repository.rb
|
265
278
|
- test/test_helper.rb
|
279
|
+
- test/test_memory_size.rb
|
266
280
|
- test/test_month.rb
|
267
281
|
- test/test_object_translation.rb
|
268
282
|
- test/test_serialized_property.rb
|