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 +8 -0
- data/MIT-LICENSE +20 -0
- data/README +88 -0
- data/Rakefile +22 -0
- data/init.rb +2 -0
- data/lib/alias_method_chain.rb +23 -0
- data/lib/hattr_accessor.rb +53 -0
- data/test/hattr_accessor_test.rb +147 -0
- metadata +59 -0
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,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
|