shuber-hattr_accessor 1.0.1

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/CHANGELOG ADDED
@@ -0,0 +1,8 @@
1
+ 2008-10-17 - Sean Huber (shuber@einsteinindustries.com)
2
+ * Refactor #{attribute}_with_hattr_accessor method
3
+ * Rename doc/README.markdown to doc/README
4
+
5
+ 2008-10-14 - Sean Huber (shuber@huberry.com)
6
+ * Initial import
7
+ * Update README
8
+ * Add tests to ensure errors are raised when :attribute does not exist
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 Sean Huber (shuber@huberry.com)
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.
data/README ADDED
@@ -0,0 +1,88 @@
1
+ hattr_accessor
2
+ ==============
3
+
4
+ A gem/plugin that allows you to define attr_accessors that reference members of a hash.
5
+
6
+
7
+ Installation
8
+ ------------
9
+
10
+ script/plugin install git://github.com/shuber/proxy.git
11
+
12
+ OR
13
+
14
+ gem install shuber-hattr_accessor
15
+
16
+
17
+ Usage
18
+ -----
19
+
20
+ The hattr_accessor method requires an option named :attribute which should be a symbol that represents the attribute name of the hash that you want to reference. For example:
21
+
22
+ class SomeClass
23
+ attr_accessor :my_hash
24
+ hattr_accessor :my_attr, :attribute => :my_hash
25
+ end
26
+
27
+ @some_class = SomeClass.new
28
+ @some_class.my_attr = 'test'
29
+ @some_class.my_hash # => { :my_attr => 'test' }
30
+
31
+ You may optionally pass a :type option which will type cast the value when calling the getter method. For example:
32
+
33
+ class SomeClass
34
+ attr_accessor :my_hash
35
+ hattr_accessor :birth_day, :birth_year, :type => :integer, :attribute => :my_hash
36
+ end
37
+
38
+ @some_class.birth_day = '12'
39
+ @some_class.birth_day # => 12
40
+
41
+ @some_class.birth_year = 2008
42
+ @some_class.birth_year # => 2008
43
+
44
+ This is useful if you're using this gem/plugin with ActiveRecord which will pass values as strings if submitted from a form. For Example:
45
+
46
+ class SomeController < ApplicationController
47
+ def create
48
+ @some_class = SomeClass.new(params[:some_class])
49
+ @some_class.birth_day # => '12'
50
+ # notice it returns as a string instead of an integer
51
+ # using :type => :integer will fix this
52
+ end
53
+ end
54
+
55
+ The current options (email me for suggestions for others) for :type are:
56
+
57
+ :string
58
+ :integer
59
+ :float
60
+ :boolean
61
+
62
+
63
+ Example
64
+ -------
65
+
66
+ class CustomField < ActiveRecord::Base
67
+ # has a text or blob attribute named :configuration
68
+ serialize :configuration, Hash
69
+ end
70
+
71
+ class CustomFields::Date < CustomField
72
+ hattr_accessor :offset, :type => :integer, :attribute => :configuration
73
+ hattr_accessor :unit, :reference, :attribute => :configuration
74
+
75
+ def default_value
76
+ self.offset.send(self.unit).send(self.reference)
77
+ end
78
+ end
79
+
80
+ @field = CustomFields::Date.new({ :offset => '5', :unit => 'days', :reference => 'from_now' })
81
+ @field.configuration # => { :offset => '5', :unit => 'days', :reference => 'from_now' }
82
+ @field.default_value # => evaluates 5.days.from_now
83
+
84
+
85
+ Contact
86
+ -------
87
+
88
+ Problems, comments, and suggestions all welcome: [shuber@huberry.com](mailto:shuber@huberry.com)
data/Rakefile ADDED
@@ -0,0 +1,22 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ desc 'Default: run the hattr_accessor tests'
6
+ task :default => :test
7
+
8
+ desc 'Test the hattr_accessor plugin.'
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << 'lib'
11
+ t.pattern = 'test/*_test.rb'
12
+ t.verbose = true
13
+ end
14
+
15
+ desc 'Generate documentation for the hattr_accessor plugin.'
16
+ Rake::RDocTask.new(:rdoc) do |rdoc|
17
+ rdoc.rdoc_dir = 'rdoc'
18
+ rdoc.title = 'hattr_accessor'
19
+ rdoc.options << '--line-numbers' << '--inline-source'
20
+ rdoc.rdoc_files.include('README.markdown')
21
+ rdoc.rdoc_files.include('lib/**/*.rb')
22
+ end
data/init.rb ADDED
@@ -0,0 +1,2 @@
1
+ require File.dirname(__FILE__) + '/lib/hattr_accessor'
2
+ $:.unshift File.dirname(__FILE__) + '/lib'
@@ -0,0 +1,23 @@
1
+ module Huberry
2
+ module AliasMethodChain # :nodoc:
3
+ # Defines the alias_method_chain method from rails unless it exists already
4
+ #
5
+ def alias_method_chain(target, feature)
6
+ aliased_target, punctuation = target.to_s.sub(/([?!=])$/, ''), $1
7
+ yield(aliased_target, punctuation) if block_given?
8
+ with_method, without_method = "#{aliased_target}_with_#{feature}#{punctuation}", "#{aliased_target}_without_#{feature}#{punctuation}"
9
+ alias_method without_method, target
10
+ alias_method target, with_method
11
+ case
12
+ when public_method_defined?(without_method)
13
+ public target
14
+ when protected_method_defined?(without_method)
15
+ protected target
16
+ when private_method_defined?(without_method)
17
+ private target
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ Module.send :include, Huberry::AliasMethodChain unless Module.method_defined? :alias_method_chain
@@ -0,0 +1,53 @@
1
+ require File.dirname(__FILE__) + '/alias_method_chain'
2
+
3
+ module Huberry
4
+ module HattrAccessor
5
+ class MissingAttributeError < StandardError; self; end
6
+
7
+ def hattr_accessor(*attrs)
8
+ options = attrs.last.is_a?(Hash) ? attrs.pop : {}
9
+
10
+ raise MissingAttributeError, 'Must specify the :attribute option which should be a symbol that references a hash attribute' if options[:attribute].nil?
11
+
12
+ attrs.each do |name|
13
+ # Defines a type casting getter method for each attribute
14
+ #
15
+ define_method name do
16
+ value = send(options[:attribute])[name]
17
+ case options[:type]
18
+ when :string
19
+ value.to_s
20
+ when :integer
21
+ value.to_i
22
+ when :float
23
+ value.to_f
24
+ when :boolean
25
+ ![false, nil, 0, '0'].include? value
26
+ else
27
+ value
28
+ end
29
+ end
30
+
31
+ # Defines a setter method for each attribute
32
+ #
33
+ define_method "#{name}=" do |value|
34
+ send(options[:attribute])[name] = value
35
+ end
36
+ end
37
+
38
+ # Overwrites the method passed as the :attribute option to ensure that it is a hash by default
39
+ #
40
+ unless instance_methods.include? "#{options[:attribute]}_with_hattr_accessor"
41
+ class_eval <<-EOF
42
+ def #{options[:attribute]}_with_hattr_accessor
43
+ self.#{options[:attribute]} = {} if #{options[:attribute]}_without_hattr_accessor.nil?
44
+ #{options[:attribute]}_without_hattr_accessor
45
+ end
46
+ alias_method_chain :#{options[:attribute]}, :hattr_accessor
47
+ EOF
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ Class.send :include, Huberry::HattrAccessor
@@ -0,0 +1,147 @@
1
+ require 'test/unit'
2
+ require File.dirname(__FILE__) + '/../lib/hattr_accessor'
3
+
4
+ class CustomField
5
+ attr_accessor :configuration, :configuration2
6
+ hattr_accessor :name, :type, :type => :string, :attribute => :configuration
7
+ hattr_accessor :unit, :reference, :attribute => :configuration
8
+ hattr_accessor :offset, :type => :integer, :attribute => :configuration
9
+ hattr_accessor :amount, :type => :float, :attribute => :configuration
10
+ hattr_accessor :required, :type => :boolean, :attribute => :configuration2
11
+ end
12
+
13
+ class HattrAccessorTest < Test::Unit::TestCase
14
+
15
+ def setup
16
+ @custom_field = CustomField.new
17
+ end
18
+
19
+ def test_should_alias_method_chain_configuration
20
+ assert CustomField.method_defined?(:configuration_with_hattr_accessor)
21
+ assert CustomField.method_defined?(:configuration_without_hattr_accessor)
22
+ end
23
+
24
+ def test_configuration_should_be_a_hash_by_default
25
+ assert_equal({}, @custom_field.configuration)
26
+ end
27
+
28
+ def test_should_set_name
29
+ @custom_field.name = 'Date'
30
+ assert_equal({ :name => 'Date' }, @custom_field.configuration)
31
+ end
32
+
33
+ def test_should_get_name
34
+ @custom_field.name = 'Date'
35
+ assert_equal 'Date', @custom_field.name
36
+ end
37
+
38
+ def test_should_type_cast_name_as_string
39
+ assert_equal '', @custom_field.name
40
+ end
41
+
42
+ def test_should_set_and_get_an_attribute_named_type
43
+ @custom_field.type = 'Date'
44
+ assert_equal 'Date', @custom_field.type
45
+ end
46
+
47
+ def test_should_set_unit
48
+ @custom_field.unit = 'days'
49
+ assert_equal({ :unit => 'days' }, @custom_field.configuration)
50
+ end
51
+
52
+ def test_should_get_unit
53
+ @custom_field.unit = 'days'
54
+ assert_equal 'days', @custom_field.unit
55
+ end
56
+
57
+ def test_should_set_reference
58
+ @custom_field.reference = 'from_now'
59
+ assert_equal({ :reference => 'from_now' }, @custom_field.configuration)
60
+ end
61
+
62
+ def test_should_get_reference
63
+ @custom_field.reference = 'from_now'
64
+ assert_equal 'from_now', @custom_field.reference
65
+ end
66
+
67
+ def test_should_set_offset
68
+ @custom_field.offset = 1
69
+ assert_equal({ :offset => 1 }, @custom_field.configuration)
70
+ end
71
+
72
+ def test_should_get_offset
73
+ @custom_field.offset = 1
74
+ assert_equal 1, @custom_field.offset
75
+ end
76
+
77
+ def test_should_type_cast_offset_as_integer
78
+ @custom_field.offset = '1'
79
+ assert_equal 1, @custom_field.offset
80
+ end
81
+
82
+ def test_should_set_amount
83
+ @custom_field.amount = 1.0
84
+ assert_equal({ :amount => 1.0 }, @custom_field.configuration)
85
+ end
86
+
87
+ def test_should_get_amount
88
+ @custom_field.amount = 1.0
89
+ assert_equal 1.0, @custom_field.amount
90
+ end
91
+
92
+ def test_should_type_cast_amount_as_float
93
+ @custom_field.amount = '1'
94
+ assert_equal 1.0, @custom_field.amount
95
+
96
+ @custom_field.amount = 1
97
+ assert_equal 1.0, @custom_field.amount
98
+ end
99
+
100
+ def test_should_set_required_in_configuration2
101
+ @custom_field.required = true
102
+ assert_equal({ :required => true }, @custom_field.configuration2)
103
+ end
104
+
105
+ def test_should_get_required
106
+ @custom_field.required = true
107
+ assert_equal true, @custom_field.required
108
+ end
109
+
110
+ def test_should_type_cast_required_as_boolean
111
+ assert_equal false, @custom_field.required
112
+
113
+ @custom_field.required = false
114
+ assert_equal false, @custom_field.required
115
+
116
+ @custom_field.required = 0
117
+ assert_equal false, @custom_field.required
118
+
119
+ @custom_field.required = '0'
120
+ assert_equal false, @custom_field.required
121
+
122
+ @custom_field.required = true
123
+ assert_equal true, @custom_field.required
124
+
125
+ @custom_field.required = 1
126
+ assert_equal true, @custom_field.required
127
+
128
+ @custom_field.required = '1'
129
+ assert_equal true, @custom_field.required
130
+
131
+ @custom_field.required = ''
132
+ assert_equal true, @custom_field.required
133
+ end
134
+
135
+ def test_should_raise_exception_if_attribute_option_is_not_passed
136
+ assert_raises Huberry::HattrAccessor::MissingAttributeError do
137
+ CustomField.hattr_accessor :test
138
+ end
139
+ end
140
+
141
+ def test_should_raise_exception_if_attribute_option_reference_does_not_exist
142
+ assert_raises NameError do
143
+ CustomField.hattr_accessor :test, :attribute => :non_existent
144
+ end
145
+ end
146
+
147
+ end
metadata ADDED
@@ -0,0 +1,59 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: shuber-hattr_accessor
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Sean Huber
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-10-14 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: A gem/plugin that allows you to define attr_accessors that reference members of a hash
17
+ email: shuber@huberry.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - CHANGELOG
26
+ - init.rb
27
+ - lib/alias_method_chain.rb
28
+ - lib/hattr_accessor.rb
29
+ - MIT-LICENSE
30
+ - Rakefile
31
+ - README
32
+ has_rdoc: false
33
+ homepage: http://github.com/shuber/hattr_accessor
34
+ post_install_message:
35
+ rdoc_options: []
36
+
37
+ require_paths:
38
+ - lib
39
+ required_ruby_version: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "0"
44
+ version:
45
+ required_rubygems_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: "0"
50
+ version:
51
+ requirements: []
52
+
53
+ rubyforge_project:
54
+ rubygems_version: 1.2.0
55
+ signing_key:
56
+ specification_version: 2
57
+ summary: A gem/plugin that allows you to define attr_accessors that reference members of a hash
58
+ test_files:
59
+ - test/hattr_accessor_test.rb