bless 0.1.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,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 201fad31dea2baafb55c2ad7ece548a0326599fa
4
+ data.tar.gz: 68bb9c8af4be0781f1de984a4582f724ceb7dd25
5
+ SHA512:
6
+ metadata.gz: 94b932c692e91be83fb16eadbd3afec8ab38bd99faf14bf0fe1f97f85d70247d2da2420f89aad110edd74bf9bb1a8dfb85afef0bc0f59edbedbca10f1a0d5aa2
7
+ data.tar.gz: a49f5f6179cdfa9770fa8f2308e5eea7fb1062a2ff8cb73a49c36ba31b5c7a4bcd06ecaa4782f033dd62e45c542ba6256d4a1be1dba92f02f34706d9f6c64360
@@ -0,0 +1,18 @@
1
+ .DS_Store
2
+ *.gem
3
+ *.rbc
4
+ .bundle
5
+ .config
6
+ .yardoc
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format documentation
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - ruby-head
4
+ - 2.1.0
5
+ - 2.0.0
6
+ - 1.9.3
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,6 @@
1
+ guard 'rspec' do
2
+ watch(%r{^spec/.+_spec\.rb$})
3
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
4
+ #watch('spec/spec_helper.rb') { 'spec' }
5
+ end
6
+
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Lennart Fridén
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.
@@ -0,0 +1,40 @@
1
+ # Bliss [![Build Status](https://secure.travis-ci.org/DevL/bliss.png)](http://travis-ci.org/DevL/bliss) ![Gem version](https://badge.fury.io/rb/bliss.png)
2
+
3
+ Miss Perl? Ever wished Ruby was more like it? Me neither, but that's no excuse for going nuts and hack together some insane code that Perlifies Ruby.
4
+
5
+ There's no excuse for using it in production though.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'bliss'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install bliss
20
+
21
+ ## Usage
22
+
23
+ Using bless is simplicity itself. Or was it idiocy? Nevermind, bless your followers by uttering the following. Preferably followed by a prayer that your code will not be seen by anyone. Ever.
24
+
25
+ ```ruby
26
+ blessed_object = bless(Object.new, String)
27
+ blessed_object.instance_of?(String) # => true
28
+ ```
29
+
30
+ Now, the proverbial example usage of bless in Perl would operate in conjunction with the `my` keyword. However, implementing support for that proved to be somewhat less than straightforward. To make a long story short, setting a local variable from an eval AND retaining that local variable beyond the scope of the eval is simply not possible in Ruby\*.
31
+
32
+ \* Until we come up with the idea of hacking Rubinius into submission. Hopefully we'll never think of that.
33
+
34
+ ## Contributing
35
+
36
+ 1. Fork it
37
+ 2. Create your feature branch (`git checkout -b I-say-we-take-off-and-nuke-it-from-orbit`)
38
+ 3. Commit your changes (`git commit -am 'It is the only way to make sure!'`)
39
+ 4. Push to the branch (`git push origin I-say-we-take-off-and-nuke-it-from-orbit`)
40
+ 5. Create new Pull Request
@@ -0,0 +1,5 @@
1
+ require 'rspec/core/rake_task'
2
+
3
+ RSpec::Core::RakeTask.new(:spec)
4
+
5
+ task :default => :spec
@@ -0,0 +1,28 @@
1
+ # encoding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'bless/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'bless'
8
+ spec.version = Bless::VERSION
9
+ spec.authors = ['Lennart Fridén', 'Kim Persson']
10
+ spec.email = ['lennart@devl.se']
11
+ spec.description = %q{Blessed are the Perl hackers}
12
+ spec.summary = %q{Brings the blessings of Perl to Ruby}
13
+ spec.homepage = 'https://github.com/DevL/bless'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_runtime_dependency 'binding_of_caller', '~> 0.7'
22
+ spec.add_development_dependency 'byebug', '~> 2.5'
23
+ spec.add_development_dependency 'bundler', '~> 1.3'
24
+ spec.add_development_dependency 'rake', '~> 10'
25
+ spec.add_development_dependency 'rspec', '~> 2.14'
26
+ spec.add_development_dependency 'guard', '~> 2.2'
27
+ spec.add_development_dependency 'guard-rspec', '~> 4.2'
28
+ end
@@ -0,0 +1,123 @@
1
+ require 'bless/version'
2
+ require 'binding_of_caller'
3
+
4
+ module Bless
5
+ class Blesser
6
+ class CannotBlessSimpletons < StandardError; end
7
+
8
+ def self.bless(object, klass, context, invoker)
9
+ assert_kernel_ancestor_on(object)
10
+ new(object, klass, context, invoker).bless
11
+ end
12
+
13
+ def bless
14
+ if blessee_writeable?
15
+ convert_or_set_blessee_in_context
16
+ else
17
+ convert_or_instantiate
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ attr_reader :blessee, :blessee_code, :blessee_owner, :code, :context, :invoker, :klass, :object
24
+
25
+ def initialize(object, klass, context, invoker)
26
+ @object = object
27
+ @context = context
28
+ @invoker = invoker
29
+ @klass = determine_target_class(klass)
30
+ @code = code_for_invoker
31
+ @blessee_code = extract_blessee_code
32
+ @blessee, @blessee_owner = blessee_and_owner
33
+ end
34
+
35
+ def self.assert_kernel_ancestor_on(object)
36
+ object.class.ancestors.include?(Kernel)
37
+ rescue NoMethodError => e
38
+ raise CannotBlessSimpletons.new
39
+ end
40
+
41
+ def determine_target_class(klass)
42
+ klass || context.eval('self.class')
43
+ end
44
+
45
+ def code_for_invoker
46
+ file, line = invoker.split(':')
47
+ IO.readlines(file)[line.to_i - 1].strip
48
+ end
49
+
50
+ def extract_blessee_code
51
+ match_data = code.match code_regex
52
+ match_data[:var] if match_data
53
+ end
54
+
55
+ def code_regex
56
+ /
57
+ bless
58
+ (\(\s*|\s+) # optional opening parens followed by optional whitespace OR mandatory whitespace
59
+ (?<var>[^,\s]+) # extract variable name
60
+ (\s*,\s*.+)? # optional whitespace, comma, optional whitespace, whatever (all optional)
61
+ \)? # optional closing parens
62
+ /x
63
+ end
64
+
65
+ def blessee_and_owner
66
+ blessee_elements = blessee_code.split('.')
67
+ [blessee_elements.pop, blessee_elements.join('.')]
68
+ end
69
+
70
+ def convertable_object?
71
+ Kernel.methods.include?(klass.name.to_sym)
72
+ end
73
+
74
+ def convert_or_set_blessee_in_context
75
+ if convertable_object?
76
+ convert_blessee_in_context
77
+ else
78
+ set_blessee_in_context
79
+ end
80
+ end
81
+
82
+ def convert_blessee_in_context
83
+ context.eval("#{blessee_code} = send('#{klass.name}', #{blessee_code})")
84
+ end
85
+
86
+ def set_blessee_in_context
87
+ context.eval("#{blessee_code} = #{klass}.new")
88
+ end
89
+
90
+ def convert_or_instantiate
91
+ if convertable_object?
92
+ send(klass.name, object)
93
+ else
94
+ klass.new
95
+ end
96
+ end
97
+
98
+ def blessee_writeable?
99
+ if !blessee_owner.empty?
100
+ blessee_assignable?
101
+ else
102
+ assignable_variables_for_context.include?(blessee.to_sym)
103
+ end
104
+ end
105
+
106
+ def blessee_assignable?
107
+ context.eval "#{blessee_owner}.respond_to?('#{blessee}=')"
108
+ end
109
+
110
+ def assignable_variables_for_context
111
+ context.eval('local_variables + instance_variables')
112
+ end
113
+ end
114
+ end
115
+
116
+ module Kernel
117
+ def bless(object, klass = nil)
118
+ context = binding.of_caller(1)
119
+ invoker = caller.first
120
+
121
+ Bless::Blesser.bless(object, klass, context, invoker)
122
+ end
123
+ end
@@ -0,0 +1,3 @@
1
+ module Bless
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,82 @@
1
+ require 'bless'
2
+
3
+ class SomePackage
4
+ end
5
+
6
+ class ParentObject
7
+ attr_accessor :child
8
+ end
9
+
10
+ describe 'Kernel#bless' do
11
+ it 'can bless an object' do
12
+ expected_class = SomePackage
13
+ some_object = bless Object.new, expected_class
14
+ some_object.should be_an_instance_of(expected_class)
15
+ end
16
+
17
+ it 'can bless a nested object' do
18
+ expected_class = SomePackage
19
+ parent = ParentObject.new
20
+ parent.child = :unchanged_child_object
21
+ bless parent.child, expected_class
22
+ parent.child.should be_an_instance_of(expected_class)
23
+ end
24
+
25
+ it 'can bless an instance variable' do
26
+ expected_class = SomePackage
27
+ @some_instance_variable = :unchanged_instance_variable
28
+ bless @some_instance_variable, expected_class
29
+ @some_instance_variable.should be_an_instance_of(expected_class)
30
+ end
31
+
32
+ it 'defaults to the current class' do
33
+ some_object = bless Object.new
34
+ expected_class = self.class
35
+ # the matcher 'be_an_instance_of' uses the 'describe' description
36
+ some_object.instance_of?(expected_class).should be_true
37
+ end
38
+
39
+ it 'changes the reference to the object without requiring assignment' do
40
+ some_object = :unchanged_object
41
+ expected_class = SomePackage
42
+ bless some_object, expected_class
43
+
44
+ some_object.should be_an_instance_of(expected_class)
45
+ end
46
+
47
+ it 'changes the reference to the object when using an implicit class' do
48
+ some_object = String.new
49
+ expected_class = self.class
50
+ bless some_object
51
+
52
+ some_object.instance_of?(expected_class).should be_true
53
+ end
54
+
55
+ it 'attempts to convert the object if possible' do
56
+ some_object = 15
57
+ expected = [15]
58
+ bless some_object, Array
59
+
60
+ some_object.should == expected
61
+ end
62
+
63
+ it 'handles parens' do
64
+ some_object = { a: 1 }
65
+ expected = [[:a, 1]]
66
+ bless(some_object, Array)
67
+
68
+ some_object.should == expected
69
+ end
70
+
71
+ class VeryBasic < BasicObject
72
+ def bless_me(klass)
73
+ ::Kernel.bless self, klass
74
+ end
75
+ end
76
+
77
+ it 'gracefully handles BasicObjects' do
78
+ expect {
79
+ VeryBasic.new.bless_me(Hash)
80
+ }.to raise_error(Bless::Blesser::CannotBlessSimpletons)
81
+ end
82
+ end
metadata ADDED
@@ -0,0 +1,156 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bless
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Lennart Fridén
8
+ - Kim Persson
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-01-03 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: binding_of_caller
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '0.7'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '0.7'
28
+ - !ruby/object:Gem::Dependency
29
+ name: byebug
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '2.5'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '2.5'
42
+ - !ruby/object:Gem::Dependency
43
+ name: bundler
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '1.3'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: '1.3'
56
+ - !ruby/object:Gem::Dependency
57
+ name: rake
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: '10'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '10'
70
+ - !ruby/object:Gem::Dependency
71
+ name: rspec
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - "~>"
75
+ - !ruby/object:Gem::Version
76
+ version: '2.14'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - "~>"
82
+ - !ruby/object:Gem::Version
83
+ version: '2.14'
84
+ - !ruby/object:Gem::Dependency
85
+ name: guard
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - "~>"
89
+ - !ruby/object:Gem::Version
90
+ version: '2.2'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - "~>"
96
+ - !ruby/object:Gem::Version
97
+ version: '2.2'
98
+ - !ruby/object:Gem::Dependency
99
+ name: guard-rspec
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - "~>"
103
+ - !ruby/object:Gem::Version
104
+ version: '4.2'
105
+ type: :development
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - "~>"
110
+ - !ruby/object:Gem::Version
111
+ version: '4.2'
112
+ description: Blessed are the Perl hackers
113
+ email:
114
+ - lennart@devl.se
115
+ executables: []
116
+ extensions: []
117
+ extra_rdoc_files: []
118
+ files:
119
+ - ".gitignore"
120
+ - ".rspec"
121
+ - ".travis.yml"
122
+ - Gemfile
123
+ - Guardfile
124
+ - LICENSE.txt
125
+ - README.md
126
+ - Rakefile
127
+ - bless.gemspec
128
+ - lib/bless.rb
129
+ - lib/bless/version.rb
130
+ - spec/bless_spec.rb
131
+ homepage: https://github.com/DevL/bless
132
+ licenses:
133
+ - MIT
134
+ metadata: {}
135
+ post_install_message:
136
+ rdoc_options: []
137
+ require_paths:
138
+ - lib
139
+ required_ruby_version: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - ">="
142
+ - !ruby/object:Gem::Version
143
+ version: '0'
144
+ required_rubygems_version: !ruby/object:Gem::Requirement
145
+ requirements:
146
+ - - ">="
147
+ - !ruby/object:Gem::Version
148
+ version: '0'
149
+ requirements: []
150
+ rubyforge_project:
151
+ rubygems_version: 2.2.0
152
+ signing_key:
153
+ specification_version: 4
154
+ summary: Brings the blessings of Perl to Ruby
155
+ test_files:
156
+ - spec/bless_spec.rb