kronn-has_many_polymorphs 3.0.0
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.
- data/CHANGELOG +86 -0
- data/LICENSE +184 -0
- data/README +214 -0
- data/lib/has_many_polymorphs.rb +19 -0
- data/lib/has_many_polymorphs/association.rb +165 -0
- data/lib/has_many_polymorphs/autoload.rb +58 -0
- data/lib/has_many_polymorphs/base.rb +71 -0
- data/lib/has_many_polymorphs/class_methods.rb +598 -0
- data/lib/has_many_polymorphs/debugging_tools.rb +104 -0
- data/lib/has_many_polymorphs/railtie.rb +8 -0
- data/lib/has_many_polymorphs/rake_task_redefine_task.rb +35 -0
- data/lib/has_many_polymorphs/reflection.rb +58 -0
- data/lib/has_many_polymorphs/support_methods.rb +88 -0
- metadata +96 -0
@@ -0,0 +1,104 @@
|
|
1
|
+
|
2
|
+
=begin rdoc
|
3
|
+
|
4
|
+
Debugging tools for Has_many_polymorphs.
|
5
|
+
|
6
|
+
Enable the different tools by setting the environment variable HMP_DEBUG. Settings with special meaning are <tt>"ruby-debug"</tt>, <tt>"trace"</tt>, and <tt>"dependencies"</tt>.
|
7
|
+
|
8
|
+
== Code generation
|
9
|
+
|
10
|
+
Enabled by default when HMP_DEBUG is set.
|
11
|
+
|
12
|
+
Ouputs a folder <tt>generated_models/</tt> in Rails.root containing valid Ruby files explaining all the ActiveRecord relationships set up by the plugin, as well as listing the line in the plugin that called each particular association method.
|
13
|
+
|
14
|
+
== Ruby-debug
|
15
|
+
|
16
|
+
Enable by setting HMP_DEBUG to <tt>"ruby-debug"</tt>.
|
17
|
+
|
18
|
+
Starts <tt>ruby-debug</tt> for the life of the process.
|
19
|
+
|
20
|
+
== Trace
|
21
|
+
|
22
|
+
Enable by setting HMP_DEBUG to <tt>"trace"</tt>.
|
23
|
+
|
24
|
+
Outputs an indented trace of relevant method calls as they occur.
|
25
|
+
|
26
|
+
== Dependencies
|
27
|
+
|
28
|
+
Enable by setting HMP_DEBUG to <tt>"dependencies"</tt>.
|
29
|
+
|
30
|
+
Turns on Rails' default dependency logging.
|
31
|
+
|
32
|
+
=end
|
33
|
+
|
34
|
+
_logger_warn "debug mode enabled"
|
35
|
+
|
36
|
+
class << ActiveRecord::Base
|
37
|
+
COLLECTION_METHODS = [:belongs_to, :has_many, :has_and_belongs_to_many, :has_one,
|
38
|
+
:has_many_polymorphs, :acts_as_double_polymorphic_join].each do |method_name|
|
39
|
+
alias_method "original_#{method_name}".to_sym, method_name
|
40
|
+
undef_method method_name
|
41
|
+
end
|
42
|
+
|
43
|
+
unless defined? GENERATED_CODE_DIR
|
44
|
+
base_dir = (defined?(Rails) and Rails.root) ? Rails.root.expand_path : '/tmp'
|
45
|
+
GENERATED_CODE_DIR = "#{base_dir}/generated_models"
|
46
|
+
|
47
|
+
begin
|
48
|
+
system "rm -rf #{GENERATED_CODE_DIR}"
|
49
|
+
Dir.mkdir GENERATED_CODE_DIR
|
50
|
+
rescue Errno::EACCES
|
51
|
+
_logger_warn "no permissions for generated code dir: #{GENERATED_CODE_DIR}"
|
52
|
+
end
|
53
|
+
|
54
|
+
if File.exist? GENERATED_CODE_DIR
|
55
|
+
alias :original_method_missing :method_missing
|
56
|
+
def method_missing(method_name, *args, &block)
|
57
|
+
if COLLECTION_METHODS.include? method_name.to_sym
|
58
|
+
Dir.chdir GENERATED_CODE_DIR do
|
59
|
+
filename = "#{demodulate(self.name.underscore)}.rb"
|
60
|
+
contents = File.open(filename).read rescue "\nclass #{self.name}\n\nend\n"
|
61
|
+
callfile, callline = caller[2][%r!/.*/(.*?:\d+)!, 1].split(':')
|
62
|
+
contents[-5..-5] = "\n #{method_name} #{args[0..-2].inspect[1..-2]},\n #{args[-1].inspect[1..-2].gsub(" :", "\n :").gsub("=>", " => ")}\n#{ block ? " #{block.inspect.sub(/\@.*\//, '@')}\n" : ""} # called from #{callfile}, line #{callline}\n\n"
|
63
|
+
File.open(filename, "w") do |file|
|
64
|
+
file.puts contents
|
65
|
+
end
|
66
|
+
end
|
67
|
+
# doesn't actually display block contents
|
68
|
+
self.send("original_#{method_name}", *args, &block)
|
69
|
+
else
|
70
|
+
self.send(:original_method_missing, method_name, *args, &block)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
case ENV['HMP_DEBUG']
|
79
|
+
|
80
|
+
when "ruby-debug"
|
81
|
+
require 'rubygems'
|
82
|
+
require 'ruby-debug'
|
83
|
+
Debugger.start
|
84
|
+
_logger_warn "ruby-debug enabled."
|
85
|
+
|
86
|
+
when "trace"
|
87
|
+
_logger_warn "method tracing enabled"
|
88
|
+
$debug_trace_indent = 0
|
89
|
+
set_trace_func (proc do |event, file, line, id, binding, classname|
|
90
|
+
if id.to_s =~ /instantiate/ #/IRB|Wirble|RubyLex|RubyToken|Logger|ConnectionAdapters|SQLite3|MonitorMixin|Benchmark|Inflector|Inflections/
|
91
|
+
if event == 'call'
|
92
|
+
puts (" " * $debug_trace_indent) + "#{event}ed #{classname}\##{id} from #{file.split('/').last}::#{line}"
|
93
|
+
$debug_trace_indent += 1
|
94
|
+
elsif event == 'return'
|
95
|
+
$debug_trace_indent -= 1 unless $debug_trace_indent == 0
|
96
|
+
puts (" " * $debug_trace_indent) + "#{event}ed #{classname}\##{id}"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end)
|
100
|
+
|
101
|
+
when "dependencies"
|
102
|
+
_logger_warn "dependency activity being logged"
|
103
|
+
(::Dependencies.log_activity = true) rescue nil
|
104
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
|
2
|
+
# Redefine instead of chain a Rake task
|
3
|
+
# http://www.bigbold.com/snippets/posts/show/2032
|
4
|
+
|
5
|
+
module Rake
|
6
|
+
module TaskManager
|
7
|
+
def redefine_task(task_class, args, &block)
|
8
|
+
task_name, deps = resolve_args(args)
|
9
|
+
task_name = task_class.scope_name(@scope, task_name)
|
10
|
+
deps = [deps] unless deps.respond_to?(:to_ary)
|
11
|
+
deps = deps.collect {|d| d.to_s }
|
12
|
+
task = @tasks[task_name.to_s] = task_class.new(task_name, self)
|
13
|
+
task.application = self
|
14
|
+
task.add_comment(@last_comment)
|
15
|
+
@last_comment = nil
|
16
|
+
task.enhance(deps, &block)
|
17
|
+
task
|
18
|
+
end
|
19
|
+
end
|
20
|
+
class Task
|
21
|
+
class << self
|
22
|
+
def redefine_task(args, &block)
|
23
|
+
Rake.application.redefine_task(self, args, &block)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class Object
|
30
|
+
def silently
|
31
|
+
stderr, stdout, $stderr, $stdout = $stderr, $stdout, StringIO.new, StringIO.new
|
32
|
+
yield
|
33
|
+
$stderr, $stdout = stderr, stdout
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module ActiveRecord #:nodoc:
|
2
|
+
module Reflection #:nodoc:
|
3
|
+
|
4
|
+
module ClassMethods #:nodoc:
|
5
|
+
|
6
|
+
# Update the default reflection switch so that <tt>:has_many_polymorphs</tt> types get instantiated.
|
7
|
+
# It's not a composed method so we have to override the whole thing.
|
8
|
+
def create_reflection(macro, name, options, active_record)
|
9
|
+
case macro
|
10
|
+
when :has_many, :belongs_to, :has_one, :has_and_belongs_to_many
|
11
|
+
klass = options[:through] ? ThroughReflection : AssociationReflection
|
12
|
+
reflection = klass.new(macro, name, options, active_record)
|
13
|
+
when :composed_of
|
14
|
+
reflection = AggregateReflection.new(macro, name, options, active_record)
|
15
|
+
# added by has_many_polymorphs #
|
16
|
+
when :has_many_polymorphs
|
17
|
+
reflection = PolymorphicReflection.new(macro, name, options, active_record)
|
18
|
+
end
|
19
|
+
write_inheritable_hash :reflections, name => reflection
|
20
|
+
reflection
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
class PolymorphicError < ActiveRecordError #:nodoc:
|
26
|
+
end
|
27
|
+
|
28
|
+
=begin rdoc
|
29
|
+
|
30
|
+
The reflection built by the <tt>has_many_polymorphs</tt> method.
|
31
|
+
|
32
|
+
Inherits from ActiveRecord::Reflection::AssociationReflection.
|
33
|
+
|
34
|
+
=end
|
35
|
+
|
36
|
+
class PolymorphicReflection < ThroughReflection
|
37
|
+
# Stub out the validity check. Has_many_polymorphs checks validity on macro creation, not on reflection.
|
38
|
+
def check_validity!
|
39
|
+
# nothing
|
40
|
+
end
|
41
|
+
|
42
|
+
# Return the source reflection.
|
43
|
+
def source_reflection
|
44
|
+
# normally is the has_many to the through model, but we return ourselves,
|
45
|
+
# since there isn't a real source class for a polymorphic target
|
46
|
+
self
|
47
|
+
end
|
48
|
+
|
49
|
+
# Set the classname of the target. Uses the join class name.
|
50
|
+
def class_name
|
51
|
+
# normally is the classname of the association target
|
52
|
+
@class_name ||= options[:join_class_name]
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
|
2
|
+
class String
|
3
|
+
|
4
|
+
# Changes an underscored string into a class reference.
|
5
|
+
def _as_class
|
6
|
+
# classify expects self to be plural
|
7
|
+
self.classify.constantize
|
8
|
+
end
|
9
|
+
|
10
|
+
# For compatibility with the Symbol extensions.
|
11
|
+
alias :_singularize :singularize
|
12
|
+
alias :_pluralize :pluralize
|
13
|
+
alias :_classify :classify
|
14
|
+
end
|
15
|
+
|
16
|
+
class Symbol
|
17
|
+
|
18
|
+
# Changes an underscored symbol into a class reference.
|
19
|
+
def _as_class; self.to_s._as_class; end
|
20
|
+
|
21
|
+
# Changes a plural symbol into a singular symbol.
|
22
|
+
def _singularize; self.to_s.singularize.to_sym; end
|
23
|
+
|
24
|
+
# Changes a singular symbol into a plural symbol.
|
25
|
+
def _pluralize; self.to_s.pluralize.to_sym; end
|
26
|
+
|
27
|
+
# Changes a symbol into a class name string.
|
28
|
+
def _classify; self.to_s.classify; end
|
29
|
+
end
|
30
|
+
|
31
|
+
class Array
|
32
|
+
|
33
|
+
# Flattens the first level of self.
|
34
|
+
def _flatten_once
|
35
|
+
self.inject([]){|r, el| r + Array(el)}
|
36
|
+
end
|
37
|
+
|
38
|
+
# Rails 1.2.3 compatibility method. Copied from http://dev.rubyonrails.org/browser/trunk/activesupport/lib/active_support/core_ext/array/extract_options.rb?rev=7217
|
39
|
+
def _extract_options!
|
40
|
+
last.is_a?(::Hash) ? pop : {}
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class Hash
|
45
|
+
|
46
|
+
# An implementation of select that returns a Hash.
|
47
|
+
def _select
|
48
|
+
if RUBY_VERSION >= "1.9"
|
49
|
+
Hash[*self.select {|k, v| yield k, v }.flatten]
|
50
|
+
else
|
51
|
+
Hash[*self.select do |key, value|
|
52
|
+
yield key, value
|
53
|
+
end._flatten_once]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
class Object
|
59
|
+
|
60
|
+
# Returns the metaclass of self.
|
61
|
+
def _metaclass; (class << self; self; end); end
|
62
|
+
|
63
|
+
# Logger shortcut.
|
64
|
+
def _logger_debug s
|
65
|
+
s = "** has_many_polymorphs: #{s}"
|
66
|
+
Rails.logger.debug(s) if Rails and Rails.logger
|
67
|
+
end
|
68
|
+
|
69
|
+
# Logger shortcut.
|
70
|
+
def _logger_warn s
|
71
|
+
s = "** has_many_polymorphs: #{s}"
|
72
|
+
if Rails and Rails.logger
|
73
|
+
Rails.logger.warn(s)
|
74
|
+
else
|
75
|
+
$stderr.puts(s)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
class ActiveRecord::Base
|
82
|
+
|
83
|
+
# Return the base class name as a string.
|
84
|
+
def _base_class_name
|
85
|
+
self.class.base_class.name.to_s
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
metadata
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: kronn-has_many_polymorphs
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 7
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 3
|
8
|
+
- 0
|
9
|
+
- 0
|
10
|
+
version: 3.0.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Evan Weaver
|
14
|
+
- James Stewart
|
15
|
+
- Matthias Viehweger
|
16
|
+
autorequire:
|
17
|
+
bindir: bin
|
18
|
+
cert_chain: []
|
19
|
+
|
20
|
+
date: 2010-10-21 00:00:00 +02:00
|
21
|
+
default_executable:
|
22
|
+
dependencies:
|
23
|
+
- !ruby/object:Gem::Dependency
|
24
|
+
name: activerecord
|
25
|
+
prerelease: false
|
26
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
27
|
+
none: false
|
28
|
+
requirements:
|
29
|
+
- - ">="
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
hash: 3
|
32
|
+
segments:
|
33
|
+
- 0
|
34
|
+
version: "0"
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id001
|
37
|
+
description:
|
38
|
+
email:
|
39
|
+
executables: []
|
40
|
+
|
41
|
+
extensions: []
|
42
|
+
|
43
|
+
extra_rdoc_files: []
|
44
|
+
|
45
|
+
files:
|
46
|
+
- lib/has_many_polymorphs/association.rb
|
47
|
+
- lib/has_many_polymorphs/autoload.rb
|
48
|
+
- lib/has_many_polymorphs/base.rb
|
49
|
+
- lib/has_many_polymorphs/class_methods.rb
|
50
|
+
- lib/has_many_polymorphs/debugging_tools.rb
|
51
|
+
- lib/has_many_polymorphs/railtie.rb
|
52
|
+
- lib/has_many_polymorphs/rake_task_redefine_task.rb
|
53
|
+
- lib/has_many_polymorphs/reflection.rb
|
54
|
+
- lib/has_many_polymorphs/support_methods.rb
|
55
|
+
- lib/has_many_polymorphs.rb
|
56
|
+
- LICENSE
|
57
|
+
- README
|
58
|
+
- CHANGELOG
|
59
|
+
has_rdoc: true
|
60
|
+
homepage: http://blog.evanweaver.com/files/doc/fauna/has_many_polymorphs/
|
61
|
+
licenses: []
|
62
|
+
|
63
|
+
post_install_message:
|
64
|
+
rdoc_options: []
|
65
|
+
|
66
|
+
require_paths:
|
67
|
+
- lib
|
68
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
69
|
+
none: false
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
hash: 3
|
74
|
+
segments:
|
75
|
+
- 0
|
76
|
+
version: "0"
|
77
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
78
|
+
none: false
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
hash: 23
|
83
|
+
segments:
|
84
|
+
- 1
|
85
|
+
- 3
|
86
|
+
- 6
|
87
|
+
version: 1.3.6
|
88
|
+
requirements: []
|
89
|
+
|
90
|
+
rubyforge_project:
|
91
|
+
rubygems_version: 1.3.7
|
92
|
+
signing_key:
|
93
|
+
specification_version: 3
|
94
|
+
summary: An ActiveRecord plugin for self-referential and double-sided polymorphic associations.
|
95
|
+
test_files: []
|
96
|
+
|