dolzenko 0.0.10 → 0.0.11

Sign up to get free protection for your applications and to get access to all the features.
data/dolzenko.gemspec CHANGED
File without changes
@@ -0,0 +1,213 @@
1
+ # Django F object for Rails 3
2
+ # http://docs.djangoproject.com/en/dev/topics/db/queries/#query-expressions
3
+ #
4
+ # Let's you reference columns (and do simple calculations on them)
5
+ # from conditions and updates.
6
+ #
7
+ # User.where(:updated_at => F(:created_at))
8
+ #
9
+ # instead of User.where("updated_at = created_at")
10
+ #
11
+ # User.where(:updated_at => F(:created_at) + 1)
12
+ #
13
+ # instead of User.where("updated_at = created_at + 1")
14
+ #
15
+ # User.where(:updated_at => F(:created_at) + F(:updated_at))
16
+ #
17
+ # instead of User.where("updated_at = created_at + updated_at")
18
+ #
19
+ # User.update_all(:mirror_id => F(:id))
20
+ #
21
+ # instead of User.update_all("mirror_id = id")
22
+ #
23
+ # user = User.find(1)
24
+ # user.mirror_id = F(:id) + 1
25
+ # user.save
26
+ #
27
+ # issues UPDATE `users` SET `mirror_id` = `users`.`id` + 1 WHERE (`users`.`id` = 1)
28
+ #
29
+ #
30
+
31
+ require "require_gist"; require_gist "383954/ea5a41269aac073b596b21fe392098827186a32b/alias_method_chain_once.rb", "a6f068593bb45fe6c9956205f672ac4a0c2e1671" # http://gist.github.com/383954
32
+
33
+ class F
34
+ attr_accessor :attr_name
35
+ attr_accessor :klass
36
+ attr_accessor :operator
37
+ attr_accessor :operand
38
+
39
+ def initialize(attr_name)
40
+ self.attr_name = attr_name.to_s
41
+ end
42
+
43
+ def to_sql(formatter = nil)
44
+ self.klass ||= formatter.environment.relation.klass
45
+ sql = klass.my_quote_columns(attr_name)
46
+ if operator && operand
47
+ operand.klass = klass if operand.is_a?(F)
48
+ sql << " #{ operator } #{ operand.is_a?(F) ? operand.to_sql(formatter) : klass.connection.quote(operand) }"
49
+ end
50
+ sql
51
+ end
52
+
53
+ def empty?
54
+ false
55
+ end
56
+
57
+ %w(+ - * /).each do |op|
58
+ define_method(op) do |arg|
59
+ self.operator = op
60
+ self.operand = arg
61
+ self
62
+ end
63
+ end
64
+ end
65
+
66
+ def F(attr_name)
67
+ F.new(attr_name)
68
+ end
69
+
70
+ if $PROGRAM_NAME == __FILE__
71
+ require File.expand_path('../../config/environment', __FILE__)
72
+ end
73
+
74
+ module ActiveRecord
75
+ class Base
76
+ def self.my_quote_columns(*column_names)
77
+ quoted_table_name = connection.quote_table_name(table_name)
78
+ column_names.map { |column_name| "#{ quoted_table_name }.#{ connection.quote_column_name(column_name) }" }.join(", ")
79
+ end
80
+ end
81
+ end
82
+
83
+ module ActiveRecord
84
+ module ConnectionAdapters #:nodoc:
85
+ class Column
86
+ def type_cast_with_f_object(value)
87
+ return value if value.is_a?(F)
88
+ type_cast_without_f_object(value)
89
+ end
90
+
91
+ alias_method_chain_once :type_cast, :f_object
92
+ end
93
+ end
94
+
95
+
96
+ class Relation
97
+ def build_where_with_f_object(*args)
98
+ if args.size == 1 && args[0].is_a?(Hash)
99
+ hash_conditions = args[0]
100
+ hash_conditions.each { |_, v| v.klass = klass if v.is_a?(F) }
101
+ end
102
+
103
+ build_where_without_f_object(*args)
104
+ end
105
+
106
+ alias_method_chain_once :build_where, :f_object
107
+ end
108
+
109
+ class Base
110
+ class << self
111
+ def sanitize_sql_hash_for_assignment_with_f_object(assignments)
112
+ f_assignments, normal_assignments = assignments.partition { |_, v| v.is_a?(F) }
113
+
114
+ f_sql = f_assignments.map do |attr, f_obj|
115
+ "#{connection.quote_column_name(attr)} = #{connection.quote_column_name(f_obj.attr_name)}"
116
+ end.join(", ")
117
+
118
+ normal_sql = sanitize_sql_hash_for_assignment_without_f_object(normal_assignments)
119
+
120
+ [(f_sql if f_sql.present?), (normal_sql if normal_sql.present?)].compact.join(", ")
121
+ end
122
+
123
+ alias_method_chain_once :sanitize_sql_hash_for_assignment, :f_object
124
+ end
125
+ end
126
+
127
+ module AttributeMethods
128
+ module Write
129
+ def write_attribute_with_f_object(attr_name, value)
130
+ write_attribute_without_f_object(attr_name, value)
131
+
132
+ # cancel number and any other type of conversions
133
+ if value.is_a?(F)
134
+ value.klass = self.class
135
+ @attributes[attr_name] = value
136
+ end
137
+ end
138
+
139
+ alias_method_chain_once :write_attribute, :f_object
140
+ end
141
+
142
+ module TimeZoneConversion
143
+ module ClassMethods
144
+ def define_method_attribute_with_f_object=(attr_name)
145
+ send(:define_method_attribute_without_f_object=, attr_name)
146
+
147
+ method_body, line = <<-EOV, __LINE__ + 1
148
+ def #{attr_name}_with_f_object=(time)
149
+ if time.is_a?(F)
150
+ time.klass = self.class
151
+ write_attribute(:#{attr_name}, time)
152
+ else
153
+ send(:#{attr_name}_without_f_object=, time)
154
+ end
155
+ end
156
+
157
+ alias_method_chain_once :#{attr_name}=, :f_object unless respond_to?(:#{attr_name}_without_f_object=)
158
+ EOV
159
+ generated_attribute_methods.module_eval(method_body, __FILE__, line)
160
+ end
161
+
162
+ alias_method_chain_once :define_method_attribute=, :f_object
163
+ end
164
+ end
165
+ end
166
+ end
167
+
168
+ if $PROGRAM_NAME == __FILE__
169
+ class User < ActiveRecord::Base
170
+ end
171
+
172
+ require 'rspec/core'
173
+ require 'rspec/expectations'
174
+ require 'rspec/matchers'
175
+
176
+ Rspec.configure do |c|
177
+ c.mock_with :rspec
178
+ end
179
+
180
+ describe F do
181
+ Rspec::Matchers.define :end_with do |expected|
182
+ match do |actual|
183
+ actual.end_with?(expected)
184
+ end
185
+ end
186
+
187
+ specify { User.where(:updated_at => F(:created_at)).to_sql.should
188
+ end_with("(`users`.`updated_at` = `users`.`created_at`)") }
189
+
190
+ specify { User.where(:updated_at => F(:created_at) + 1).to_sql.should
191
+ end_with("(`users`.`updated_at` = `users`.`created_at` + 1)") }
192
+
193
+ specify { User.where(:updated_at => F(:created_at) + F(:updated_at)).to_sql.should
194
+ end_with("(`users`.`updated_at` = `users`.`created_at` + `users`.`updated_at`)") }
195
+
196
+ specify { User.where(:updated_at => F(:created_at) + F(:updated_at)).to_sql.should
197
+ end_with("(`users`.`updated_at` = `users`.`created_at` + `users`.`updated_at`)") }
198
+
199
+ def update_sql(f_obj)
200
+ id_attr = User.scoped.arel_table.find_attribute_matching_name("id")
201
+ Arel::Update.new(User.scoped, id_attr => f_obj).to_sql.strip
202
+ end
203
+
204
+ specify { update_sql(F(:di)).should
205
+ end_with("SET `id` = `users`.`di`") }
206
+
207
+ specify { update_sql(F(:di) + 1).should
208
+ end_with("SET `id` = `users`.`di` + 1") }
209
+
210
+ specify { update_sql(F(:di) + F(:id)).should
211
+ end_with("SET `id` = `users`.`di` + `users`.`id`") }
212
+ end
213
+ end
@@ -0,0 +1,176 @@
1
+ # Django Q object for Rails 2, 3
2
+ # http://docs.djangoproject.com/en/dev/topics/db/queries/#complex-lookups-with-q-objects
3
+ #
4
+ # Let's you build ORed, ANDed, and negated conditions without dropping to
5
+ # writing SQL.
6
+ #
7
+ # User.where(~Q(:user_id => nil))
8
+ #
9
+ # instead of User.where("user_id IS NOT NULL")
10
+ #
11
+ # User.where(Q(:user_id => nil) | Q(:id => nil))
12
+ #
13
+ # instead of User.where("user_id IS NULL OR id IS NULL")
14
+ #
15
+ # User.where(~(Q(:user_id => nil) & Q(:id => nil)))
16
+ #
17
+ # instead of User.where("user_id IS NOT NULL AND id IS NOT NULL")
18
+ #
19
+ # On Ruby 1.9 Object#! can be used to negate conditions
20
+ #
21
+ # User.where(!Q(:user_id => nil))
22
+ #
23
+
24
+ require "require_gist"; require_gist "383954/ea5a41269aac073b596b21fe392098827186a32b/alias_method_chain_once.rb", "a6f068593bb45fe6c9956205f672ac4a0c2e1671" # http://gist.github.com/383954
25
+
26
+ class Q
27
+ def |(other)
28
+ OrQ.new(self, other)
29
+ end
30
+
31
+ def &(other)
32
+ AndQ.new(self, other)
33
+ end
34
+
35
+ def ~
36
+ NotQ.new(self)
37
+ end
38
+
39
+ alias_method "!", "~"
40
+ end
41
+
42
+ class BinaryQ < Q
43
+ attr_accessor :op1, :op2
44
+
45
+ def initialize(op1, op2)
46
+ self.op1, self.op2 = op1, op2
47
+ end
48
+
49
+ def empty?
50
+ false
51
+ end
52
+ end
53
+
54
+ class UnaryQ < Q
55
+ attr_accessor :op1
56
+
57
+ def initialize(*args)
58
+ self.op1 = (args.size == 1 ? args[0] : args)
59
+ end
60
+
61
+ def to_q_sql(klass)
62
+ klass.send(:sanitize_sql, op1)
63
+ end
64
+
65
+ def empty?
66
+ op1.empty?
67
+ end
68
+ end
69
+
70
+ class AndQ < BinaryQ
71
+ def to_q_sql(klass)
72
+ "(#{ op1.to_q_sql(klass) }) AND (#{ op2.to_q_sql(klass) })"
73
+ end
74
+ end
75
+
76
+ class NotQ < UnaryQ
77
+ def to_q_sql(klass)
78
+ "(NOT (#{ op1.to_q_sql(klass) }))"
79
+ end
80
+ end
81
+
82
+ class OrQ < BinaryQ
83
+ def to_q_sql(klass)
84
+ "(#{ op1.to_q_sql(klass) }) OR (#{ op2.to_q_sql(klass) })"
85
+ end
86
+ end
87
+
88
+ def Q(*args)
89
+ UnaryQ.new(*args)
90
+ end
91
+
92
+ if $PROGRAM_NAME == __FILE__
93
+ require File.expand_path('../../config/environment', __FILE__)
94
+ end
95
+
96
+ module ActiveRecord
97
+ if defined?(Relation)
98
+ # Rails 3
99
+ class Relation
100
+ def build_where_with_q_object(*args)
101
+ if args.size == 1 && args[0].is_a?(Q)
102
+ return args[0].to_q_sql(klass)
103
+ end
104
+
105
+ build_where_without_q_object(*args)
106
+ end
107
+
108
+ alias_method_chain_once :build_where, :q_object
109
+ end
110
+ else
111
+ # Rails 2
112
+ class Base
113
+ class << self
114
+ def sanitize_sql_for_conditions_with_q_object(*args)
115
+ if args.size == 1 && args[0].is_a?(Q)
116
+ return args[0].to_q_sql(klass)
117
+ end
118
+
119
+ sanitize_sql_for_conditions_without_q_object(*args)
120
+ end
121
+
122
+ alias_method_chain_once :sanitize_sql_for_conditions, :q_object
123
+ end
124
+ end
125
+ end
126
+ end
127
+
128
+ module ActiveRecord
129
+ class Base
130
+ def self.Q(*args)
131
+ UnaryQ.new(*args).to_q_sql(self)
132
+ end
133
+ end
134
+ end
135
+
136
+ if $PROGRAM_NAME == __FILE__
137
+ class User < ActiveRecord::Base
138
+ end
139
+
140
+ require 'rspec/expectations'
141
+ require 'rspec/core'
142
+
143
+ Rspec.configure do |c|
144
+ c.mock_with :rspec
145
+ end
146
+
147
+ describe Q do
148
+ Rspec::Matchers.define :be_like_conditions do |expected|
149
+ match do |actual|
150
+ actual.to_q_sql(User) == expected
151
+ end
152
+ end
153
+
154
+ it { Q(:email => nil).should
155
+ be_like_conditions("`users`.`email` IS NULL") }
156
+
157
+ it { (~Q(:user_id => nil)).should
158
+ be_like_conditions("(NOT (`users`.`user_id` IS NULL))") }
159
+
160
+ it { (!Q(:user_id => nil)).should
161
+ be_like_conditions("(NOT (`users`.`user_id` IS NULL))") }
162
+
163
+ it { (User.Q(:is_avatar => nil)).should == "`users`.`is_avatar` IS NULL" }
164
+
165
+ it { (User.Q("name LIKE :like OR email LIKE :like", :like => "%#{ 42 }%")).should == "name LIKE '%42%' OR email LIKE '%42%'" }
166
+
167
+ it { (Q(:league_id => nil) & Q("path LIKE ?", "prefix/%")).should
168
+ be_like_conditions("(`users`.`league_id` IS NULL) AND (path LIKE 'prefix/%')") }
169
+
170
+ it { (Q(:to_account_id => 2) | Q(:from_account_id => 1)).should
171
+ be_like_conditions("(`users`.`to_account_id` = 2) OR (`users`.`from_account_id` = 1)") }
172
+
173
+ it { (!Q(:user_id => nil) & Q(:email => nil)).should
174
+ be_like_conditions("((NOT (`users`.`user_id` IS NULL)) AND (`users`.`email` IS NULL)") }
175
+ end
176
+ end
@@ -0,0 +1,169 @@
1
+ # Formats the Exception so that it looks *familiar*,
2
+ # i.e. exactly like your interpreter does it.
3
+ #
4
+ # Port of MRI native `error_print` function.
5
+ class Exception
6
+ require "English"
7
+
8
+ def self.error_print(e = $ERROR_INFO)
9
+ warn_print = ""
10
+ backtrace = e.backtrace
11
+ backtrace = [ backtrace ] if backtrace.is_a?(String) # 1.9 returns single String for SystemStackError
12
+
13
+ warn_print << backtrace[0]
14
+ if e.is_a?(RuntimeError) && e.message.empty?
15
+ warn_print << ": unhandled exception\n"
16
+ else
17
+ if e.message.empty?
18
+ warn_print << ": #{ e.class.name }\n"
19
+ else
20
+ split_message = e.message.split("\n")
21
+ warn_print << ": "
22
+ if split_message.size == 1
23
+ warn_print << "#{ e.message } (#{ e.class.name })\n"
24
+ else
25
+ warn_print << split_message[0]
26
+ warn_print << " (#{ e.class.name })\n"
27
+ warn_print << split_message[1..-1].join("\n").chomp << "\n"
28
+ end
29
+ end
30
+ end
31
+
32
+ len = backtrace.size
33
+
34
+ # int skip = eclass == rb_eSysStackError;
35
+ skip = e.is_a?(SystemStackError)
36
+
37
+ # #define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5)
38
+ # #define TRACE_HEAD 8
39
+ # #define TRACE_TAIL 5
40
+ trace_head = 8
41
+ trace_tail = 5
42
+ trace_max = (trace_head + trace_tail + 5)
43
+ #
44
+ # for (i = 1; i < len; i++) {
45
+ i = 1
46
+ while i < len
47
+ # if (TYPE(ptr[i]) == T_STRING) {
48
+ # warn_printf("\tfrom %s\n", RSTRING_PTR(ptr[i]));
49
+ # }
50
+ warn_print << "\tfrom %s\n" % e.backtrace[i]
51
+
52
+ # if (skip && i == TRACE_HEAD && len > TRACE_MAX) {
53
+ if skip && i == trace_head && len > trace_max
54
+ # warn_printf("\t ... %ld levels...\n",
55
+ # len - TRACE_HEAD - TRACE_TAIL);
56
+ warn_print << "\t ... %d levels...\n" % (len - trace_head - trace_tail)
57
+ # i = len - TRACE_TAIL;
58
+ i = len - trace_tail
59
+ # }
60
+ end
61
+ # }
62
+ i += 1
63
+ end
64
+ warn_print
65
+ end
66
+ end
67
+
68
+
69
+ if $PROGRAM_NAME == __FILE__
70
+ if ARGV.empty?
71
+ # Main test suite runner
72
+ require "spec"
73
+ require "require_gist"; require_gist "371861/7dbcff4b266451b70cca183ce24917340587e8d3/shell_out.rb", "1e8bbc0ef3d1d078a4e57eb03225913c3a1e4fe5" # http://gist.github.com/371861
74
+
75
+ describe "Exception.error_print" do
76
+ include ShellOut
77
+ %w(normal
78
+ multiline
79
+ empty_message
80
+ non_empty_message
81
+ runtime_empty
82
+ runtime_non_empty
83
+ sys_stack).each do |type|
84
+ it "outputs the same message as the native interpreter does for #{ type } exception" do
85
+ native = shell_out("ruby #{ __FILE__ } native raise_#{ type }", :out => :return)
86
+
87
+ native.should include(__FILE__)
88
+
89
+ error_printed = shell_out("ruby #{ __FILE__ } error_print raise_#{ type }", :out => :return)
90
+
91
+ error_printed.should include(__FILE__)
92
+
93
+ error_printed.should == native
94
+ end
95
+ end
96
+
97
+ end
98
+ exit ::Spec::Runner::CommandLine.run
99
+ else
100
+ # Helper
101
+ def raise_normal
102
+ f10
103
+ end
104
+
105
+ def raise_multiline
106
+ raise "qwe\nasd\nzxc"
107
+ end
108
+
109
+ def raise_empty_message
110
+ raise ArgumentError, ""
111
+ end
112
+
113
+ def raise_non_empty_message
114
+ raise ArgumentError, "qwe"
115
+ end
116
+
117
+ def raise_runtime_empty
118
+ raise
119
+ end
120
+
121
+ def raise_runtime_non_empty
122
+ raise RuntimeError, "runtime non empty"
123
+ end
124
+
125
+ def raise_sys_stack
126
+ baz
127
+ end
128
+
129
+ # puts (0..20).map { |i| "def f#{i}() f#{i+1}(); end"}.join("\n")
130
+ def f0() f1(); end
131
+ def f1() f2(); end
132
+ def f2() f3(); end
133
+ def f3() f4(); end
134
+ def f4() f5(); end
135
+ def f5() f6(); end
136
+ def f6() f7(); end
137
+ def f7() f8(); end
138
+ def f8() f9(); end
139
+ def f9() f10(); end
140
+ def f10() f11(); end
141
+ def f11() f12(); end
142
+ def f12() f13(); end
143
+ def f13() f14(); end
144
+ def f14() f15(); end
145
+ def f15() f16(); end
146
+ def f16() f17(); end
147
+ def f17() f18(); end
148
+ def f18() f19(); end
149
+ def f19() f20(); end
150
+ def f20
151
+ raise(ArgumentError, "multi\nline\nerror")
152
+ end
153
+
154
+
155
+ def foo; bar; end; def bar; foo; end; def baz; foo; end;
156
+
157
+ class NonExistingException < Exception
158
+ end
159
+
160
+ begin
161
+ eval ARGV[1]
162
+ # we need to keep the same backtraces to make comparison adequate
163
+ # since NonExistingException will never be raised - the exception
164
+ # will propagate to the top level and interpreter will do it's job
165
+ rescue (ARGV[0] == "native" ? NonExistingException : Exception) => e
166
+ puts Exception.error_print
167
+ end
168
+ end
169
+ end
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Usage: ./gist_readme.rb source_file.rb [README.md]
4
+ #
5
+ # Extracts first comment block from source_file.rb into README.md file
6
+ #
7
+ #
8
+ raise "source_file should be specified" if ARGV.empty?
9
+
10
+ File.open(File.expand_path(File.join("../", ARGV[1] || "README.md") , __FILE__), "w") do |f|
11
+ first_comment = []
12
+ IO.read(File.expand_path(File.join("../", ARGV[0]), __FILE__)).each_line do |l|
13
+ if l =~ /\s*#/
14
+ first_comment << l.sub(/^\s*#\s/, "").rstrip
15
+ elsif !first_comment.empty?
16
+ break
17
+ end
18
+ end
19
+ f.write(first_comment.join("\n"))
20
+ end
@@ -0,0 +1,106 @@
1
+ # Check Thomas Sawyer take on the problem http://github.com/rubyworks/paramix
2
+ module IncludableWithOptions
3
+ class << self
4
+ attr_accessor :last_default_options
5
+ end
6
+
7
+ def self.included(includable_with_options)
8
+ %w(string/methodize kernel/constant module/basename module/spacename).each { |facets_core_ext| require "facets/#{ facets_core_ext }" }
9
+
10
+ raise "IncludableWithOptions should be included by the Module" unless includable_with_options.instance_of?(Module)
11
+
12
+ options_class_var_name = "@@#{ includable_with_options.basename.methodize }_options"
13
+
14
+ unless IncludableWithOptions.last_default_options.nil?
15
+ includable_with_options.send(:class_variable_set, options_class_var_name, IncludableWithOptions.last_default_options)
16
+ IncludableWithOptions.last_default_options = nil
17
+ end
18
+
19
+ context = Kernel.constant(includable_with_options.spacename)
20
+
21
+ option_setting_duplicator = <<-CODE
22
+ def #{ context != Kernel ? "self." : "" }#{ includable_with_options.basename }(options = nil)
23
+ m = Kernel.constant("#{ includable_with_options.name }").dup
24
+ m.send(:class_variable_set, "#{ options_class_var_name }", options)
25
+ m
26
+ end
27
+ CODE
28
+
29
+ context.module_eval(option_setting_duplicator)
30
+ end
31
+ end
32
+
33
+ def IncludableWithOptions(options = {})
34
+ m = Kernel.const_get(:IncludableWithOptions).dup
35
+ # Because of Ruby bug (?) model function +included+ won't be able to access @@default_options:
36
+ # http://redmine.ruby-lang.org/issues/show/3080
37
+ # m.send(:class_variable_set, :@@default_options, options[:default])
38
+ IncludableWithOptions.last_default_options = options[:default]
39
+ m
40
+ end
41
+
42
+ if $PROGRAM_NAME == __FILE__
43
+
44
+ module MyStuff
45
+ module SystemWithTweaks
46
+ include IncludableWithOptions(:default => {})
47
+
48
+ def system(*args)
49
+ puts "@@system_with_tweaks_options #{ @@system_with_tweaks_options }"
50
+ puts "Executing command: #{ args.join(" ") }" if @@system_with_tweaks_options[:echo]
51
+ result = Kernel.system(*args)
52
+ raise "Command #{ args.join(" ") } exited with a nonzero exit status" if @@system_with_tweaks_options[:raise_exceptions]
53
+ result
54
+ end
55
+ end
56
+ end
57
+
58
+ module MyStuff
59
+ class D
60
+ include MyStuff::SystemWithTweaks(:asd => 123)
61
+
62
+ def m
63
+ system "echo 'just echoing'"
64
+ end
65
+ end
66
+ end
67
+
68
+
69
+ module SystemWithTweaks
70
+ include IncludableWithOptions(:default => { :echo => true })
71
+
72
+ def system(*args)
73
+ puts "Executing command: #{ args.join(" ") }" if @@system_with_tweaks_options[:echo]
74
+ result = Kernel.system(*args)
75
+ raise "Command #{ args.join(" ") } exited with a nonzero exit status" if @@system_with_tweaks_options[:raise_exceptions]
76
+ result
77
+ end
78
+ end
79
+
80
+ class C
81
+ include SystemWithTweaks(:echo => true)
82
+
83
+ def m
84
+ system "ls"
85
+ end
86
+ end
87
+
88
+ module MyStuff
89
+ class B
90
+ include MyStuff::SystemWithTweaks(:raise_exceptions => true)
91
+
92
+ def m
93
+ system "does_not_exist"
94
+ end
95
+ end
96
+ end
97
+
98
+ puts "Top level include with options"
99
+ C.new.m
100
+
101
+ puts "Namespaced include without options"
102
+ MyStuff::D.new.m
103
+
104
+ puts "Namespaced include with options"
105
+ MyStuff::B.new.m
106
+ end