emipair-delayed_job 2.0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/MIT-LICENSE +20 -0
- data/README.textile +213 -0
- data/Rakefile +33 -0
- data/VERSION +1 -0
- data/benchmarks.rb +33 -0
- data/contrib/delayed_job.monitrc +14 -0
- data/contrib/delayed_job_multiple.monitrc +23 -0
- data/emipair-delayed_job.gemspec +25 -0
- data/generators/delayed_job/delayed_job_generator.rb +22 -0
- data/generators/delayed_job/templates/migration.rb +21 -0
- data/generators/delayed_job/templates/script +5 -0
- data/init.rb +1 -0
- data/lib/delayed/backend/active_record.rb +90 -0
- data/lib/delayed/backend/base.rb +111 -0
- data/lib/delayed/backend/data_mapper.rb +147 -0
- data/lib/delayed/backend/mongo_mapper.rb +110 -0
- data/lib/delayed/command.rb +109 -0
- data/lib/delayed/message_sending.rb +22 -0
- data/lib/delayed/performable_method.rb +62 -0
- data/lib/delayed/railtie.rb +10 -0
- data/lib/delayed/recipes.rb +31 -0
- data/lib/delayed/tasks.rb +15 -0
- data/lib/delayed/worker.rb +214 -0
- data/lib/delayed_job.rb +15 -0
- data/lib/passive_support.rb +4 -0
- data/lib/passive_support/basic_object.rb +16 -0
- data/lib/passive_support/core_ext.rb +8 -0
- data/lib/passive_support/core_ext/class.rb +1 -0
- data/lib/passive_support/core_ext/class/attribute_accessors.rb +57 -0
- data/lib/passive_support/core_ext/date.rb +10 -0
- data/lib/passive_support/core_ext/date/behavior.rb +42 -0
- data/lib/passive_support/core_ext/date/calculations.rb +241 -0
- data/lib/passive_support/core_ext/date/conversions.rb +107 -0
- data/lib/passive_support/core_ext/date_time.rb +12 -0
- data/lib/passive_support/core_ext/date_time/calculations.rb +126 -0
- data/lib/passive_support/core_ext/date_time/conversions.rb +107 -0
- data/lib/passive_support/core_ext/enumerable.rb +120 -0
- data/lib/passive_support/core_ext/kernel.rb +5 -0
- data/lib/passive_support/core_ext/kernel/agnostics.rb +11 -0
- data/lib/passive_support/core_ext/kernel/daemonizing.rb +7 -0
- data/lib/passive_support/core_ext/kernel/debugger.rb +16 -0
- data/lib/passive_support/core_ext/kernel/reporting.rb +59 -0
- data/lib/passive_support/core_ext/kernel/requires.rb +24 -0
- data/lib/passive_support/core_ext/module.rb +20 -0
- data/lib/passive_support/core_ext/module/aliasing.rb +74 -0
- data/lib/passive_support/core_ext/module/attr_accessor_with_default.rb +31 -0
- data/lib/passive_support/core_ext/module/attr_internal.rb +32 -0
- data/lib/passive_support/core_ext/module/delegation.rb +135 -0
- data/lib/passive_support/core_ext/module/inclusion.rb +30 -0
- data/lib/passive_support/core_ext/module/introspection.rb +90 -0
- data/lib/passive_support/core_ext/module/loading.rb +23 -0
- data/lib/passive_support/core_ext/module/model_naming.rb +25 -0
- data/lib/passive_support/core_ext/module/synchronization.rb +39 -0
- data/lib/passive_support/core_ext/numeric.rb +9 -0
- data/lib/passive_support/core_ext/numeric/bytes.rb +50 -0
- data/lib/passive_support/core_ext/numeric/conversions.rb +19 -0
- data/lib/passive_support/core_ext/numeric/time.rb +81 -0
- data/lib/passive_support/core_ext/object.rb +6 -0
- data/lib/passive_support/core_ext/object/blank.rb +76 -0
- data/lib/passive_support/core_ext/object/conversions.rb +15 -0
- data/lib/passive_support/core_ext/object/extending.rb +80 -0
- data/lib/passive_support/core_ext/object/instance_variables.rb +74 -0
- data/lib/passive_support/core_ext/object/misc.rb +90 -0
- data/lib/passive_support/core_ext/object/singleton_class.rb +13 -0
- data/lib/passive_support/core_ext/string.rb +1 -0
- data/lib/passive_support/core_ext/string/constantize.rb +7 -0
- data/lib/passive_support/core_ext/time.rb +46 -0
- data/lib/passive_support/core_ext/time/behavior.rb +13 -0
- data/lib/passive_support/core_ext/time/calculations.rb +313 -0
- data/lib/passive_support/core_ext/time/conversions.rb +90 -0
- data/lib/passive_support/core_ext/time/zones.rb +86 -0
- data/lib/passive_support/duration.rb +100 -0
- data/lib/passive_support/ordered_hash.rb +158 -0
- data/rails/init.rb +5 -0
- data/recipes/delayed_job.rb +1 -0
- data/spec/backend/active_record_job_spec.rb +46 -0
- data/spec/backend/data_mapper_job_spec.rb +16 -0
- data/spec/backend/mongo_mapper_job_spec.rb +94 -0
- data/spec/backend/shared_backend_spec.rb +268 -0
- data/spec/delayed_method_spec.rb +58 -0
- data/spec/performable_method_spec.rb +42 -0
- data/spec/sample_jobs.rb +25 -0
- data/spec/setup/active_record.rb +33 -0
- data/spec/setup/data_mapper.rb +24 -0
- data/spec/setup/mongo_mapper.rb +17 -0
- data/spec/spec_helper.rb +19 -0
- data/spec/story_spec.rb +17 -0
- data/spec/worker_spec.rb +225 -0
- data/tasks/jobs.rake +1 -0
- metadata +323 -0
@@ -0,0 +1,107 @@
|
|
1
|
+
module PassiveSupport #:nodoc:
|
2
|
+
module CoreExtensions #:nodoc:
|
3
|
+
module DateTime #:nodoc:
|
4
|
+
# Converting datetimes to formatted strings, dates, and times.
|
5
|
+
module Conversions
|
6
|
+
def self.append_features(base) #:nodoc:
|
7
|
+
base.class_eval do
|
8
|
+
alias_method :default_inspect, :inspect
|
9
|
+
alias_method :to_default_s, :to_s unless (instance_methods(false) & [:to_s, 'to_s']).empty?
|
10
|
+
|
11
|
+
# Ruby 1.9 has DateTime#to_time which internally relies on Time. We define our own #to_time which allows
|
12
|
+
# DateTimes outside the range of what can be created with Time.
|
13
|
+
remove_method :to_time if instance_methods.include?(:to_time)
|
14
|
+
end
|
15
|
+
|
16
|
+
super
|
17
|
+
|
18
|
+
base.class_eval do
|
19
|
+
alias_method :to_s, :to_formatted_s
|
20
|
+
alias_method :inspect, :readable_inspect
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Convert to a formatted string. See Time::DATE_FORMATS for predefined formats.
|
25
|
+
#
|
26
|
+
# This method is aliased to <tt>to_s</tt>.
|
27
|
+
#
|
28
|
+
# === Examples
|
29
|
+
# datetime = DateTime.civil(2007, 12, 4, 0, 0, 0, 0) # => Tue, 04 Dec 2007 00:00:00 +0000
|
30
|
+
#
|
31
|
+
# datetime.to_formatted_s(:db) # => "2007-12-04 00:00:00"
|
32
|
+
# datetime.to_s(:db) # => "2007-12-04 00:00:00"
|
33
|
+
# datetime.to_s(:number) # => "20071204000000"
|
34
|
+
# datetime.to_formatted_s(:short) # => "04 Dec 00:00"
|
35
|
+
# datetime.to_formatted_s(:long) # => "December 04, 2007 00:00"
|
36
|
+
# datetime.to_formatted_s(:long_ordinal) # => "December 4th, 2007 00:00"
|
37
|
+
# datetime.to_formatted_s(:rfc822) # => "Tue, 04 Dec 2007 00:00:00 +0000"
|
38
|
+
#
|
39
|
+
# == Adding your own datetime formats to to_formatted_s
|
40
|
+
# DateTime formats are shared with Time. You can add your own to the
|
41
|
+
# Time::DATE_FORMATS hash. Use the format name as the hash key and
|
42
|
+
# either a strftime string or Proc instance that takes a time or
|
43
|
+
# datetime argument as the value.
|
44
|
+
#
|
45
|
+
# # config/initializers/time_formats.rb
|
46
|
+
# Time::DATE_FORMATS[:month_and_year] = "%B %Y"
|
47
|
+
# Time::DATE_FORMATS[:short_ordinal] = lambda { |time| time.strftime("%B #{time.day.ordinalize}") }
|
48
|
+
def to_formatted_s(format = :default)
|
49
|
+
return to_default_s unless formatter = ::Time::DATE_FORMATS[format]
|
50
|
+
formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Returns the +utc_offset+ as an +HH:MM formatted string. Examples:
|
54
|
+
#
|
55
|
+
# datetime = DateTime.civil(2000, 1, 1, 0, 0, 0, Rational(-6, 24))
|
56
|
+
# datetime.formatted_offset # => "-06:00"
|
57
|
+
# datetime.formatted_offset(false) # => "-0600"
|
58
|
+
def formatted_offset(colon = true, alternate_utc_string = nil)
|
59
|
+
utc? && alternate_utc_string || utc_offset.to_utc_offset_s(colon)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Overrides the default inspect method with a human readable one, e.g., "Mon, 21 Feb 2005 14:30:00 +0000"
|
63
|
+
def readable_inspect
|
64
|
+
to_s(:rfc822)
|
65
|
+
end
|
66
|
+
|
67
|
+
# Converts self to a Ruby Date object; time portion is discarded
|
68
|
+
def to_date
|
69
|
+
::Date.new(year, month, day)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Attempts to convert self to a Ruby Time object; returns self if out of range of Ruby Time class
|
73
|
+
# If self has an offset other than 0, self will just be returned unaltered, since there's no clean way to map it to a Time
|
74
|
+
def to_time
|
75
|
+
self.offset == 0 ? ::Time.utc_time(year, month, day, hour, min, sec) : self
|
76
|
+
end
|
77
|
+
|
78
|
+
# To be able to keep Times, Dates and DateTimes interchangeable on conversions
|
79
|
+
def to_datetime
|
80
|
+
self
|
81
|
+
end
|
82
|
+
|
83
|
+
# Converts datetime to an appropriate format for use in XML
|
84
|
+
def xmlschema
|
85
|
+
strftime("%Y-%m-%dT%H:%M:%S%Z")
|
86
|
+
end if RUBY_VERSION < '1.9'
|
87
|
+
|
88
|
+
# Converts self to a floating-point number of seconds since the Unix epoch
|
89
|
+
def to_f
|
90
|
+
seconds_since_unix_epoch.to_f
|
91
|
+
end
|
92
|
+
|
93
|
+
# Converts self to an integer number of seconds since the Unix epoch
|
94
|
+
def to_i
|
95
|
+
seconds_since_unix_epoch.to_i
|
96
|
+
end
|
97
|
+
|
98
|
+
private
|
99
|
+
|
100
|
+
def seconds_since_unix_epoch
|
101
|
+
seconds_per_day = 86_400
|
102
|
+
(self - ::DateTime.civil(1970)) * seconds_per_day
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
require 'passive_support/ordered_hash'
|
2
|
+
|
3
|
+
module Enumerable
|
4
|
+
# Ruby 1.8.7 introduces group_by, but the result isn't ordered. Override it.
|
5
|
+
remove_method(:group_by) if [].respond_to?(:group_by) && RUBY_VERSION < '1.9'
|
6
|
+
|
7
|
+
# Collect an enumerable into sets, grouped by the result of a block. Useful,
|
8
|
+
# for example, for grouping records by date.
|
9
|
+
#
|
10
|
+
# Example:
|
11
|
+
#
|
12
|
+
# latest_transcripts.group_by(&:day).each do |day, transcripts|
|
13
|
+
# p "#{day} -> #{transcripts.map(&:class).join(', ')}"
|
14
|
+
# end
|
15
|
+
# "2006-03-01 -> Transcript"
|
16
|
+
# "2006-02-28 -> Transcript"
|
17
|
+
# "2006-02-27 -> Transcript, Transcript"
|
18
|
+
# "2006-02-26 -> Transcript, Transcript"
|
19
|
+
# "2006-02-25 -> Transcript"
|
20
|
+
# "2006-02-24 -> Transcript, Transcript"
|
21
|
+
# "2006-02-23 -> Transcript"
|
22
|
+
def group_by
|
23
|
+
assoc = PassiveSupport::OrderedHash.new
|
24
|
+
|
25
|
+
each do |element|
|
26
|
+
key = yield(element)
|
27
|
+
|
28
|
+
if assoc.has_key?(key)
|
29
|
+
assoc[key] << element
|
30
|
+
else
|
31
|
+
assoc[key] = [element]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
assoc
|
36
|
+
end unless [].respond_to?(:group_by)
|
37
|
+
|
38
|
+
# Calculates a sum from the elements. Examples:
|
39
|
+
#
|
40
|
+
# payments.sum { |p| p.price * p.tax_rate }
|
41
|
+
# payments.sum(&:price)
|
42
|
+
#
|
43
|
+
# The latter is a shortcut for:
|
44
|
+
#
|
45
|
+
# payments.inject { |sum, p| sum + p.price }
|
46
|
+
#
|
47
|
+
# It can also calculate the sum without the use of a block.
|
48
|
+
#
|
49
|
+
# [5, 15, 10].sum # => 30
|
50
|
+
# ["foo", "bar"].sum # => "foobar"
|
51
|
+
# [[1, 2], [3, 1, 5]].sum => [1, 2, 3, 1, 5]
|
52
|
+
#
|
53
|
+
# The default sum of an empty list is zero. You can override this default:
|
54
|
+
#
|
55
|
+
# [].sum(Payment.new(0)) { |i| i.amount } # => Payment.new(0)
|
56
|
+
#
|
57
|
+
def sum(identity = 0, &block)
|
58
|
+
if block_given?
|
59
|
+
map(&block).sum(identity)
|
60
|
+
else
|
61
|
+
inject { |sum, element| sum + element } || identity
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Iterates over a collection, passing the current element *and* the
|
66
|
+
# +memo+ to the block. Handy for building up hashes or
|
67
|
+
# reducing collections down to one object. Examples:
|
68
|
+
#
|
69
|
+
# %w(foo bar).each_with_object({}) { |str, hsh| hsh[str] = str.upcase } #=> {'foo' => 'FOO', 'bar' => 'BAR'}
|
70
|
+
#
|
71
|
+
# *Note* that you can't use immutable objects like numbers, true or false as
|
72
|
+
# the memo. You would think the following returns 120, but since the memo is
|
73
|
+
# never changed, it does not.
|
74
|
+
#
|
75
|
+
# (1..5).each_with_object(1) { |value, memo| memo *= value } # => 1
|
76
|
+
#
|
77
|
+
def each_with_object(memo, &block)
|
78
|
+
returning memo do |m|
|
79
|
+
each do |element|
|
80
|
+
block.call(element, m)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end unless [].respond_to?(:each_with_object)
|
84
|
+
|
85
|
+
# Convert an enumerable to a hash. Examples:
|
86
|
+
#
|
87
|
+
# people.index_by(&:login)
|
88
|
+
# => { "nextangle" => <Person ...>, "chade-" => <Person ...>, ...}
|
89
|
+
# people.index_by { |person| "#{person.first_name} #{person.last_name}" }
|
90
|
+
# => { "Chade- Fowlersburg-e" => <Person ...>, "David Heinemeier Hansson" => <Person ...>, ...}
|
91
|
+
#
|
92
|
+
def index_by
|
93
|
+
inject({}) do |accum, elem|
|
94
|
+
accum[yield(elem)] = elem
|
95
|
+
accum
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# Returns true if the collection has more than 1 element. Functionally equivalent to collection.size > 1.
|
100
|
+
# Works with a block too ala any?, so people.many? { |p| p.age > 26 } # => returns true if more than 1 person is over 26.
|
101
|
+
def many?(&block)
|
102
|
+
size = block_given? ? select(&block).size : self.size
|
103
|
+
size > 1
|
104
|
+
end
|
105
|
+
|
106
|
+
# Returns true if none of the elements match the given block.
|
107
|
+
#
|
108
|
+
# success = responses.none? {|r| r.status / 100 == 5 }
|
109
|
+
#
|
110
|
+
# This is a builtin method in Ruby 1.8.7 and later.
|
111
|
+
def none?(&block)
|
112
|
+
!any?(&block)
|
113
|
+
end unless [].respond_to?(:none?)
|
114
|
+
|
115
|
+
|
116
|
+
# The negative of the Enumerable#include?. Returns true if the collection does not include the object.
|
117
|
+
def exclude?(object)
|
118
|
+
!include?(object)
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class Object
|
2
|
+
# Makes backticks behave (somewhat more) similarly on all platforms.
|
3
|
+
# On win32 `nonexistent_command` raises Errno::ENOENT; on Unix, the
|
4
|
+
# spawned shell prints a message to stderr and sets $?. We emulate
|
5
|
+
# Unix on the former but not the latter.
|
6
|
+
def `(command) #:nodoc:
|
7
|
+
super
|
8
|
+
rescue Errno::ENOENT => e
|
9
|
+
STDERR.puts "#$0: #{e}"
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Kernel
|
2
|
+
unless respond_to?(:debugger)
|
3
|
+
# Starts a debugging session if ruby-debug has been loaded (call script/server --debugger to do load it).
|
4
|
+
def debugger
|
5
|
+
message = "\n***** Debugger requested, but was not available: Start server with --debugger to enable *****\n"
|
6
|
+
defined?(Rails) ? Rails.logger.info(message) : $stderr.puts(message)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
undef :breakpoint if respond_to?(:breakpoint)
|
11
|
+
def breakpoint
|
12
|
+
message = "\n***** The 'breakpoint' command has been renamed 'debugger' -- please change *****\n"
|
13
|
+
defined?(Rails) ? Rails.logger.info(message) : $stderr.puts(message)
|
14
|
+
debugger
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Kernel
|
2
|
+
# Sets $VERBOSE to nil for the duration of the block and back to its original value afterwards.
|
3
|
+
#
|
4
|
+
# silence_warnings do
|
5
|
+
# value = noisy_call # no warning voiced
|
6
|
+
# end
|
7
|
+
#
|
8
|
+
# noisy_call # warning voiced
|
9
|
+
def silence_warnings
|
10
|
+
old_verbose, $VERBOSE = $VERBOSE, nil
|
11
|
+
yield
|
12
|
+
ensure
|
13
|
+
$VERBOSE = old_verbose
|
14
|
+
end
|
15
|
+
|
16
|
+
# Sets $VERBOSE to true for the duration of the block and back to its original value afterwards.
|
17
|
+
def enable_warnings
|
18
|
+
old_verbose, $VERBOSE = $VERBOSE, true
|
19
|
+
yield
|
20
|
+
ensure
|
21
|
+
$VERBOSE = old_verbose
|
22
|
+
end
|
23
|
+
|
24
|
+
# For compatibility
|
25
|
+
def silence_stderr #:nodoc:
|
26
|
+
silence_stream(STDERR) { yield }
|
27
|
+
end
|
28
|
+
|
29
|
+
# Silences any stream for the duration of the block.
|
30
|
+
#
|
31
|
+
# silence_stream(STDOUT) do
|
32
|
+
# puts 'This will never be seen'
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# puts 'But this will'
|
36
|
+
def silence_stream(stream)
|
37
|
+
old_stream = stream.dup
|
38
|
+
stream.reopen(RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'NUL:' : '/dev/null')
|
39
|
+
stream.sync = true
|
40
|
+
yield
|
41
|
+
ensure
|
42
|
+
stream.reopen(old_stream)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Blocks and ignores any exception passed as argument if raised within the block.
|
46
|
+
#
|
47
|
+
# suppress(ZeroDivisionError) do
|
48
|
+
# 1/0
|
49
|
+
# puts "This code is NOT reached"
|
50
|
+
# end
|
51
|
+
#
|
52
|
+
# puts "This code gets executed and nothing related to ZeroDivisionError was seen"
|
53
|
+
def suppress(*exception_classes)
|
54
|
+
begin yield
|
55
|
+
rescue Exception => e
|
56
|
+
raise unless exception_classes.any? { |cls| e.kind_of?(cls) }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Kernel
|
2
|
+
# Require a library with fallback to RubyGems. Warnings during library
|
3
|
+
# loading are silenced to increase signal/noise for application warnings.
|
4
|
+
def require_library_or_gem(library_name)
|
5
|
+
silence_warnings do
|
6
|
+
begin
|
7
|
+
require library_name
|
8
|
+
rescue LoadError => cannot_require
|
9
|
+
# 1. Requiring the module is unsuccessful, maybe it's a gem and nobody required rubygems yet. Try.
|
10
|
+
begin
|
11
|
+
require 'rubygems'
|
12
|
+
rescue LoadError => rubygems_not_installed
|
13
|
+
raise cannot_require
|
14
|
+
end
|
15
|
+
# 2. Rubygems is installed and loaded. Try to load the library again
|
16
|
+
begin
|
17
|
+
require library_name
|
18
|
+
rescue LoadError => gem_not_installed
|
19
|
+
raise cannot_require
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'passive_support/core_ext/module/inclusion'
|
2
|
+
require 'passive_support/core_ext/module/delegation'
|
3
|
+
require 'passive_support/core_ext/module/introspection'
|
4
|
+
require 'passive_support/core_ext/module/loading'
|
5
|
+
require 'passive_support/core_ext/module/aliasing'
|
6
|
+
require 'passive_support/core_ext/module/model_naming'
|
7
|
+
require 'passive_support/core_ext/module/synchronization'
|
8
|
+
|
9
|
+
module PassiveSupport
|
10
|
+
module CoreExtensions
|
11
|
+
# Various extensions for the Ruby core Module class.
|
12
|
+
module Module
|
13
|
+
# Nothing here. Only defined for API documentation purposes.
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class Module
|
19
|
+
include PassiveSupport::CoreExtensions::Module
|
20
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module PassiveSupport
|
2
|
+
module CoreExtensions
|
3
|
+
module Module
|
4
|
+
# Encapsulates the common pattern of:
|
5
|
+
#
|
6
|
+
# alias_method :foo_without_feature, :foo
|
7
|
+
# alias_method :foo, :foo_with_feature
|
8
|
+
#
|
9
|
+
# With this, you simply do:
|
10
|
+
#
|
11
|
+
# alias_method_chain :foo, :feature
|
12
|
+
#
|
13
|
+
# And both aliases are set up for you.
|
14
|
+
#
|
15
|
+
# Query and bang methods (foo?, foo!) keep the same punctuation:
|
16
|
+
#
|
17
|
+
# alias_method_chain :foo?, :feature
|
18
|
+
#
|
19
|
+
# is equivalent to
|
20
|
+
#
|
21
|
+
# alias_method :foo_without_feature?, :foo?
|
22
|
+
# alias_method :foo?, :foo_with_feature?
|
23
|
+
#
|
24
|
+
# so you can safely chain foo, foo?, and foo! with the same feature.
|
25
|
+
def alias_method_chain(target, feature)
|
26
|
+
# Strip out punctuation on predicates or bang methods since
|
27
|
+
# e.g. target?_without_feature is not a valid method name.
|
28
|
+
aliased_target, punctuation = target.to_s.sub(/([?!=])$/, ''), $1
|
29
|
+
yield(aliased_target, punctuation) if block_given?
|
30
|
+
|
31
|
+
with_method, without_method = "#{aliased_target}_with_#{feature}#{punctuation}", "#{aliased_target}_without_#{feature}#{punctuation}"
|
32
|
+
|
33
|
+
alias_method without_method, target
|
34
|
+
alias_method target, with_method
|
35
|
+
|
36
|
+
case
|
37
|
+
when public_method_defined?(without_method)
|
38
|
+
public target
|
39
|
+
when protected_method_defined?(without_method)
|
40
|
+
protected target
|
41
|
+
when private_method_defined?(without_method)
|
42
|
+
private target
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Allows you to make aliases for attributes, which includes
|
47
|
+
# getter, setter, and query methods.
|
48
|
+
#
|
49
|
+
# Example:
|
50
|
+
#
|
51
|
+
# class Content < ActiveRecord::Base
|
52
|
+
# # has a title attribute
|
53
|
+
# end
|
54
|
+
#
|
55
|
+
# class Email < Content
|
56
|
+
# alias_attribute :subject, :title
|
57
|
+
# end
|
58
|
+
#
|
59
|
+
# e = Email.find(1)
|
60
|
+
# e.title # => "Superstars"
|
61
|
+
# e.subject # => "Superstars"
|
62
|
+
# e.subject? # => true
|
63
|
+
# e.subject = "Megastars"
|
64
|
+
# e.title # => "Megastars"
|
65
|
+
def alias_attribute(new_name, old_name)
|
66
|
+
module_eval <<-STR, __FILE__, __LINE__ + 1
|
67
|
+
def #{new_name}; self.#{old_name}; end # def subject; self.title; end
|
68
|
+
def #{new_name}?; self.#{old_name}?; end # def subject?; self.title?; end
|
69
|
+
def #{new_name}=(v); self.#{old_name} = v; end # def subject=(v); self.title = v; end
|
70
|
+
STR
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|