dolzenko 0.0.10 → 0.0.11

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/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