sidekiq 5.2.5 → 6.0.3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of sidekiq might be problematic. Click here for more details.

Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +82 -0
  3. data/.gitignore +0 -2
  4. data/.standard.yml +20 -0
  5. data/6.0-Upgrade.md +72 -0
  6. data/COMM-LICENSE +11 -9
  7. data/Changes.md +136 -0
  8. data/Ent-2.0-Upgrade.md +37 -0
  9. data/Ent-Changes.md +32 -1
  10. data/Gemfile +12 -17
  11. data/Gemfile.lock +196 -0
  12. data/Pro-5.0-Upgrade.md +25 -0
  13. data/Pro-Changes.md +26 -2
  14. data/README.md +19 -31
  15. data/Rakefile +5 -4
  16. data/bin/sidekiqload +33 -25
  17. data/bin/sidekiqmon +8 -0
  18. data/lib/generators/sidekiq/templates/worker_test.rb.erb +1 -1
  19. data/lib/generators/sidekiq/worker_generator.rb +20 -12
  20. data/lib/sidekiq/api.rb +230 -214
  21. data/lib/sidekiq/cli.rb +111 -174
  22. data/lib/sidekiq/client.rb +55 -46
  23. data/lib/sidekiq/delay.rb +5 -6
  24. data/lib/sidekiq/exception_handler.rb +10 -12
  25. data/lib/sidekiq/extensions/action_mailer.rb +10 -20
  26. data/lib/sidekiq/extensions/active_record.rb +9 -7
  27. data/lib/sidekiq/extensions/class_methods.rb +9 -7
  28. data/lib/sidekiq/extensions/generic_proxy.rb +4 -4
  29. data/lib/sidekiq/fetch.rb +11 -12
  30. data/lib/sidekiq/job_logger.rb +45 -7
  31. data/lib/sidekiq/job_retry.rb +71 -60
  32. data/lib/sidekiq/launcher.rb +57 -51
  33. data/lib/sidekiq/logger.rb +165 -0
  34. data/lib/sidekiq/manager.rb +7 -9
  35. data/lib/sidekiq/middleware/chain.rb +14 -4
  36. data/lib/sidekiq/middleware/i18n.rb +5 -7
  37. data/lib/sidekiq/monitor.rb +133 -0
  38. data/lib/sidekiq/paginator.rb +18 -14
  39. data/lib/sidekiq/processor.rb +83 -75
  40. data/lib/sidekiq/rails.rb +23 -29
  41. data/lib/sidekiq/redis_connection.rb +31 -37
  42. data/lib/sidekiq/scheduled.rb +28 -29
  43. data/lib/sidekiq/testing/inline.rb +2 -1
  44. data/lib/sidekiq/testing.rb +34 -23
  45. data/lib/sidekiq/util.rb +17 -16
  46. data/lib/sidekiq/version.rb +2 -1
  47. data/lib/sidekiq/web/action.rb +14 -10
  48. data/lib/sidekiq/web/application.rb +64 -66
  49. data/lib/sidekiq/web/helpers.rb +89 -71
  50. data/lib/sidekiq/web/router.rb +17 -14
  51. data/lib/sidekiq/web.rb +41 -49
  52. data/lib/sidekiq/worker.rb +129 -97
  53. data/lib/sidekiq.rb +61 -42
  54. data/sidekiq.gemspec +16 -16
  55. data/web/assets/javascripts/dashboard.js +4 -23
  56. data/web/assets/stylesheets/application-dark.css +125 -0
  57. data/web/assets/stylesheets/application.css +9 -0
  58. data/web/assets/stylesheets/bootstrap.css +1 -1
  59. data/web/locales/de.yml +14 -2
  60. data/web/locales/ja.yml +2 -1
  61. data/web/views/_job_info.erb +2 -1
  62. data/web/views/busy.erb +4 -1
  63. data/web/views/dead.erb +2 -2
  64. data/web/views/layout.erb +1 -0
  65. data/web/views/morgue.erb +4 -1
  66. data/web/views/queue.erb +10 -1
  67. data/web/views/queues.erb +1 -1
  68. data/web/views/retries.erb +4 -1
  69. data/web/views/retry.erb +2 -2
  70. data/web/views/scheduled.erb +4 -1
  71. metadata +21 -32
  72. data/.travis.yml +0 -17
  73. data/Appraisals +0 -9
  74. data/bin/sidekiqctl +0 -237
  75. data/gemfiles/rails_4.gemfile +0 -31
  76. data/gemfiles/rails_5.gemfile +0 -31
  77. data/lib/sidekiq/core_ext.rb +0 -1
  78. data/lib/sidekiq/logging.rb +0 -122
  79. data/lib/sidekiq/middleware/server/active_record.rb +0 -23
