adamtanner-terror 0.3.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.
@@ -0,0 +1,2 @@
1
+ .DS_Store
2
+ *.swp
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Adam Tanner
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,49 @@
1
+ !! TERROR !!
2
+
3
+ Terror allows you to define your errors/exceptions in a pretty run-of-the-mill style DSL.
4
+
5
+ Reasons Terror exists:
6
+
7
+ * Because defining errors as subclasses of StandardError looks ugly.
8
+ * Also, because I wanted to make a pseudo-useful DSL.
9
+
10
+ How to use Terror:
11
+
12
+ For times where all you need is a pretty name to raise.
13
+
14
+ exceptions :exceptionally, "exceptional"
15
+
16
+
17
+ If you need a little more control over your exceptions you can use a block.
18
+ The methods inside the block become camel-cased exceptions where the method name
19
+ is the exception name.
20
+
21
+ exceptions do
22
+ there_is_no_exception "You did wrong. There is no exception!"
23
+ end
24
+
25
+ The argument passed to the method is the message you want to use when you raise the exception.
26
+ For the example above you would do:
27
+
28
+ raise ThereIsNoException, ThereIsNoException.message
29
+
30
+ If you need even more control over your exceptions and want to add custom functionality you can
31
+ pass the method a block and insert whatever code you want available for the exception.
32
+
33
+ exceptions do
34
+ my_exception do
35
+ def handle_my_exception()
36
+ return "Check that out, I can add my own methods!"
37
+ end
38
+ end
39
+ end
40
+
41
+ And, of course, all of these can be done together in the same exceptions method if you need more,
42
+ or less, functionality for different exceptions.
43
+
44
+ Things I'd Like to Get Around to Doing:
45
+
46
+ * Making this a gem.
47
+ * Writing tests. (In progress)
48
+
49
+ That's all folks.
@@ -0,0 +1,13 @@
1
+ begin
2
+ require 'jeweler'
3
+ Jeweler::Tasks.new do |gem|
4
+ gem.name = "terror"
5
+ gem.summary = "Because defining exceptions as subclasses of StandardError looks ugly."
6
+ gem.description = "Because defining exceptions as subclasses of StandardError looks ugly."
7
+ gem.email = "adam@adamtanner.org"
8
+ gem.homepage = "http://github.com/adamtanner/terror"
9
+ gem.authors = ["Adam Tanner"]
10
+ end
11
+ rescue LoadError
12
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
13
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.3.0
@@ -0,0 +1,48 @@
1
+ module Terror
2
+ def self.included(base)
3
+ base.send(:include, Terror::InstanceMethods)
4
+ base.send(:extend, Terror::ClassMethods)
5
+ Terror.base_class = base
6
+ end
7
+
8
+ class ErrorBuilder
9
+ def method_missing(method, *arguments, &block)
10
+ return Terror.base_class.new.send(method, *arguments) if Terror.base_class.new.respond_to?(method)
11
+ return Terror.base_class.send(method, *arguments) if Terror.base_class.respond_to?(method)
12
+ error_class = Terror.base_class.const_set(Terror.camelize(method), Class.new(StandardError))
13
+ error_class.class_eval(&block) if block_given?
14
+ message, arguments = arguments
15
+ if message
16
+ error_class.class_eval %{ class << self; self.send(:define_method, :message) { "#{message}" }; end }
17
+ end
18
+ end
19
+ end
20
+
21
+ module ClassMethods
22
+ def exceptions(*exceptions, &block)
23
+ Terror::ErrorBuilder.new.instance_eval(&block) if block_given?
24
+
25
+ exceptions.each do |exception|
26
+ Terror.base_class.const_set(Terror.camelize(exception), Class.new(StandardError))
27
+ end
28
+ end
29
+ end
30
+
31
+ module InstanceMethods
32
+
33
+ end
34
+
35
+ private
36
+ # @see Lifted from the Rails Inflector.
37
+ def self.camelize(string)
38
+ string.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
39
+ end
40
+
41
+ def self.base_class=(base)
42
+ @@base_class = base
43
+ end
44
+
45
+ def self.base_class
46
+ @@base_class
47
+ end
48
+ end
@@ -0,0 +1,68 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
2
+
3
+ require 'terror'
4
+
5
+ describe Terror do
6
+ before(:all) do
7
+ TestClass = Class.new
8
+ TestClass.send(:include, Terror)
9
+ end
10
+
11
+ it "should take a symbol and convert it to an exception" do
12
+ TestClass.exceptions :exception_from_symbol
13
+ TestClass.constants.should include("ExceptionFromSymbol")
14
+ end
15
+
16
+ it "should take a string and convert it to an exception" do
17
+ TestClass.exceptions "ExceptionFromString"
18
+ TestClass.constants.should include("ExceptionFromString")
19
+ end
20
+
21
+ it "should convert the method in the block to an exception" do
22
+ TestClass.exceptions { exception_from_block }
23
+ TestClass.constants.should include("ExceptionFromBlock")
24
+ end
25
+
26
+ it "should assign the message from the method in the block" do
27
+ TestClass.exceptions { exception_from_block_with_message "Message from exception." }
28
+ TestClass::ExceptionFromBlockWithMessage.message.should match("Message from exception.")
29
+ end
30
+
31
+ it "should evaluate the block given to the method in the context of the exception" do
32
+ TestClass.exceptions do
33
+ exception_with_custom_code do
34
+ def custom_handle
35
+ end
36
+ end
37
+ end
38
+ TestClass::ExceptionWithCustomCode.new.should respond_to(:custom_handle)
39
+ end
40
+
41
+ it "should evaluate instance methods from the base class from within the block" do
42
+ TestClass.send(:define_method, :message_from_base_class) { return "This is a message from the base class!" }
43
+ TestClass.exceptions do
44
+ exception_with_message_from_helper message_from_base_class
45
+ end
46
+ TestClass::ExceptionWithMessageFromHelper.message.should match("This is a message from the base class!")
47
+ end
48
+
49
+ it "should evaluate singleton methods from the base class from within the block" do
50
+ TestClass.class_eval %{ def self.message_from_base_class; return "This is a message from the base class!"; end }
51
+ TestClass.exceptions do
52
+ exception_with_message_from_class_helper message_from_base_class
53
+ end
54
+ TestClass::ExceptionWithMessageFromClassHelper.message.should match("This is a message from the base class!")
55
+ end
56
+
57
+ it "should evaluate methods with arguments from the base class from within the block" do
58
+ TestClass.send(:define_method, :message_from_base_class_with_arguments) do |first, second, third|
59
+ "This is my message. I love #{first} #{second} #{third}!"
60
+ end
61
+ TestClass.exceptions do
62
+ exception_with_message_from_helper_with_arguments message_from_base_class_with_arguments("super", "long", "methods")
63
+ end
64
+ TestClass::ExceptionWithMessageFromHelperWithArguments.message.
65
+ should match("This is my message. I love super long methods!")
66
+ end
67
+ end
68
+
metadata ADDED
@@ -0,0 +1,61 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: adamtanner-terror
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.0
5
+ platform: ruby
6
+ authors:
7
+ - Adam Tanner
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-08-31 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Because defining exceptions as subclasses of StandardError looks ugly.
17
+ email: adam@adamtanner.org
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - LICENSE
24
+ - README.markdown
25
+ files:
26
+ - .gitignore
27
+ - LICENSE
28
+ - README.markdown
29
+ - Rakefile
30
+ - VERSION
31
+ - lib/terror.rb
32
+ - spec/terror_spec.rb
33
+ has_rdoc: true
34
+ homepage: http://github.com/adamtanner/terror
35
+ licenses:
36
+ post_install_message:
37
+ rdoc_options:
38
+ - --charset=UTF-8
39
+ require_paths:
40
+ - lib
41
+ required_ruby_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: "0"
46
+ version:
47
+ required_rubygems_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: "0"
52
+ version:
53
+ requirements: []
54
+
55
+ rubyforge_project:
56
+ rubygems_version: 1.3.5
57
+ signing_key:
58
+ specification_version: 2
59
+ summary: Because defining exceptions as subclasses of StandardError looks ugly.
60
+ test_files:
61
+ - spec/terror_spec.rb