subtle 0.3.4

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rvmrc ADDED
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # This is an RVM Project .rvmrc file, used to automatically load the ruby
4
+ # development environment upon cd'ing into the directory
5
+
6
+ # First we specify our desired <ruby>[@<gemset>], the @gemset name is optional.
7
+ environment_id="ruby-1.9.3-p0@subtle"
8
+
9
+ #
10
+ # Uncomment following line if you want options to be set only for given project.
11
+ #
12
+ # PROJECT_JRUBY_OPTS=( --1.9 )
13
+
14
+ #
15
+ # First we attempt to load the desired environment directly from the environment
16
+ # file. This is very fast and efficient compared to running through the entire
17
+ # CLI and selector. If you want feedback on which environment was used then
18
+ # insert the word 'use' after --create as this triggers verbose mode.
19
+ #
20
+ if [[ -d "${rvm_path:-$HOME/.rvm}/environments" \
21
+ && -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
22
+ then
23
+ \. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
24
+
25
+ if [[ -s "${rvm_path:-$HOME/.rvm}/hooks/after_use" ]]
26
+ then
27
+ . "${rvm_path:-$HOME/.rvm}/hooks/after_use"
28
+ fi
29
+ else
30
+ # If the environment file has not yet been created, use the RVM CLI to select.
31
+ if ! rvm --create "$environment_id"
32
+ then
33
+ echo "Failed to create RVM environment '${environment_id}'."
34
+ return 1
35
+ fi
36
+ fi
37
+
38
+ #
39
+ # If you use an RVM gemset file to install a list of gems (*.gems), you can have
40
+ # it be automatically loaded. Uncomment the following and adjust the filename if
41
+ # necessary.
42
+ #
43
+ # filename=".gems"
44
+ # if [[ -s "$filename" ]]
45
+ # then
46
+ # rvm gemset import "$filename" | grep -v already | grep -v listed | grep -v complete | sed '/^$/d'
47
+ # fi
48
+
49
+ # If you use bundler, this might be useful to you:
50
+ # if command -v bundle && [[ -s Gemfile ]]
51
+ # then
52
+ # bundle install
53
+ # fi
54
+
55
+
data/.travis.yml ADDED
@@ -0,0 +1,12 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.2
5
+ - 1.9.3
6
+ - jruby-18mode
7
+ - jruby-19mode
8
+ - rbx-18mode
9
+ - rbx-19mode
10
+ - ruby-head
11
+ - jruby-head
12
+ - ree
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ gem 'blankslate'
6
+ gem 'mocha'
7
+
8
+
9
+ gem 'minitest'
10
+ group :development do
11
+ gem 'guard'
12
+ gem 'guard-minitest', :git => 'git://github.com/aspiers/guard-minitest.git'
13
+ gem 'ruby_gntp'
14
+ end
data/Guardfile ADDED
@@ -0,0 +1,12 @@
1
+ guard 'minitest' do
2
+ watch(%r|^test/test_(.*)\.rb|)
3
+ watch(%r|^lib/(.*)([^/]+)\.rb|) { |m| "test/#{m[1]}test_#{m[2]}.rb" }
4
+ watch(%r|^test/test_helper\.rb|) { "test" }
5
+ watch(%r|^lib/(.*)\.rb|) { |m| "test/test_#{m[1]}.rb" }
6
+
7
+ watch(%r{^spec/.+_spec\.rb$})
8
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
9
+ watch(%r{^lib/subtle/(.+)\.rb$}) { |m| "spec/subtle/#{m[1]}_spec.rb" }
10
+ watch(%r{^spec/models/.+\.rb$}) { ["spec/models", "spec/acceptance"] }
11
+ watch('spec/spec_helper.rb') { "spec" }
12
+ end
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Darren Cauthon
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,123 @@
1
+ # Subtle
2
+
3
+
4
+
5
+ I don't like "grab-bag" method libraries any more than anybody, but also like everybody: I'll make an exception for **MINE**. :)
6
+
7
+ ## Installation
8
+ Add this line to your application's Gemfile:
9
+
10
+ gem 'subtle'
11
+
12
+ And then execute:
13
+
14
+ $ bundle
15
+
16
+ Or install it yourself as:
17
+
18
+ gem install subtle
19
+
20
+ ## Usage
21
+
22
+ ### Arrays to Objects
23
+
24
+ This feature exists to make the creation of sets of objects with data easily.
25
+
26
+ * Create an array of symbols of symbols that match the properties on the objects you want, and
27
+ * Pass a block that returns an array of arrays with matching data.
28
+
29
+ ````ruby
30
+ records = [:first_name, :last_name].to_objects {
31
+ [
32
+ ["John", "Galt"],
33
+ ["Howard", "Roark"],
34
+ ["Dagny", "Taggart"]
35
+ ]}
36
+
37
+ records[0].first_name # "John"
38
+ records[0].last_name # "Galt"
39
+
40
+ records[1].first_name # "Howard"
41
+ records[1].last_name # "Roark"
42
+
43
+ records[2].first_name # "Dagny"
44
+ records[2].last_name # "Taggart"
45
+ ````
46
+
47
+ ### Safety Proc
48
+
49
+ This feature was written because I hate wrapping code in begin/rescue/end blocks. If I have a line of code and I don't particularly care if it fails, I have to wrap it in three more lines of care to stop exceptions.
50
+
51
+ To me, this is most useful in import work or one-off processes where I might want to check to run a small block of code regardless of whether it fails. This could lead to less code not just because of the lost begin/rescue/end lines, but because code can be written without concern of whether it will fail (nil checks, etc.).
52
+
53
+ ````ruby
54
+ person.name = document.at_xpath('./h1').text
55
+
56
+ # if this call fails then we will move on
57
+ -> { person.bio = document.xpath('./div[@class="bio_info"]//span').text }.call_safely
58
+
59
+ # if this call fails then the second block will be called
60
+ -> { person.special = document.xpath('./div[@class="active"]//a')[1].text == "special" }.call_safely { person.special = false }
61
+ ````
62
+
63
+ ### Param Constructor
64
+
65
+ One thing I liked about C# was the ability to instantiate my objects like this:
66
+
67
+ ````c#
68
+ var person = new Person() { FirstName = "John", LastName = "Galt" };
69
+ ````
70
+
71
+ This syntax is not built into Ruby syntax today, but it does exist in Rails models. So I took that idea from Rails and wrote an implementation that works like this:
72
+
73
+ ````ruby
74
+ class Person
75
+ params_constructor
76
+ attr_accessor :first_name, :last_name
77
+ end
78
+
79
+ person = Person.new(first_name: "John", last_name: "Galt")
80
+ ````
81
+
82
+ ### Proc to Object
83
+
84
+ I was inspired to write this feature while dealing with some bad Rails code. A programmer wrote a before_filter on ApplicationController that made a big, expensive web service call to pass the users current weather information to the view. This weather information was shown in various places on the site, but there were many pages on the site where the data was not being used at all.
85
+
86
+ A thought came to me... *would it be possible to create an object that does the work to instantiate itself, but only when it is referenced?*
87
+
88
+ Well, this doesn't quite do that, but it's close. It lets you turn this:
89
+
90
+ ````ruby
91
+ before_filter do
92
+ service = BigExpensiveWeatherService.new
93
+ # we just paid the price right now
94
+ @weather_results = service.an_expensive_web_call
95
+ end
96
+ ````
97
+
98
+ into this:
99
+
100
+ ````ruby
101
+ before_filter do
102
+ # we haven't paid the price for this call
103
+ @weather_results = -> do
104
+ service = BigExpensiveWeatherService.new
105
+ service.an_expensive_web_call
106
+ end.to_object
107
+ end
108
+ ````
109
+
110
+ With both, you could do this:
111
+
112
+ ````haml
113
+ %span
114
+ = @weather_results.temperature
115
+ ````
116
+
117
+ But with the latter, the call to execute the big web service won't be made until .temperature is called. Future calls to methods on @weather_results will use the same object passed from the Proc.
118
+
119
+ I know, I know... there are lots of reasons **NOT** to do this, and I'm not saying to do this all the time, but it's neat to know that it is possible.
120
+
121
+
122
+
123
+
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rake/testtask'
3
+
4
+ task :default => [:test]
5
+
6
+ Rake::TestTask.new do |t|
7
+ t.libs.push "lib"
8
+ t.test_files = FileList['spec/subtle/*_spec.rb']
9
+ t.verbose = true
10
+ end
data/lib/subtle.rb ADDED
@@ -0,0 +1,6 @@
1
+ require File.dirname(__FILE__) + '/subtle/cover.rb'
2
+ Dir[File.dirname(__FILE__) + '/subtle/*.rb'].each {|file| require file }
3
+
4
+ module Subtle
5
+ # Your code goes here...
6
+ end
@@ -0,0 +1,32 @@
1
+ class Array
2
+
3
+ def to_objects(&blk)
4
+ records = blk.call
5
+ return [] if records.empty?
6
+ records.map { |record| create_object_for_this_record(record) }
7
+ end
8
+
9
+ private
10
+
11
+ def create_object_for_this_record(record)
12
+ result = Object.new
13
+ self.each_with_index do |property_name, index|
14
+ value = get_the_value(record, index)
15
+ add_reader_for(result, property_name, value)
16
+ end
17
+ result
18
+ end
19
+
20
+ def get_the_value(value, index)
21
+ return value unless value.kind_of?(Array)
22
+ value[index]
23
+ end
24
+
25
+ def add_reader_for(result, property_name, this_value)
26
+ result.instance_variable_set("@#{property_name}", this_value)
27
+ result.instance_eval("
28
+ class << self
29
+ attr_accessor :#{property_name}
30
+ end")
31
+ end
32
+ end
@@ -0,0 +1,29 @@
1
+ require 'blankslate'
2
+
3
+ module Subtle
4
+ module CoverMethods
5
+ def initialize(subject)
6
+ @subject = subject
7
+ end
8
+
9
+ def method_missing(meth, *args, &blk)
10
+ @subject.send(meth, *args, &blk)
11
+ rescue
12
+ Subtle::Cover.new Object.new
13
+ end
14
+
15
+ def the_original_subject
16
+ @subject
17
+ end
18
+ end
19
+
20
+ module StrictCoverMethods
21
+ def method_missing(meth, *args, &blk)
22
+ @subject.send(meth, *args, &blk)
23
+ end
24
+ end
25
+
26
+ class Cover < ::BlankSlate
27
+ include Subtle::CoverMethods
28
+ end
29
+ end
@@ -0,0 +1,5 @@
1
+ class Proc
2
+ def to_object
3
+ Subtle::LazyCover.new self
4
+ end
5
+ end
@@ -0,0 +1,27 @@
1
+ module Subtle
2
+ class LazyCover < Cover
3
+ include Subtle::StrictCoverMethods
4
+
5
+ def initialize(block)
6
+ @block = block
7
+ end
8
+
9
+ alias :the_original_subject_from_the_base_class :the_original_subject
10
+ def the_original_subject
11
+ setup_the_subject
12
+ the_original_subject_from_the_base_class
13
+ end
14
+
15
+ private
16
+
17
+ alias :old_method_missing :method_missing
18
+ def method_missing(meth, *args, &blk)
19
+ setup_the_subject
20
+ old_method_missing meth, *args, &blk
21
+ end
22
+
23
+ def setup_the_subject
24
+ @subject = @block.call if @subject.nil?
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,10 @@
1
+ class Object
2
+ def param_constructor
3
+ self.class_eval('
4
+ def initialize(params={})
5
+ params.each do |attr, value|
6
+ self.public_send("#{attr}=", value)
7
+ end if params
8
+ end')
9
+ end
10
+ end
@@ -0,0 +1,7 @@
1
+ class Proc
2
+ def call_safely
3
+ self.call
4
+ rescue
5
+ yield if block_given?
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ module Subtle
2
+ VERSION = "0.3.4"
3
+ end
@@ -0,0 +1,4 @@
1
+ require 'mocha'
2
+ require 'minitest/spec'
3
+ require 'minitest/autorun'
4
+ require './lib/subtle.rb'
@@ -0,0 +1,99 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "arrays to objects" do
4
+
5
+ [:name, :street].each do |property|
6
+ describe "with an array with one symbol named #{property.to_s}" do
7
+ describe "and no data" do
8
+ before do
9
+ @values = [property].to_objects { [] }
10
+ end
11
+
12
+ it "should return an empty array" do
13
+ @values.must_be_empty
14
+ end
15
+ end
16
+
17
+ ["Dangy", "Taggart"].each do |name|
18
+ describe "and one record with #{name}" do
19
+ before do
20
+ @values = [property].to_objects { [name] }
21
+ end
22
+
23
+ it "should return one record" do
24
+ @values.count.must_equal 1
25
+ end
26
+
27
+ it "should have a property with the name of Dangy" do
28
+ @values[0].send(property).must_equal name
29
+ end
30
+ end
31
+ end
32
+
33
+ describe "and two records with John and Howard" do
34
+ before do
35
+ @values = [property].to_objects {["John", "Howard"]}
36
+ end
37
+
38
+ it "should return two records" do
39
+ @values.count.must_equal 2
40
+ end
41
+
42
+ it "should set the first to John" do
43
+ @values[0].send(property).must_equal "John"
44
+ end
45
+
46
+ it "should set the second to Howard" do
47
+ @values[1].send(property).must_equal "Howard"
48
+ end
49
+ end
50
+ end
51
+
52
+ describe "with an array with two symbols named first_name and last_name" do
53
+ describe "with 'Ellis' and 'Wyatt'" do
54
+ before do
55
+ @values = [:first_name, :last_name].to_objects { [['Ellis', 'Wyatt']] }
56
+ end
57
+
58
+ it "should return one record" do
59
+ @values.count.must_equal 1
60
+ end
61
+
62
+ it "should set the first name to Ellis" do
63
+ @values[0].first_name.must_equal 'Ellis'
64
+ end
65
+
66
+ it "should set the last name to Wyatt" do
67
+ @values[0].last_name.must_equal 'Wyatt'
68
+ end
69
+ end
70
+
71
+ describe "with 'Ellis' and 'Wyatt', then 'Dagny' and 'Taggart'" do
72
+ before do
73
+ @values = [:first_name, :last_name].to_objects { [['Ellis', 'Wyatt'], ['Dagny', 'Taggart']] }
74
+ end
75
+
76
+ it "should return one record" do
77
+ @values.count.must_equal 2
78
+ end
79
+
80
+ it "should set the first name to Ellis on the first record" do
81
+ @values[0].first_name.must_equal 'Ellis'
82
+ end
83
+
84
+ it "should set the last name to Wyatt on the first record" do
85
+ @values[0].last_name.must_equal 'Wyatt'
86
+ end
87
+
88
+ it "should set the first name to Dagny on the second record" do
89
+ @values[1].first_name.must_equal 'Dagny'
90
+ end
91
+
92
+ it "should set the last name to Wyatt on the second record" do
93
+ @values[1].last_name.must_equal 'Taggart'
94
+ end
95
+ end
96
+ end
97
+ end
98
+
99
+ end
@@ -0,0 +1,94 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Subtle::Cover do
4
+ before do
5
+ end
6
+
7
+ describe "when given an Object" do
8
+ before do
9
+ @view_model = Subtle::Cover.new Object.new
10
+ end
11
+
12
+ it "should not throw an exception on methods that do not exist" do
13
+ @view_model.not_this
14
+ @view_model.or_this_either
15
+ end
16
+
17
+ it "should return an object if the method does not exist" do
18
+ @view_model.should_be_a_view_model.wont_be_nil
19
+ @view_model.another_test.wont_be_nil
20
+ end
21
+
22
+ it "should return new view models each time on methods that do not exist" do
23
+ first = @view_model.one_call
24
+ second = @view_model.second_call
25
+
26
+ first.object_id.wont_equal @view_model.object_id
27
+ second.object_id.wont_equal @view_model.object_id
28
+ first.object_id.wont_equal second.object_id
29
+ end
30
+ end
31
+
32
+ describe "when given a Person object" do
33
+ class Person
34
+ attr_accessor :first_name, :last_name
35
+ end
36
+
37
+ before do
38
+ @person = Person.new
39
+ @view_model = Subtle::Cover.new @person
40
+ end
41
+
42
+ [["John", "Galt"], ["Howard", "Roark"]].each do |name|
43
+ describe "with name of #{name[0]} #{name[1]}" do
44
+ before do
45
+ @person.first_name = name[0]
46
+ @person.last_name = name[1]
47
+ end
48
+
49
+ it "should return John as the first name" do
50
+ @view_model.first_name.must_equal name[0]
51
+ end
52
+
53
+ it "should return Galt as the last name" do
54
+ @view_model.last_name.must_equal name[1]
55
+ end
56
+ end
57
+ end
58
+ end
59
+
60
+ describe "when given an object that uses a block" do
61
+ class Thing
62
+ class << self
63
+ attr_accessor :test_value
64
+ end
65
+ def test(&blk)
66
+ blk.call
67
+ end
68
+ end
69
+
70
+ before do
71
+ @thing = Thing.new
72
+ @view_model = Subtle::Cover.new @thing
73
+ end
74
+
75
+ it "should call the block" do
76
+ @view_model.test do
77
+ Thing.test_value = true
78
+ end
79
+ Thing.test_value.must_equal true
80
+ end
81
+ end
82
+
83
+ [1, "abc", Object.new].each do |subject|
84
+ describe "#the_original_subject" do
85
+ before do
86
+ @cover = Subtle::Cover.new subject
87
+ end
88
+
89
+ it "should return the original" do
90
+ @cover.the_original_subject.must_equal subject
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,39 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "lambda to object" do
4
+
5
+ describe "to_object on a lambda that returns nil" do
6
+ before do
7
+ @value = -> { nil }.to_object
8
+ end
9
+
10
+ it "should remember the original value is nil" do
11
+ @value.the_original_subject.must_equal nil
12
+ end
13
+ end
14
+
15
+ describe "to_object on a lambda that returns an integer" do
16
+ before do
17
+ @value = -> { 1 }.to_object
18
+ end
19
+
20
+ it "should remember the original value is 1" do
21
+ @value.the_original_subject.must_equal 1
22
+ end
23
+
24
+ it "should be able to use the value as an integer" do
25
+ (@value + 1).must_equal 2
26
+ end
27
+ end
28
+
29
+ describe "to_object on a lambda, but never accessing the variable" do
30
+ before do
31
+ @was_called = false
32
+ @value = -> { raise 'it was called' }.to_object
33
+ end
34
+
35
+ it "should not be called" do
36
+ #will throw an exception if it was called above
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,66 @@
1
+ require 'mocha'
2
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
3
+
4
+ class LazyCoverTest
5
+ class << self
6
+ attr_accessor :was_called
7
+ end
8
+ end
9
+
10
+ describe Subtle::LazyCover do
11
+
12
+ it "should not call the block passed to it" do
13
+ lazy = Subtle::LazyCover.new(-> { raise 'was called' })
14
+ end
15
+
16
+ it "should call the block passed to it when things are references" do
17
+ LazyCoverTest.was_called = false
18
+ lazy = Subtle::LazyCover.new(-> { LazyCoverTest.was_called = true })
19
+ LazyCoverTest.was_called.must_equal false
20
+ lazy.to_s
21
+ LazyCoverTest.was_called.must_equal true
22
+ end
23
+
24
+ it "should call the block passed to it only once" do
25
+ LazyCoverTest.was_called = 0
26
+ lazy = Subtle::LazyCover.new(-> { LazyCoverTest.was_called = LazyCoverTest.was_called + 1 })
27
+ LazyCoverTest.was_called.must_equal 0
28
+ lazy.to_s
29
+ LazyCoverTest.was_called.must_equal 1
30
+ lazy.to_s
31
+ LazyCoverTest.was_called.must_equal 1
32
+ end
33
+
34
+ it "should return the same exceptions passed from its base class methods" do
35
+
36
+ object = Object.new
37
+ object.stubs(:defined_method).returns("yes")
38
+
39
+ lazy = Subtle::LazyCover.new(-> { object })
40
+ lazy.defined_method.must_equal "yes"
41
+ was_called = false
42
+ begin
43
+ lazy.not_a_defined_method
44
+ rescue NoMethodError
45
+ was_called = true
46
+ end
47
+ was_called.must_equal true
48
+ end
49
+
50
+ describe "the original subject" do
51
+ it "should call the block passed to it" do
52
+ Subtle::LazyCover.new(-> { 0 }).the_original_subject.must_equal 0
53
+ Subtle::LazyCover.new(-> { "x" }).the_original_subject.must_equal "x"
54
+ end
55
+
56
+ it "should only call the block passed to it once" do
57
+ LazyCoverTest.was_called = 0
58
+ lazy = Subtle::LazyCover.new(-> { LazyCoverTest.was_called += 1 })
59
+ lazy.the_original_subject
60
+ LazyCoverTest.was_called.must_equal 1
61
+ lazy.the_original_subject
62
+ LazyCoverTest.was_called.must_equal 1
63
+ end
64
+ end
65
+
66
+ end
@@ -0,0 +1,19 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ class ParamConstructorTest
4
+ param_constructor
5
+ attr_accessor :first_name, :last_name
6
+ end
7
+
8
+ describe "param_constructor" do
9
+ it "should let the object be instantiated with a hash" do
10
+ test = ParamConstructorTest.new(first_name: "John", last_name: "Galt")
11
+ test.first_name.must_equal "John"
12
+ test.last_name.must_equal "Galt"
13
+ end
14
+
15
+ it "should allow the object to be instantiated with no params" do
16
+ test = ParamConstructorTest.new
17
+ # should not throw an error
18
+ end
19
+ end
@@ -0,0 +1,35 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ module SafetyProc
4
+ class << self
5
+ attr_accessor :called
6
+ end
7
+ end
8
+
9
+ describe "Safety Proc" do
10
+ describe "a proc that will throw an exception" do
11
+ before do
12
+ SafetyProc.called = false
13
+ @proc = -> do
14
+ SafetyProc.called = true
15
+ raise 'k'
16
+ end
17
+ end
18
+
19
+ it "should trap the exception yet still call the method" do
20
+ @proc.call_safely
21
+ SafetyProc.called.must_equal true
22
+ end
23
+ end
24
+
25
+ describe "a proc with a block to call on error" do
26
+ before do
27
+ SafetyProc.called = false
28
+ end
29
+
30
+ it "call the block" do
31
+ @proc = -> { raise 'k' }.call_safely { SafetyProc.called = true }
32
+ SafetyProc.called.must_equal true
33
+ end
34
+ end
35
+ end
data/subtle.gemspec ADDED
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/subtle/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Darren Cauthon"]
6
+ gem.email = ["darren@cauthon.com"]
7
+ gem.description = %q{A few small updates to make even more concise Ruby.}
8
+ gem.summary = %q{A few small updates to make even more concise Ruby.}
9
+ gem.homepage = "http://www.github.com/darrencauthon/subtle"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "subtle"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Subtle::VERSION
17
+
18
+ # specify any dependencies here; for example:
19
+ gem.add_runtime_dependency 'blankslate'
20
+ gem.add_development_dependency 'mocha'
21
+ gem.add_development_dependency 'rake'
22
+ end
metadata ADDED
@@ -0,0 +1,130 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: subtle
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.4
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Darren Cauthon
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-08-02 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: blankslate
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: mocha
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rake
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: A few small updates to make even more concise Ruby.
63
+ email:
64
+ - darren@cauthon.com
65
+ executables: []
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - .gitignore
70
+ - .rvmrc
71
+ - .travis.yml
72
+ - Gemfile
73
+ - Guardfile
74
+ - LICENSE
75
+ - README.md
76
+ - Rakefile
77
+ - lib/subtle.rb
78
+ - lib/subtle/array_to_object.rb
79
+ - lib/subtle/cover.rb
80
+ - lib/subtle/lambda_to_object.rb
81
+ - lib/subtle/lazy_cover.rb
82
+ - lib/subtle/param_constructor.rb
83
+ - lib/subtle/safety_proc.rb
84
+ - lib/subtle/version.rb
85
+ - spec/spec_helper.rb
86
+ - spec/subtle/array_to_object_spec.rb
87
+ - spec/subtle/cover_spec.rb
88
+ - spec/subtle/lambda_to_object_spec.rb
89
+ - spec/subtle/lazy_cover_spec.rb
90
+ - spec/subtle/param_constructor_spec.rb
91
+ - spec/subtle/safety_proc_spec.rb
92
+ - subtle.gemspec
93
+ homepage: http://www.github.com/darrencauthon/subtle
94
+ licenses: []
95
+ post_install_message:
96
+ rdoc_options: []
97
+ require_paths:
98
+ - lib
99
+ required_ruby_version: !ruby/object:Gem::Requirement
100
+ none: false
101
+ requirements:
102
+ - - ! '>='
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ segments:
106
+ - 0
107
+ hash: 867729927420554654
108
+ required_rubygems_version: !ruby/object:Gem::Requirement
109
+ none: false
110
+ requirements:
111
+ - - ! '>='
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ segments:
115
+ - 0
116
+ hash: 867729927420554654
117
+ requirements: []
118
+ rubyforge_project:
119
+ rubygems_version: 1.8.24
120
+ signing_key:
121
+ specification_version: 3
122
+ summary: A few small updates to make even more concise Ruby.
123
+ test_files:
124
+ - spec/spec_helper.rb
125
+ - spec/subtle/array_to_object_spec.rb
126
+ - spec/subtle/cover_spec.rb
127
+ - spec/subtle/lambda_to_object_spec.rb
128
+ - spec/subtle/lazy_cover_spec.rb
129
+ - spec/subtle/param_constructor_spec.rb
130
+ - spec/subtle/safety_proc_spec.rb