@@ -1,18 +1,19 @@
1
1
  # frozen_string_literal: true
2
- require 'rack'
2
+
3
+ require "rack"
3
4
 
4
5
  module Sidekiq
5
6
  module WebRouter
6
- GET = 'GET'
7
- DELETE = 'DELETE'
8
- POST = 'POST'
9
- PUT = 'PUT'
10
- PATCH = 'PATCH'
11
- HEAD = 'HEAD'
7
+ GET = "GET"
8
+ DELETE = "DELETE"
9
+ POST = "POST"
10
+ PUT = "PUT"
11
+ PATCH = "PATCH"
12
+ HEAD = "HEAD"
12
13
 
13
- ROUTE_PARAMS = 'rack.route_params'
14
- REQUEST_METHOD = 'REQUEST_METHOD'
15
- PATH_INFO = 'PATH_INFO'
14
+ ROUTE_PARAMS = "rack.route_params"
15
+ REQUEST_METHOD = "REQUEST_METHOD"
16
+ PATH_INFO = "PATH_INFO"
16
17
 
17
18
  def get(path, &block)
18
19
  route(GET, path, &block)
@@ -35,7 +36,7 @@ module Sidekiq
35
36
  end
36
37
 
37
38
  def route(method, path, &block)
38
- @routes ||= { GET => [], POST => [], PUT => [], PATCH => [], DELETE => [], HEAD => [] }
39
+ @routes ||= {GET => [], POST => [], PUT => [], PATCH => [], DELETE => [], HEAD => []}
39
40
 
40
41
  @routes[method] << WebRoute.new(method, path, block)
41
42
  @routes[HEAD] << WebRoute.new(method, path, block) if method == GET
@@ -50,7 +51,8 @@ module Sidekiq
50
51
  path_info = "/" if path_info == ""
51
52
 
52
53
  @routes[request_method].each do |route|
53
- if params = route.match(request_method, path_info)
54
+ params = route.match(request_method, path_info)
55
+ if params
54
56
  env[ROUTE_PARAMS] = params
55
57
 
56
58
  return WebAction.new(env, route.block)
@@ -77,7 +79,7 @@ module Sidekiq
77
79
  end
78
80
 
79
81
  def compile
80
- if pattern.match(NAMED_SEGMENTS_PATTERN)
82
+ if pattern.match?(NAMED_SEGMENTS_PATTERN)
81
83
  p = pattern.gsub(NAMED_SEGMENTS_PATTERN, '/\1(?<\2>[^$/]+)')
82
84
 
83
85
  Regexp.new("\\A#{p}\\Z")
@@ -91,7 +93,8 @@ module Sidekiq
91
93
  when String
92
94
  {} if path == matcher
93
95
  else
94
- if path_match = path.match(matcher)
96
+ path_match = path.match(matcher)
97
+ if path_match
95
98
  Hash[path_match.names.map(&:to_sym).zip(path_match.captures)]
96
99
  end
97
100
  end
data/lib/sidekiq/web.rb CHANGED
@@ -1,20 +1,21 @@
1
1
  # frozen_string_literal: true
2
- require 'erb'
3
2
 
4
- require 'sidekiq'
5
- require 'sidekiq/api'
6
- require 'sidekiq/paginator'
7
- require 'sidekiq/web/helpers'
3
+ require "erb"
8
4
 
9
- require 'sidekiq/web/router'
10
- require 'sidekiq/web/action'
11
- require 'sidekiq/web/application'
5
+ require "sidekiq"
6
+ require "sidekiq/api"
7
+ require "sidekiq/paginator"
8
+ require "sidekiq/web/helpers"
12
9
 
13
- require 'rack/protection'
10
+ require "sidekiq/web/router"
11
+ require "sidekiq/web/action"
12
+ require "sidekiq/web/application"
14
13
 
15
- require 'rack/builder'
16
- require 'rack/file'
17
- require 'rack/session/cookie'
14
+ require "rack/protection"
15
+
16
+ require "rack/builder"
17
+ require "rack/file"
18
+ require "rack/session/cookie"
18
19
 
