bizside 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +7 -0
  2. data/app/assets/images/jquery-treeTable/images/toggle-collapse-dark.png +0 -0
  3. data/app/assets/images/jquery-treeTable/images/toggle-collapse-light.png +0 -0
  4. data/app/assets/images/jquery-treeTable/images/toggle-expand-dark.png +0 -0
  5. data/app/assets/images/jquery-treeTable/images/toggle-expand-light.png +0 -0
  6. data/app/assets/javascripts/bizside.js +1 -0
  7. data/app/assets/javascripts/jquery-treeTable/jquery.treeTable.js +400 -0
  8. data/app/assets/stylesheets/bizside.css +3 -0
  9. data/app/assets/stylesheets/jquery-treeTable/jquery.treeTable.css.erb +55 -0
  10. data/lib/bizside/acl/access_control_utils.rb +36 -0
  11. data/lib/bizside/acl/available_helper.rb +65 -0
  12. data/lib/bizside/acl/controller_helper.rb +15 -0
  13. data/lib/bizside/acl.rb +6 -0
  14. data/lib/bizside/active_record_logger.rb +3 -0
  15. data/lib/bizside/audit/job_logger.rb +14 -0
  16. data/lib/bizside/audit/logger.rb +35 -0
  17. data/lib/bizside/audit_log.rb +158 -0
  18. data/lib/bizside/cache/entry.rb +112 -0
  19. data/lib/bizside/cache/file_store.rb +167 -0
  20. data/lib/bizside/cache/store.rb +237 -0
  21. data/lib/bizside/cache_util.rb +47 -0
  22. data/lib/bizside/cache_utils.rb +10 -0
  23. data/lib/bizside/carrierwave.rb +48 -0
  24. data/lib/bizside/config.rb +63 -0
  25. data/lib/bizside/configurations/mail.rb +37 -0
  26. data/lib/bizside/configurations/prefix.rb +25 -0
  27. data/lib/bizside/configurations/storage.rb +28 -0
  28. data/lib/bizside/coverage/launch.rb +25 -0
  29. data/lib/bizside/coverage/rcov_formatter.rb +13 -0
  30. data/lib/bizside/cron_validator.rb +62 -0
  31. data/lib/bizside/cucumber.rb +1 -0
  32. data/lib/bizside/engine.rb +4 -0
  33. data/lib/bizside/file_converter.rb +56 -0
  34. data/lib/bizside/file_uploader.rb +71 -0
  35. data/lib/bizside/gengou.rb +46 -0
  36. data/lib/bizside/gengou.yml +5 -0
  37. data/lib/bizside/hanaita_conf.rb +88 -0
  38. data/lib/bizside/implicit_ftps.rb +29 -0
  39. data/lib/bizside/itamae_conf.rb +186 -0
  40. data/lib/bizside/job_utils.rb +285 -0
  41. data/lib/bizside/log_analyzer.rb +122 -0
  42. data/lib/bizside/mailer.rb +56 -0
  43. data/lib/bizside/query_builder.rb +78 -0
  44. data/lib/bizside/railtie.rb +80 -0
  45. data/lib/bizside/record_has_warnings.rb +4 -0
  46. data/lib/bizside/resque.rb +141 -0
  47. data/lib/bizside/rsync.rb +40 -0
  48. data/lib/bizside/safe_pty.rb +17 -0
  49. data/lib/bizside/shib_utils.rb +18 -0
  50. data/lib/bizside/show_exceptions.rb +18 -0
  51. data/lib/bizside/sql_utils.rb +45 -0
  52. data/lib/bizside/string_io.rb +39 -0
  53. data/lib/bizside/string_utils.rb +157 -0
  54. data/lib/bizside/task_helper.rb +263 -0
  55. data/lib/bizside/tasks.rb +6 -0
  56. data/lib/bizside/test_help.rb +17 -0
  57. data/lib/bizside/uploader/content_type_validator.rb +39 -0
  58. data/lib/bizside/uploader/default_extensions.yml +15 -0
  59. data/lib/bizside/uploader/exif.rb +43 -0
  60. data/lib/bizside/uploader/extension_whitelist.rb +26 -0
  61. data/lib/bizside/uploader/filename_validator.rb +31 -0
  62. data/lib/bizside/user_agent/action_view/action_view_4.rb +56 -0
  63. data/lib/bizside/user_agent/action_view/use_variant.rb +4 -0
  64. data/lib/bizside/user_agent/action_view.rb +10 -0
  65. data/lib/bizside/user_agent/controller_helper.rb +51 -0
  66. data/lib/bizside/user_agent.rb +108 -0
  67. data/lib/bizside/validations.rb +8 -0
  68. data/lib/bizside/version.rb +3 -0
  69. data/lib/bizside/view_helper.rb +10 -0
  70. data/lib/bizside/warning.rb +24 -0
  71. data/lib/bizside/yes.rb +16 -0
  72. data/lib/bizside.rb +96 -0
  73. data/lib/cron_validator.rb +3 -0
  74. data/lib/gengou.rb +3 -0
  75. data/lib/job_utils.rb +3 -0
  76. data/lib/query_builder.rb +3 -0
  77. data/lib/record_has_warnings.rb +3 -0
  78. data/lib/sql_utils.rb +3 -0
  79. data/lib/string_utils.rb +3 -0
  80. data/lib/user_agent.rb +3 -0
  81. data/lib/yes.rb +3 -0
  82. data/rails/locales/ja.yml +12 -0
  83. data/validations/collection_presence_validator.rb +15 -0
  84. data/validations/email_validator.rb +1 -0
  85. data/validations/ip_address_validator.rb +22 -0
  86. data/validations/tel_validator.rb +28 -0
  87. data/validations/url_validator.rb +30 -0
  88. data/validations/zip_validator.rb +35 -0
  89. metadata +467 -0