19
20
  module Sidekiq
20
21
  class Web
@@ -25,12 +26,12 @@ module Sidekiq
25
26
  ASSETS = "#{ROOT}/assets"
26
27
 
27
28
  DEFAULT_TABS = {
28
- "Dashboard" => '',
29
- "Busy" => 'busy',
30
- "Queues" => 'queues',
31
- "Retries" => 'retries',
32
- "Scheduled" => 'scheduled',
33
- "Dead" => 'morgue',
29
+ "Dashboard" => "",
30
+ "Busy" => "busy",
31
+ "Queues" => "queues",
32
+ "Retries" => "retries",
33
+ "Scheduled" => "scheduled",
34
+ "Dead" => "morgue",
34
35
  }
35
36
 
36
37
  class << self
@@ -64,11 +65,11 @@ module Sidekiq
64
65
  end
65
66
 
66
67
  def enable(*opts)
67
- opts.each {|key| set(key, true) }
68
+ opts.each { |key| set(key, true) }
68
69
  end
69
70
 
70
71
  def disable(*opts)
71
- opts.each {|key| set(key, false) }
72
+ opts.each { |key| set(key, false) }
72
73
  end
73
74
 
74
75
  # Helper for the Sinatra syntax: Sidekiq::Web.set(:session_secret, Rails.application.secrets...)
@@ -81,10 +82,10 @@ module Sidekiq
81
82
  end
82
83
 
83
84
  def self.inherited(child)
84
- child.app_url = self.app_url
85
- child.session_secret = self.session_secret
86
- child.redis_pool = self.redis_pool
87
- child.sessions = self.sessions
85
+ child.app_url = app_url
86
+ child.session_secret = session_secret
87
+ child.redis_pool = redis_pool
88
+ child.sessions = sessions
88
89
  end
89
90
 
90
91
  def settings
@@ -113,11 +114,11 @@ module Sidekiq
113
114
  end
114
115
 
115
116
  def enable(*opts)
116
- opts.each {|key| set(key, true) }
117
+ opts.each { |key| set(key, true) }
117
118
  end
118
119
 
119
120
  def disable(*opts)
120
- opts.each {|key| set(key, false) }
121
+ opts.each { |key| set(key, false) }
121
122
  end
122
123
 
123
124
  def set(attribute, value)
@@ -145,28 +146,28 @@ module Sidekiq
145
146
  private
146
147
 
147
148
  def using?(middleware)
148
- middlewares.any? do |(m,_)|
149
- m.kind_of?(Array) && (m[0] == middleware || m[0].kind_of?(middleware))
149
+ middlewares.any? do |(m, _)|
150
+ m.is_a?(Array) && (m[0] == middleware || m[0].is_a?(middleware))
150
151
  end
151
152
  end
152
153
 
153
154
  def build_sessions
154
155
  middlewares = self.middlewares
155
156
 
156
- unless using?(::Rack::Protection) || ENV['RACK_ENV'] == 'test'
157
- middlewares.unshift [[::Rack::Protection, { use: :authenticity_token }], nil]
157
+ unless using?(::Rack::Protection) || ENV["RACK_ENV"] == "test"
158
+ middlewares.unshift [[::Rack::Protection, {use: :authenticity_token}], nil]
158
159
  end
159
160
 
160
161
  s = sessions
161
162
  return unless s
162
163
 
163
164
  unless using? ::Rack::Session::Cookie
164
- unless secret = Web.session_secret
165
- require 'securerandom'
165
+ unless (secret = Web.session_secret)
166
+ require "securerandom"
166
167
  secret = SecureRandom.hex(64)
167
168
  end
168
169
 
169
- options = { secret: secret }
170
+ options = {secret: secret}
170
171
  options = options.merge(s.to_hash) if s.respond_to? :to_hash
171
172
 
172
173
  middlewares.unshift [[::Rack::Session::Cookie, options], nil]
@@ -180,13 +181,13 @@ module Sidekiq
180
181
  klass = self.class
181
182
 
182
183
  ::Rack::Builder.new do
183
- %w(stylesheets javascripts images).each do |asset_dir|
184
+ %w[stylesheets javascripts images].each do |asset_dir|
184
185
  map "/#{asset_dir}" do