@@ -0,0 +1,158 @@
1
+ require_relative 'audit/logger'
2
+
3
+ module Bizside
4
+ class AuditLog
5
+
6
+ def initialize(app)
7
+ @app = app
8
+ end
9
+
10
+ def call(env)
11
+ start = Time.now.strftime('%Y-%m-%dT%H:%M:%S.%3N%z')
12
+ @status, @headers, @response = @app.call(env)
13
+ stop = Time.now.strftime('%Y-%m-%dT%H:%M:%S.%3N%z')
14
+ exception = env[Bizside::ShowExceptions::BIZSIDE_EXCEPTION_ENV_KEY]
15
+
16
+ if env['BIZSIDE_SUPPRESS_AUDIT']
17
+ return @status, @headers, @response
18
+ end
19
+
20
+ if Bizside.rails_env&.development?
21
+ return @status, @headers, @response if env['REQUEST_URI'] =~ /\/[^\/]+\/assets\/.*/
22
+ elsif Bizside.rails_env&.test?
23
+ return @status, @headers, @response
24
+ end
25
+
26
+ info = build_loginfo(env, start, stop, @status, exception)
27
+ logger.record(info)
28
+
29
+ return @status, @headers, @response
30
+ end
31
+
32
+ private
33
+
34
+ def logger
35
+ @logger ||= Bizside::Audit::Logger.logger
36
+ end
37
+
38
+ def build_loginfo(env, start, stop, status, exception)
39
+ info = {
40
+ time: start,
41
+ add_on_name: detect_add_on_name(env),
42
+ feature: detect_feature(env),
43
+ action: detect_action(env),
44
+ data: detect_data(env),
45
+ interactive: detect_interactive(env),
46
+ company: detect_company(env),
47
+ user: detect_user(env),
48
+ employee_code: detect_employee_code(env),
49
+ department: detect_department(env),
50
+ project: detect_project(env),
51
+ server_name: env['SERVER_NAME'],
52
+ server_address: ENV['HOSTNAME'] || env['SERVER_ADDR'], # nginx と apache で異なる
53
+ server_port: env['SERVER_PORT'],
54
+ scheme: env['rack.url_scheme'],
55
+ path: env['PATH_INFO'],
56
+ referrer: env['HTTP_REFERER'],
57
+ request_method: env['REQUEST_METHOD'],
58
+ request_uri: env['BIZSIDE_REQUEST_URI'].presence || env['REQUEST_URI'],
59
+ remote_address: env['REMOTE_ADDR'],
60
+ status: status,
61
+ started_at: start,
62
+ finished_at: stop,
63
+ device: detect_device(env),
64
+ user_agent: detect_user_agent(env),
65
+ exception: detect_exception(exception),
66
+ exception_message: detect_exception_message(exception),
67
+ exception_backtrace: detect_exception_backtrace(exception)
68
+ }
69
+
70
+ info
71
+ end
72
+
73
+ def detect_company(env)
74
+ env['BIZSIDE_COMPANY']
75
+ end
76
+
77
+ def detect_user(env)
78
+ ret = env['BIZSIDE_USER']
79
+ ret ||= Bizside::ShibUtils._get_bizside_user(env)
80
+
81
+ if ret.to_s.empty?
82
+ if defined?(Devise)
83
+ warden = env['warden']
84
+ if warden.authenticate?
85
+ auth_user = warden.send(warden.config[:default_scope])
86
+ ret = auth_user.email
87
+ end
88
+ end
89
+ end
90
+
91
+ ret
92
+ end
93
+
94
+ def detect_add_on_name(env)
95
+ ret = env['BIZSIDE_ADD_ON_NAME']
96
+ ret ||= Bizside.config.add_on_name
97
+ ret
98
+ end
99
+
100
+ def detect_feature(env)
101
+ env['BIZSIDE_FEATURE']
102
+ end
103
+
104
+ def detect_action(env)
105
+ env['BIZSIDE_ACTION']
106
+ end
107
+
108
+ def detect_data(env)
109
+ env['BIZSIDE_DATA']
110
+ end
111
+
112
+ def detect_interactive(env)
113
+ env['BIZSIDE_INTERACTIVE']
114
+ end
115
+
116
+ def detect_department(env)
117
+ env['BIZSIDE_DEPARTMENT']
118
+ end
119
+
120
+ def detect_project(env)
121
+ env['BIZSIDE_PROJECT']
122
+ end
123
+
124
+ def detect_device(env)
125
+ env['BIZSIDE_DEVICE']
126
+ end
127
+
128
+ def detect_user_agent(env)
129
+ ret = env['BIZSIDE_USER_AGENT']
130
+ ret ||= env['HTTP_USER_AGENT']
131
+ ret
132
+ end
133
+
134
+ def detect_employee_code(env)
135
+ ret = env['BIZSIDE_EMPLOYEE_CODE']
136
+ ret
137
+ end
138
+
139
+ def detect_exception(exception)
140
+ return '' unless exception
141
+
142
+ exception.class.name
143
+ end
144
+
145
+ def detect_exception_message(exception)
146
+ return '' unless exception
147
+
148
+ exception.to_s
149
+ end
150
+
151
+ def detect_exception_backtrace(exception)
152
+ return '' unless exception
153
+
154
+ exception.backtrace.join("\n")
155
+ end
156
+
157
+ end
158
+ end
@@ -0,0 +1,112 @@
1
+ module Bizside
2
+ module Cache
3
+ class Entry
4
+ DEFAULT_COMPRESS_LIMIT = 16.kilobytes
5
+
6
+ def initialize(value, options = {})
7
+ if should_compress?(value, options)
8
+ @value = compress(value)
9
+ @compressed = true
10
+ else
11
+ @value = value
12
+ end
13
+
14
+ @created_at = Time.now.to_f
15
+ @expires_in = options[:expires_in]
16
+ @expires_in = @expires_in.to_f if @expires_in
17
+ end
18
+
19
+ def value
20
+ convert_version_4beta1_entry! if defined?(@v)
21
+ compressed? ? uncompress(@value) : @value
22
+ end
23
+
24
+ def expired?
25
+ convert_version_4beta1_entry! if defined?(@v)
26
+ @expires_in && @created_at + @expires_in <= Time.now.to_f
27
+ end
28
+
29
+ def expires_at
30
+ @expires_in ? @created_at + @expires_in : nil
31
+ end
32
+
33
+ def expires_at=(value)
34
+ if value
35
+ @expires_in = value.to_f - @created_at
36
+ else
37
+ @expires_in = nil
38
+ end
39
+ end
40
+
41
+ def size
42
+ if defined?(@s)
43
+ @s
44
+ else
45
+ case value
46
+ when NilClass
47
+ 0
48
+ when String
49
+ @value.bytesize
50
+ else
51
+ @s = Marshal.dump(@value).bytesize
52
+ end
53
+ end
54
+ end
55
+
56
+ def dup_value!
57
+ convert_version_4beta1_entry! if defined?(@v)
58
+
59
+ if @value && !compressed? && !(@value.is_a?(Numeric) || @value == true || @value == false)
60
+ if @value.is_a?(String)
61
+ @value = @value.dup
62
+ else
63
+ @value = Marshal.load(Marshal.dump(@value))
64
+ end
65
+ end
66
+ end
67
+
68
+ private
69
+
70
+ def should_compress?(value, options)
71
+ if value && options[:compress]
72
+ compress_threshold = options[:compress_threshold] || DEFAULT_COMPRESS_LIMIT
73
+ serialized_value_size = (value.is_a?(String) ? value : Marshal.dump(value)).bytesize
74
+
75
+ return true if serialized_value_size >= compress_threshold
76
+ end
77
+
78
+ false
79
+ end
80
+
81
+ def compressed?
82
+ defined?(@compressed) ? @compressed : false
83
+ end
84
+
85
+ def compress(value)
86
+ Zlib::Deflate.deflate(Marshal.dump(value))
87
+ end
88
+
89
+ def uncompress(value)
90
+ Marshal.load(Zlib::Inflate.inflate(value))
91
+ end
92
+
93
+ def convert_version_4beta1_entry!
94
+ if defined?(@v)
95
+ @value = @v
96
+ remove_instance_variable(:@v)
97
+ end
98
+
99
+ if defined?(@c)
100
+ @compressed = @c
101
+ remove_instance_variable(:@c)
102
+ end
103
+
104
+ if defined?(@x) && @x
105
+ @created_at ||= Time.now.to_f
106
+ @expires_in = @x - @created_at
107
+ remove_instance_variable(:@x)
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,167 @@
1
+ require 'bizside/cache/store'
2
+
3
+ module Bizside
4
+ module Cache
5
+ class FileStore < Store
6
+
7
+ attr_reader :cache_path
8
+
9
+ DIR_FORMATTER = "%03X"
10
+ FILENAME_MAX_SIZE = 228 # max filename size on file system is 255, minus room for timestamp and random characters appended by Tempfile (used by atomic write)
11
+ FILEPATH_MAX_SIZE = 900 # max is 1024, plus some room
12
+ EXCLUDED_DIRS = ['.', '..'].freeze
13
+
14
+ def initialize(cache_path, options = nil)
15
+ super(options)
16
+ @cache_path = cache_path.to_s
17
+ end
18
+
19
+ def clear(options = nil)
20
+ root_dirs = Dir.entries(cache_path).reject {|f| (EXCLUDED_DIRS + [".gitkeep"]).include?(f)}
21
+ FileUtils.rm_r(root_dirs.collect{|f| File.join(cache_path, f)})
22
+ end
23
+
24
+ def cleanup(options = nil)
25
+ options = merged_options(options)
26
+ search_dir(cache_path) do |fname|
27
+ key = file_path_key(fname)
28
+ entry = read_entry(key, options)
29
+ delete_entry(key, options) if entry && entry.expired?
30
+ end
31
+ end
32
+
33
+ def increment(name, amount = 1, options = nil)
34
+ modify_value(name, amount, options)
35
+ end
36
+
37
+ def decrement(name, amount = 1, options = nil)
38
+ modify_value(name, -amount, options)
39
+ end
40
+
41
+ def delete_matched(matcher, options = nil)
42
+ options = merged_options(options)
43
+ instrument(:delete_matched, matcher.inspect) do
44
+ matcher = key_matcher(matcher, options)
45
+ search_dir(cache_path) do |path|
46
+ key = file_path_key(path)
47
+ delete_entry(key, options) if key.match(matcher)
48
+ end
49
+ end
50
+ end
51
+
52
+ protected
53
+
54
+ def read_entry(key, options)
55
+ file_name = key_file_path(key)
56
+ if File.exist?(file_name)
57
+ File.open(file_name) { |f| Marshal.load(f) }
58
+ end
59
+ rescue => e
60
+ nil
61
+ end
62
+
63
+ def write_entry(key, entry, options)
64
+ file_name = key_file_path(key)
65
+ return false if options[:unless_exist] && File.exist?(file_name)
66
+ ensure_cache_path(File.dirname(file_name))
67
+ File.atomic_write(file_name, cache_path) {|f| Marshal.dump(entry, f)}
68
+ true
69
+ end
70
+
71
+ def delete_entry(key, options)
72
+ file_name = key_file_path(key)
73
+ if File.exist?(file_name)
74
+ begin
75
+ File.delete(file_name)
76
+ delete_empty_directories(File.dirname(file_name))
77
+ true
78
+ rescue => e
79
+ raise e if File.exist?(file_name)
80
+ false
81
+ end
82
+ end
83
+ end
84
+
85
+ private
86
+
87
+ def lock_file(file_name, &block)
88
+ if File.exist?(file_name)
89
+ File.open(file_name, 'r+') do |f|
90
+ begin
91
+ f.flock File::LOCK_EX
92
+ yield
93
+ ensure
94
+ f.flock File::LOCK_UN
95
+ end
96
+ end
97
+ else
98
+ yield
99
+ end
100
+ end
101
+
102
+ def key_file_path(key)
103
+ if key.size > FILEPATH_MAX_SIZE
104
+ key = Digest::MD5.hexdigest(key)
105
+ end
106
+
107
+ fname = URI.encode_www_form_component(key)
108
+ hash = Zlib.adler32(fname)
109
+ hash, dir_1 = hash.divmod(0x1000)
110
+ dir_2 = hash.modulo(0x1000)
111
+ fname_paths = []
112
+
113
+ begin
114
+ fname_paths << fname[0, FILENAME_MAX_SIZE]
115
+ fname = fname[FILENAME_MAX_SIZE..-1]
116
+ end until fname.blank?
117
+
118
+ File.join(cache_path, DIR_FORMATTER % dir_1, DIR_FORMATTER % dir_2, *fname_paths)
119
+ end
120
+
121
+ def file_path_key(path)
122
+ fname = path[cache_path.to_s.size..-1].split(File::SEPARATOR, 4).last
123
+ URI.decode_www_form_component(fname, Encoding::UTF_8)
124
+ end
125
+
126
+ def delete_empty_directories(dir)
127
+ return if File.realpath(dir) == File.realpath(cache_path)
128
+ if Dir.entries(dir).reject {|f| EXCLUDED_DIRS.include?(f)}.empty?
129
+ Dir.delete(dir) rescue nil
130
+ delete_empty_directories(File.dirname(dir))
131
+ end
132
+ end
133
+
134
+ def ensure_cache_path(path)
135
+ FileUtils.makedirs(path) unless File.exist?(path)
136
+ end
137
+
138
+ def search_dir(dir, &callback)
139
+ return if !File.exist?(dir)
140
+ Dir.foreach(dir) do |d|
141
+ next if EXCLUDED_DIRS.include?(d)
142
+ name = File.join(dir, d)
143
+ if File.directory?(name)
144
+ search_dir(name, &callback)
145
+ else
146
+ callback.call name
147
+ end
148
+ end
149
+ end
150
+
151
+ def modify_value(name, amount, options)
152
+ file_name = key_file_path(namespaced_key(name, options))
153
+
154
+ lock_file(file_name) do
155
+ options = merged_options(options)
156
+
157
+ if num = read(name, options)
158
+ num = num.to_i + amount
159
+ write(name, num, options)
160
+ num
161
+ end
162
+ end
163
+ end
164
+
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,237 @@
1
+ require 'bizside/cache/entry'
2
+
3
+ module Bizside
4
+ module Cache
5
+ class Store
6
+
7
+ attr_reader :options
8
+
9
+ def initialize(options = nil)
10
+ @options = options ? options.dup : {}
11
+ end
12
+
13
+ def fetch(name, options = nil)
14
+ if block_given?
15
+ options = merged_options(options)
16
+ key = namespaced_key(name, options)
17
+
18
+ cached_entry = find_cached_entry(key, name, options) unless options[:force]
19
+ entry = handle_expired_entry(cached_entry, key, options)
20
+
21
+ if entry
22
+ get_entry_value(entry, name, options)
23
+ else
24
+ save_block_result_to_cache(name, options) { |_name| yield _name }
25
+ end
26
+ else
27
+ read(name, options)
28
+ end
29
+ end
30
+
31
+ def read(name, options = nil)
32
+ options = merged_options(options)
33
+ key = namespaced_key(name, options)
34
+ instrument(:read, name, options) do |payload|
35
+ entry = read_entry(key, options)
36
+ if entry
37
+ if entry.expired?
38
+ delete_entry(key, options)
39
+ payload[:hit] = false if payload
40
+ nil
41
+ else
42
+ payload[:hit] = true if payload
43
+ entry.value
44
+ end
45
+ else
46
+ payload[:hit] = false if payload
47
+ nil
48
+ end
49
+ end
50
+ end
51
+
52
+ def read_multi(*names)
53
+ options = names.extract_options!
54
+ options = merged_options(options)
55
+ results = {}
56
+ names.each do |name|
57
+ key = namespaced_key(name, options)
58
+ entry = read_entry(key, options)
59
+ if entry
60
+ if entry.expired?
61
+ delete_entry(key, options)
62
+ else
63
+ results[name] = entry.value
64
+ end
65
+ end
66
+ end
67
+ results
68
+ end
69
+
70
+ def fetch_multi(*names)
71
+ options = names.extract_options!
72
+ options = merged_options(options)
73
+ results = read_multi(*names, options)
74
+
75
+ names.each_with_object({}) do |name, memo|
76
+ memo[name] = results.fetch(name) do
77
+ value = yield name
78
+ write(name, value, options)
79
+ value
80
+ end
81
+ end
82
+ end
83
+
84
+ def write(name, value, options = nil)
85
+ options = merged_options(options)
86
+
87
+ instrument(:write, name, options) do
88
+ entry = Bizside::Cache::Entry.new(value, options)
89
+ write_entry(namespaced_key(name, options), entry, options)
90
+ end
91
+ end
92
+
93
+ def delete(name, options = nil)
94
+ options = merged_options(options)
95
+
96
+ instrument(:delete, name) do
97
+ delete_entry(namespaced_key(name, options), options)
98
+ end
99
+ end
100
+
101
+ def exist?(name, options = nil)
102
+ options = merged_options(options)
103
+
104
+ instrument(:exist?, name) do
105
+ entry = read_entry(namespaced_key(name, options), options)
106
+ (entry && !entry.expired?) || false
107
+ end
108
+ end
109
+
110
+ def delete_matched(matcher, options = nil)
111
+ raise NotImplementedError.new("does not support delete_matched")
112
+ end
113
+
114
+ def increment(name, amount = 1, options = nil)
115
+ raise NotImplementedError.new("does not support increment")
116
+ end
117
+
118
+ def decrement(name, amount = 1, options = nil)
119
+ raise NotImplementedError.new("does not support decrement")
120
+ end
121
+
122
+ def cleanup(options = nil)
123
+ raise NotImplementedError.new("does not support cleanup")
124
+ end
125
+
126
+ def clear(options = nil)
127
+ raise NotImplementedError.new("does not support clear")
128
+ end
129
+
130
+ protected
131
+
132
+ def key_matcher(pattern, options)
133
+ prefix = options[:namespace].is_a?(Proc) ? options[:namespace].call : options[:namespace]
134
+ if prefix
135
+ source = pattern.source
136
+ if source.start_with?('^')
137
+ source = source[1, source.length]
138
+ else
139
+ source = ".*#{source[0, source.length]}"
140
+ end
141
+ Regexp.new("^#{Regexp.escape(prefix)}:#{source}", pattern.options)
142
+ else
143
+ pattern
144
+ end
145
+ end
146
+
147
+ def read_entry(key, options)
148
+ raise NotImplementedError.new
149
+ end
150
+
151
+ def write_entry(key, entry, options)
152
+ raise NotImplementedError.new
153
+ end
154
+
155
+ def delete_entry(key, options)
156
+ raise NotImplementedError.new
157
+ end
158
+
159
+ private
160
+
161
+ def merged_options(call_options)
162
+ if call_options
163
+ options.merge(call_options)
164
+ else
165
+ options.dup
166
+ end
167
+ end
168
+
169
+ def expanded_key(key)
170
+ return key.cache_key.to_s if key.respond_to?(:cache_key)
171
+
172
+ case key
173
+ when Array
174
+ if key.size > 1
175
+ key = key.collect{|element| expanded_key(element)}
176
+ else
177
+ key = key.first
178
+ end
179
+ when Hash
180
+ key = key.sort_by { |k,_| k.to_s }.collect{|k,v| "#{k}=#{v}"}
181
+ end
182
+
183
+ key.to_param
184
+ end
185
+
186
+ def namespaced_key(key, options)
187
+ key = expanded_key(key)
188
+ namespace = options[:namespace] if options
189
+ prefix = namespace.is_a?(Proc) ? namespace.call : namespace
190
+ key = "#{prefix}:#{key}" if prefix
191
+ key
192
+ end
193
+
194
+ def instrument(operation, key, options = nil)
195
+ payload = { :key => key }
196
+ payload.merge!(options) if options.is_a?(Hash)
197
+ ActiveSupport::Notifications.instrument("cache_#{operation}.active_support", payload){ yield(payload) }
198
+ end
199
+
200
+ def find_cached_entry(key, name, options)
201
+ instrument(:read, name, options) do |payload|
202
+ payload[:super_operation] = :fetch if payload
203
+ read_entry(key, options)
204
+ end
205
+ end
206
+
207
+ def handle_expired_entry(entry, key, options)
208
+ if entry && entry.expired?
209
+ race_ttl = options[:race_condition_ttl].to_i
210
+ if (race_ttl > 0) && (Time.now.to_f - entry.expires_at <= race_ttl)
211
+ entry.expires_at = Time.now + race_ttl
212
+ write_entry(key, entry, :expires_in => race_ttl * 2)
213
+ else
214
+ delete_entry(key, options)
215
+ end
216
+ entry = nil
217
+ end
218
+ entry
219
+ end
220
+
221
+ def get_entry_value(entry, name, options)
222
+ instrument(:fetch_hit, name, options) { |payload| }
223
+ entry.value
224
+ end
225
+
226
+ def save_block_result_to_cache(name, options)
227
+ result = instrument(:generate, name, options) do |payload|
228
+ yield(name)
229
+ end
230
+
231
+ write(name, result, options)
232
+ result
233
+ end
234
+
235
+ end
236
+ end
237
+ end
@@ -0,0 +1,47 @@
1
+ module Bizside
2
+ module CacheUtil
3
+
4
+ def fetch(key, options = {})
5
+ if block_given?
6
+ action = cache.exist?(key) ? 'READ' : 'WRITE'
7
+ output_log "#{action} CACHE: #{key}"
8
+ cache.fetch(key, options) do
9
+ yield
10
+ end
11
+ else
12
+ output_log "READ CACHE: #{key}"
13
+ cache.fetch(key, options)
14
+ end
15
+ end
16
+
17
+ def delete(key)
18
+ output_log "CLEAR CACHE: #{key}"
19
+ cache.delete(key)
20
+ end
21
+
22
+ def delete_matched(matcher)
23
+ output_log "CLEAR CACHE: #{matcher}"
24
+ cache.delete_matched(matcher)
25
+ end
26
+
27
+ def clear(options = nil)
28
+ output_log "CLEAR ALL CACHE"
29
+ cache.clear(options)
30
+ end
31
+
32
+ def cache
33
+ raise 'サブクラスで実装'
34
+ end
35
+
36
+ private
37
+
38
+ def output_log message
39
+ if defined?(Rails) && Rails.logger
40
+ Rails.logger.info message
41
+ else
42
+ puts message
43
+ end
44
+ end
45
+
46
+ end
47
+ end