185
- run ::Rack::File.new("#{ASSETS}/#{asset_dir}", { 'Cache-Control' => 'public, max-age=86400' })
186
+ run ::Rack::File.new("#{ASSETS}/#{asset_dir}", {"Cache-Control" => "public, max-age=86400"})
186
187
  end
187
188
  end
188
189
 
189
- middlewares.each {|middleware, block| use(*middleware, &block) }
190
+ middlewares.each { |middleware, block| use(*middleware, &block) }
190
191
 
191
192
  run WebApplication.new(klass)
192
193
  end
@@ -196,18 +197,9 @@ module Sidekiq
196
197
  Sidekiq::WebApplication.helpers WebHelpers
197
198
  Sidekiq::WebApplication.helpers Sidekiq::Paginator
198
199
 
199
- Sidekiq::WebAction.class_eval "def _render\n#{ERB.new(File.read(Web::LAYOUT)).src}\nend"
200
- end
201
-
202
- if defined?(::ActionDispatch::Request::Session) &&
203
- !::ActionDispatch::Request::Session.method_defined?(:each)
204
- # mperham/sidekiq#2460
205
- # Rack apps can't reuse the Rails session store without
206
- # this monkeypatch, fixed in Rails 5.
207
- class ActionDispatch::Request::Session
208
- def each(&block)
209
- hash = self.to_hash
210
- hash.each(&block)
200
+ Sidekiq::WebAction.class_eval <<-RUBY, __FILE__, __LINE__ + 1
201
+ def _render
202
+ #{ERB.new(File.read(Web::LAYOUT)).src}
211
203
  end
212
- end
204
+ RUBY
213
205
  end
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
- require 'sidekiq/client'
3
2
 
4
- module Sidekiq
3
+ require "sidekiq/client"
5
4
 
5
+ module Sidekiq
6
6
  ##
7
7
  # Include this module in your worker class and you can easily create
8
8
  # asynchronous jobs:
@@ -21,15 +21,124 @@ module Sidekiq
21
21
  #
22
22
  # Note that perform_async is a class method, perform is an instance method.
23
23
  module Worker
24
+ ##
25
+ # The Options module is extracted so we can include it in ActiveJob::Base
26
+ # and allow native AJs to configure Sidekiq features/internals.
27
+ module Options
28
+ def self.included(base)
29
+ base.extend(ClassMethods)
30
+ base.sidekiq_class_attribute :sidekiq_options_hash
31
+ base.sidekiq_class_attribute :sidekiq_retry_in_block
32
+ base.sidekiq_class_attribute :sidekiq_retries_exhausted_block
33
+ end
34
+
35
+ module ClassMethods
36
+ ACCESSOR_MUTEX = Mutex.new
37
+
38
+ ##
39
+ # Allows customization for this type of Worker.
40
+ # Legal options:
41
+ #
42
+ # queue - name of queue to use for this job type, default *default*
43
+ # retry - enable retries for this Worker in case of error during execution,
44
+ # *true* to use the default or *Integer* count
45
+ # backtrace - whether to save any error backtrace in the retry payload to display in web UI,
46
+ # can be true, false or an integer number of lines to save, default *false*
47
+ #
48
+ # In practice, any option is allowed. This is the main mechanism to configure the
49
+ # options for a specific job.
50
+ def sidekiq_options(opts = {})
51
+ opts = Hash[opts.map { |k, v| [k.to_s, v] }] # stringify
52
+ self.sidekiq_options_hash = get_sidekiq_options.merge(Hash[opts.map { |k, v| [k.to_s, v] }])
53
+ end
54
+
55
+ def sidekiq_retry_in(&block)
56
+ self.sidekiq_retry_in_block = block
57
+ end
58
+
59
+ def sidekiq_retries_exhausted(&block)
60
+ self.sidekiq_retries_exhausted_block = block
61
+ end
62
+
63
+ def get_sidekiq_options # :nodoc:
64
+ self.sidekiq_options_hash ||= Sidekiq.default_worker_options
65
+ end
66
+
67
+ def sidekiq_class_attribute(*attrs)
68
+ instance_reader = true
69
+ instance_writer = true
70
+
71
+ attrs.each do |name|
72
+ synchronized_getter = "__synchronized_#{name}"
73
+
74
+ singleton_class.instance_eval do
75
+ undef_method(name) if method_defined?(name) || private_method_defined?(name)
76
+ end
77
+
78
+ define_singleton_method(synchronized_getter) { nil }
79
+ singleton_class.class_eval do
80
+ private(synchronized_getter)
81
+ end
82
+
83
+ define_singleton_method(name) { ACCESSOR_MUTEX.synchronize { send synchronized_getter } }
84
+
85
+ ivar = "@#{name}"
86
+
87
+ singleton_class.instance_eval do
88
+ m = "#{name}="
89
+ undef_method(m) if method_defined?(m) || private_method_defined?(m)
90
+ end
91
+ define_singleton_method("#{name}=") do |val|
92
+ singleton_class.class_eval do
93
+ ACCESSOR_MUTEX.synchronize do
94
+ undef_method(synchronized_getter) if method_defined?(synchronized_getter) || private_method_defined?(synchronized_getter)
95
+ define_method(synchronized_getter) { val }
96
+ end
97
+ end
98
+
99
+ if singleton_class?
100
+ class_eval do
101
+ undef_method(name) if method_defined?(name) || private_method_defined?(name)
102
+ define_method(name) do
103
+ if instance_variable_defined? ivar
104
+ instance_variable_get ivar
105
+ else
106
+ singleton_class.send name
107
+ end
108
+ end
109
+ end
110
+ end
111
+ val
112
+ end
113
+
114
+ if instance_reader
115
+ undef_method(name) if method_defined?(name) || private_method_defined?(name)
116
+ define_method(name) do
117
+ if instance_variable_defined?(ivar)
118
+ instance_variable_get ivar
119
+ else
120
+ self.class.public_send name
121
+ end
122
+ end
123
+ end
124
+
125
+ if instance_writer
126
+ m = "#{name}="
127
+ undef_method(m) if method_defined?(m) || private_method_defined?(m)
128
+ attr_writer name
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
134
+
24
135
  attr_accessor :jid
25
136
 
26
137
  def self.included(base)
27
- raise ArgumentError, "You cannot include Sidekiq::Worker in an ActiveJob: #{base.name}" if base.ancestors.any? {|c| c.name == 'ActiveJob::Base' }
138
+ raise ArgumentError, "Sidekiq::Worker cannot be included in an ActiveJob: #{base.name}" if base.ancestors.any? { |c| c.name == "ActiveJob::Base" }
28
139
 
140
+ base.include(Options)
29
141
  base.extend(ClassMethods)
30
- base.sidekiq_class_attribute :sidekiq_options_hash
31
- base.sidekiq_class_attribute :sidekiq_retry_in_block
32
- base.sidekiq_class_attribute :sidekiq_retries_exhausted_block
33
142
  end
34
143
 
35
144
  def logger
@@ -46,8 +155,13 @@ module Sidekiq
46
155
  @opts = opts
47
156
  end
48
157
 
158
+ def set(options)
159
+ @opts.merge!(options)
160
+ self
161
+ end
162
+
49
163
  def perform_async(*args)
50
- @klass.client_push(@opts.merge('args' => args, 'class' => @klass))
164
+ @klass.client_push(@opts.merge("args" => args, "class" => @klass))
51
165
  end
52
166
 
53
167
  # +interval+ must be a timestamp, numeric or something that acts
@@ -57,17 +171,15 @@ module Sidekiq
57
171
  now = Time.now.to_f
58
172
  ts = (int < 1_000_000_000 ? now + int : int)
59
173
 
60
- payload = @opts.merge('class' => @klass, 'args' => args, 'at' => ts)
174
+ payload = @opts.merge("class" => @klass, "args" => args)
61
175
  # Optimization to enqueue something now that is scheduled to go out now or in the past
62
- payload.delete('at') if ts <= now
176
+ payload["at"] = ts if ts > now
63
177
  @klass.client_push(payload)
64
178
  end
65
179
  alias_method :perform_at, :perform_in
66
180
  end
67
181
 
68
182
  module ClassMethods
69
- ACCESSOR_MUTEX = Mutex.new
70
-
71
183
  def delay(*args)
72
184
  raise ArgumentError, "Do not call .delay on a Sidekiq::Worker class, call .perform_async"
73
185
  end
@@ -85,7 +197,7 @@ module Sidekiq
85
197
  end
86
198
 
87
199
  def perform_async(*args)
88
- client_push('class' => self, 'args' => args)
200
+ client_push("class" => self, "args" => args)
89
201
  end
90
202
 
91
203
  # +interval+ must be a timestamp, numeric or something that acts
@@ -95,10 +207,10 @@ module Sidekiq
95
207
  now = Time.now.to_f
96
208
  ts = (int < 1_000_000_000 ? now + int : int)
97
209
 
98
- item = { 'class' => self, 'args' => args, 'at' => ts }
210
+ item = {"class" => self, "args" => args}
99
211
 
100
212
  # Optimization to enqueue something now that is scheduled to go out now or in the past
101
- item.delete('at') if ts <= now
213
+ item["at"] = ts if ts > now
102
214
 
103
215
  client_push(item)
104
216
  end
@@ -117,25 +229,12 @@ module Sidekiq
117
229
  #
118
230
  # In practice, any option is allowed. This is the main mechanism to configure the
119
231
  # options for a specific job.
120
- def sidekiq_options(opts={})
121
- # stringify
122
- self.sidekiq_options_hash = get_sidekiq_options.merge(Hash[opts.map{|k, v| [k.to_s, v]}])
123
- end
124
-
125
- def sidekiq_retry_in(&block)
126
- self.sidekiq_retry_in_block = block
127
- end
128
-
129
- def sidekiq_retries_exhausted(&block)
130
- self.sidekiq_retries_exhausted_block = block
131
- end
132
-
133
- def get_sidekiq_options # :nodoc:
134
- self.sidekiq_options_hash ||= Sidekiq.default_worker_options
232
+ def sidekiq_options(opts = {})
233
+ super
135
234
  end
136
235
 
137
236
  def client_push(item) # :nodoc:
138
- pool = Thread.current[:sidekiq_via_pool] || get_sidekiq_options['pool'] || Sidekiq.redis_pool
237
+ pool = Thread.current[:sidekiq_via_pool] || get_sidekiq_options["pool"] || Sidekiq.redis_pool
139
238
  # stringify
140
239
  item.keys.each do |key|
141
240
  item[key.to_s] = item.delete(key)
@@ -143,73 +242,6 @@ module Sidekiq
143
242
 
144
243
  Sidekiq::Client.new(pool).push(item)
145
244
  end
146
-
147
- def sidekiq_class_attribute(*attrs)
148
- instance_reader = true
149
- instance_writer = true
150
-
151
- attrs.each do |name|
152
- synchronized_getter = "__synchronized_#{name}"
153
-
154
- singleton_class.instance_eval do
155
- undef_method(name) if method_defined?(name) || private_method_defined?(name)
156
- end
157
-
158
- define_singleton_method(synchronized_getter) { nil }
159
- singleton_class.class_eval do
160
- private(synchronized_getter)
161
- end
162
-
163
- define_singleton_method(name) { ACCESSOR_MUTEX.synchronize { send synchronized_getter } }
164
-
165
- ivar = "@#{name}"
166
-
167
- singleton_class.instance_eval do
168
- m = "#{name}="
169
- undef_method(m) if method_defined?(m) || private_method_defined?(m)
170
- end
171
- define_singleton_method("#{name}=") do |val|
172
- singleton_class.class_eval do
173
- ACCESSOR_MUTEX.synchronize do
174
- undef_method(synchronized_getter) if method_defined?(synchronized_getter) || private_method_defined?(synchronized_getter)
175
- define_method(synchronized_getter) { val }
176
- end
177
- end
178
-
179
- if singleton_class?
180
- class_eval do
181
- undef_method(name) if method_defined?(name) || private_method_defined?(name)
182
- define_method(name) do
183
- if instance_variable_defined? ivar
184
- instance_variable_get ivar
185
- else
186
- singleton_class.send name
187
- end
188
- end
189
- end
190
- end
191
- val
192
- end
193
-
194
- if instance_reader
195
- undef_method(name) if method_defined?(name) || private_method_defined?(name)
196
- define_method(name) do
197
- if instance_variable_defined?(ivar)
198
- instance_variable_get ivar
199
- else
200
- self.class.public_send name
201
- end
202
- end
203
- end
204
-
205
- if instance_writer
206
- m = "#{name}="
207
- undef_method(m) if method_defined?(m) || private_method_defined?(m)
208
- attr_writer name
209
- end
210
- end
211
- end
212
-
213
245
  end
214
246
  end
215
247
  end