easy_attributes 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README.rdoc +156 -0
- data/Rakefile +52 -0
- data/VERSION +1 -0
- data/easy_attributes.gemspec +51 -0
- data/lib/easy_attributes.rb +364 -0
- data/test/helper.rb +19 -0
- data/test/test_easy_attributes.rb +147 -0
- metadata +73 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Allen Fair
|
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.rdoc
ADDED
@@ -0,0 +1,156 @@
|
|
1
|
+
= easy_attributes
|
2
|
+
|
3
|
+
Easy Attributes is a Ruby DSL to give more control to attributes. Tested with ruby 1.87 & 1.9.2
|
4
|
+
|
5
|
+
== Usage
|
6
|
+
|
7
|
+
Easy Attributes works in any Ruby class, it does not require Active Record or other ORM.
|
8
|
+
|
9
|
+
First, install this from rubygems.org
|
10
|
+
gem install easy_attributes
|
11
|
+
|
12
|
+
Next, you need to configure your app to use it, by either:
|
13
|
+
require 'rubygems' # Rails application, no framework
|
14
|
+
require 'easy_attributes' #
|
15
|
+
|
16
|
+
config.gem 'easy_attributes' # Rails 2.x, in your ./config/environment.rb
|
17
|
+
|
18
|
+
gem 'easy_attributes' # Rails 3.x, in your ./Gemfile
|
19
|
+
|
20
|
+
Configuration:
|
21
|
+
EasyAttributes::Config.orm = :active_model # will generate some validations, etc.
|
22
|
+
EasyAttributes::Config.load(filename) # Loads a file of column/value/names/descriptions
|
23
|
+
EasyAttributes::define(attribute_name, {:name=>value, ...})
|
24
|
+
|
25
|
+
Declaration:
|
26
|
+
|
27
|
+
class Record < ObjectRelationalMapperOfChoice
|
28
|
+
include EasyAttributes
|
29
|
+
|
30
|
+
attr_values :field, :name=>'value', :name=>'value', ... :validate=>:active_record, :required=>true, :like=>'other' ...
|
31
|
+
attr_sequence :field, :name, :name, ... ,:start=>1, :step=>1
|
32
|
+
attr_money :amount, :units=>"dollars", :unit=>'$', :negative=>'%.2f CR'
|
33
|
+
attr_bytes :bandwidth
|
34
|
+
end
|
35
|
+
|
36
|
+
== attr_values
|
37
|
+
|
38
|
+
will define:
|
39
|
+
field() # => value ### if orm == :attr, attr_accessor will be installed for the attribute
|
40
|
+
field=(value) # => value
|
41
|
+
field_sym() # => :name
|
42
|
+
field_sym=(symbol) # => value
|
43
|
+
field_values() # => {:name=>value, ...}
|
44
|
+
field_is?(:name) # true if :name matches current value
|
45
|
+
field_is?(:name, :name, ...) # true if value matches a given symbol
|
46
|
+
field_is?(:greater_than, :name) # true if the value is greater than the value of :name
|
47
|
+
The first argument can be one of:
|
48
|
+
:greater_than, :gt, :greater_than_or_equal, :ge, :less_than, :lt, :less_than_or_equal, :le
|
49
|
+
field_is?(:between, :name1, :name2) # true if the value is between the corresponding values
|
50
|
+
|
51
|
+
== attr_sequence
|
52
|
+
|
53
|
+
sets up a attr_values with the sequential numbering, by default starting at 1 incrementing by 1
|
54
|
+
|
55
|
+
== attr_bytes
|
56
|
+
|
57
|
+
Creates helper fields to display and accept byte quantities as KB, MB, GB, TB, etc. Since a kilobyte (KB) is
|
58
|
+
now defined as 1000 bytes, and a kibibyte (KiB) is the 1024 quantity, you wan to configure which you want to use
|
59
|
+
|
60
|
+
EasyAttributes::Config.kb_size = 1000 # Uses KB units as 1KB = 1000 bytes
|
61
|
+
EasyAttributes::Config.kb_size = 1024 # Uses KB units as 1KB = 1024 bytes
|
62
|
+
EasyAttributes::Config.kb_size = :new # Uses KiB units as 1KiB = 1024 bytes (DEFAULT)
|
63
|
+
EasyAttributes::Config.kb_size = :both # Combines usage of KB (1000) and KiB (1024) units (Watch out!)
|
64
|
+
|
65
|
+
attr_bytes creates the following methods for a :bandwidth attribute
|
66
|
+
|
67
|
+
bandwidth_bytes = "1 KB" # => 1024
|
68
|
+
bandwidth_bytes # => "1 KB" using whatever unit is best
|
69
|
+
bandwidth_bytes(:MiB) # => "12345.67 MB" using the specified unit
|
70
|
+
bandwidth_bytes(:MiB, :precision=>0) # => "123 MB"
|
71
|
+
|
72
|
+
== attr_money
|
73
|
+
|
74
|
+
is the inclusion of my easy_money gem
|
75
|
+
|
76
|
+
Mixin the EasyAttributes module into the (model) class you need, and declare the
|
77
|
+
attributes (columns) you wish you have the attr_money helpers
|
78
|
+
|
79
|
+
class Ledger
|
80
|
+
include EasyAttributes
|
81
|
+
attr_accessor :amount, :euro # Integer value of cents
|
82
|
+
attr_money :amount # Creates amount_money() and amount_money=() methods
|
83
|
+
attr_money :amount, :units=>"dollars", :unit=>'$', :negative=>'%.2f CR'
|
84
|
+
# Creates amount_dollars() and amount_dollars=() methods
|
85
|
+
end
|
86
|
+
|
87
|
+
ledger = Ledger.new
|
88
|
+
ledger.amount = 100 # 100 cents = $1.00
|
89
|
+
ledger.amount_money #=> "1.00"
|
90
|
+
ledger.amount_money = "-123.45"
|
91
|
+
ledger.amount #=> -12345 (cents)
|
92
|
+
ledger.amount_money(:negative=>'%.2f CR', :zero=>'Free') # Uses these formats
|
93
|
+
ledger.amount_dollars #=> "$123.45 CR"
|
94
|
+
|
95
|
+
# Track the bets of the Gamesters of Triskelion on their drill thrall competitions.
|
96
|
+
class ProviderWagers < ActiveRecord::Base
|
97
|
+
include EasyAttributes
|
98
|
+
attr_money :quatloos, :units=>'quatloos', :precision=>3,
|
99
|
+
:zero=>'even', :nil=>'no bet', :negative=>'%.3f Loss', :unit=>'Q',
|
100
|
+
:negative_regex=>/^(-?)(.+\d)\s*Loss/i
|
101
|
+
# creates amount_quatloos(), amount_quatloos=()
|
102
|
+
end
|
103
|
+
|
104
|
+
# in your views
|
105
|
+
<%= f.text_field :amount_quatloos %> # -12000 => "Q12.000 Loss"
|
106
|
+
|
107
|
+
Options for attr_money calls:
|
108
|
+
* :money_method - Use this as the alternative name to the money-access methods
|
109
|
+
* :units - Use this as an alternative suffix name to the money methods ('dollars' gives 'xx_dollars')
|
110
|
+
* :precision - The number of digits implied after the decimal, default is 2
|
111
|
+
* :separator - The character to use after the integer part, default is '.'
|
112
|
+
* :delimiter - The character to use between every 3 digits of the integer part, default none
|
113
|
+
* :positive - The sprintf format to use for positive numbers, default is based on precision
|
114
|
+
* :negative - The sprintf format to use for negative numbers, default is same as :positive
|
115
|
+
* :zero - The sprintf format to use for zero, default is same as :positive
|
116
|
+
* :nil - The sprintf format to use for nil values, default none
|
117
|
+
* :unit - Prepend this to the front of the money value, say '$', default none
|
118
|
+
* :blank - Return this value when the money string is empty or has no digits on assignment
|
119
|
+
* :negative_regex - A Regular Expression used to determine if a number is negative (and without a - sign), defaults to having a "CR" after the number
|
120
|
+
|
121
|
+
=== Formatters
|
122
|
+
You can also call or build your own custom conversions. Ensure that
|
123
|
+
you can convert between the integer and money forms if you need to.
|
124
|
+
|
125
|
+
The "money" type is a string, suitable for human editing, and will convert back into
|
126
|
+
integer type. If you override the formatting options, test that your money result
|
127
|
+
string will convert properly back to the original integer value.
|
128
|
+
|
129
|
+
include EasyAttributes
|
130
|
+
...
|
131
|
+
puts EasyAttributes.money_to_integer( money_string, :option=>value, ... )
|
132
|
+
puts EasyAttributes.integer_to_money( cents_integer, :option=>value, ... )
|
133
|
+
puts EasyAttributes.integer_to_float( cents_integer, :option=>value, ... )
|
134
|
+
puts EasyAttributes.float_to_integer( money_float, :option=>value, ... )
|
135
|
+
|
136
|
+
EasyAttributes.integer_to_float( nil, blank:0 ) #=> 0.0 [Ruby 1.9.1 Syntax]
|
137
|
+
EasyAttributes.integer_to_float( 12345, :precision=>3 ) #=> 12.345
|
138
|
+
EasyAttributes.float_to_integer(12.345111, :precision=>3 ) #=> 12345
|
139
|
+
|
140
|
+
The options to these methods are the same as the #attr_money declarations
|
141
|
+
|
142
|
+
|
143
|
+
== Note on Patches/Pull Requests
|
144
|
+
|
145
|
+
* Fork the project.
|
146
|
+
* Make your feature addition or bug fix.
|
147
|
+
* Add tests for it. This is important so I don't break it in a
|
148
|
+
future version unintentionally.
|
149
|
+
* Commit, do not mess with rakefile, version, or history.
|
150
|
+
(if you want to have your own version, that is fine but
|
151
|
+
bump version in a commit by itself I can ignore when I pull)
|
152
|
+
* Send me a pull request. Bonus points for topic branches.
|
153
|
+
|
154
|
+
== Copyright
|
155
|
+
|
156
|
+
Copyright (c) 2010 Allen Fair. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "easy_attributes"
|
8
|
+
gem.summary = %Q{Easy Attributes for Ruby}
|
9
|
+
gem.description = %Q{Easy Attributes is a Ruby DSL to give more control to attributes.}
|
10
|
+
gem.email = "allen.fair@gmail.com"
|
11
|
+
gem.homepage = "http://github.com/afair/easy_attributes"
|
12
|
+
gem.authors = ["Allen Fair"]
|
13
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
14
|
+
end
|
15
|
+
Jeweler::GemcutterTasks.new
|
16
|
+
rescue LoadError
|
17
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
18
|
+
end
|
19
|
+
|
20
|
+
require 'rake/testtask'
|
21
|
+
Rake::TestTask.new(:test) do |test|
|
22
|
+
test.libs << 'lib' << 'test'
|
23
|
+
test.pattern = 'test/**/test_*.rb'
|
24
|
+
test.verbose = true
|
25
|
+
end
|
26
|
+
|
27
|
+
begin
|
28
|
+
require 'rcov/rcovtask'
|
29
|
+
Rcov::RcovTask.new do |test|
|
30
|
+
test.libs << 'test'
|
31
|
+
test.pattern = 'test/**/test_*.rb'
|
32
|
+
test.verbose = true
|
33
|
+
end
|
34
|
+
rescue LoadError
|
35
|
+
task :rcov do
|
36
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
task :test => :check_dependencies
|
41
|
+
|
42
|
+
task :default => :test
|
43
|
+
|
44
|
+
require 'rake/rdoctask'
|
45
|
+
Rake::RDocTask.new do |rdoc|
|
46
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
47
|
+
|
48
|
+
rdoc.rdoc_dir = 'rdoc'
|
49
|
+
rdoc.title = "easy_attributes #{version}"
|
50
|
+
rdoc.rdoc_files.include('README*')
|
51
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
52
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{easy_attributes}
|
8
|
+
s.version = "0.1.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Allen Fair"]
|
12
|
+
s.date = %q{2010-04-28}
|
13
|
+
s.description = %q{Easy Attributes is a Ruby DSL to give more control to attributes.}
|
14
|
+
s.email = %q{allen.fair@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
".gitignore",
|
22
|
+
"LICENSE",
|
23
|
+
"README.rdoc",
|
24
|
+
"Rakefile",
|
25
|
+
"VERSION",
|
26
|
+
"easy_attributes.gemspec",
|
27
|
+
"lib/easy_attributes.rb",
|
28
|
+
"test/helper.rb",
|
29
|
+
"test/test_easy_attributes.rb"
|
30
|
+
]
|
31
|
+
s.homepage = %q{http://github.com/afair/easy_attributes}
|
32
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
33
|
+
s.require_paths = ["lib"]
|
34
|
+
s.rubygems_version = %q{1.3.6}
|
35
|
+
s.summary = %q{Easy Attributes for Ruby}
|
36
|
+
s.test_files = [
|
37
|
+
"test/helper.rb",
|
38
|
+
"test/test_easy_attributes.rb"
|
39
|
+
]
|
40
|
+
|
41
|
+
if s.respond_to? :specification_version then
|
42
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
43
|
+
s.specification_version = 3
|
44
|
+
|
45
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
46
|
+
else
|
47
|
+
end
|
48
|
+
else
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
@@ -0,0 +1,364 @@
|
|
1
|
+
# Mixes in attr_* definitions into ruby classes for using symbolic names as values, money, and bytes
|
2
|
+
module EasyAttributes
|
3
|
+
|
4
|
+
def self.included(base) #:nodoc:
|
5
|
+
base.extend( ClassMethods )
|
6
|
+
#EasyAttributes::Config
|
7
|
+
#puts "easy_attributes included into #{base}"
|
8
|
+
end
|
9
|
+
|
10
|
+
# Configuration class for EasyAttributes, set at load time.
|
11
|
+
class Config
|
12
|
+
@@orm = :attr # :attr, :active_model
|
13
|
+
@@attributes = {}
|
14
|
+
@@values = {}
|
15
|
+
@@kb_size=:iec
|
16
|
+
|
17
|
+
# Values: :old, :jedec, or 1024 uses KB=1024
|
18
|
+
# :new, :iec uses KiB=1024, no KB
|
19
|
+
# 1000, :decimal uses only KB (1000) (other values mix KB and KiB units)
|
20
|
+
def self.kb_size=(b)
|
21
|
+
@@kb_size = b
|
22
|
+
end
|
23
|
+
|
24
|
+
# Returns the kb_size setting
|
25
|
+
def self.kb_size
|
26
|
+
@@kb_size
|
27
|
+
end
|
28
|
+
|
29
|
+
# Set the ORM or attribute manager, currently to :attr (attr_accessor) or :active_model
|
30
|
+
def self.orm=(o)
|
31
|
+
@@orm = o
|
32
|
+
end
|
33
|
+
|
34
|
+
# Returns the ORM setting
|
35
|
+
def self.orm
|
36
|
+
@@orm
|
37
|
+
end
|
38
|
+
|
39
|
+
# Defines a symbol name to a hash of :name=>value
|
40
|
+
def self.define(name, hash)
|
41
|
+
@@attributes[name] = hash
|
42
|
+
end
|
43
|
+
|
44
|
+
# Returns the symbol table
|
45
|
+
def self.attributes
|
46
|
+
@@attributes
|
47
|
+
end
|
48
|
+
|
49
|
+
# Loads a tab-delimted filename into the symbol table in format:
|
50
|
+
# attribute value role symbolic_name short_description long_description (useful for "<option>" data)
|
51
|
+
# If a block is given, it should parse a file line and return an array of
|
52
|
+
# [attribute, value, role*, name, short*, long_description*], *denotes not required, but placeholder required
|
53
|
+
def self.load(filename)
|
54
|
+
File.open(filename).each do |r|
|
55
|
+
next unless r =~ /^\w/
|
56
|
+
(col, val, priv, symbol, word, desc) = block_given? ? yield(r) : r.split(/\t/)
|
57
|
+
next if desc.nil? || desc.empty? || symbol.empty? || word.empty? || symbol.nil?
|
58
|
+
col = col.to_sym
|
59
|
+
@@values[col] = {:sym=>{}, :val=>{}, :rec=>{}} unless @@values.has_key?(col)
|
60
|
+
@@values[col][:sym][symbol.to_sym] = val.to_i
|
61
|
+
@@values[col][:val][val] = symbol.to_sym
|
62
|
+
@@values[col][:rec][symbol.to_sym] = {:word=>word, :description=>desc, :value=>val.to_i}
|
63
|
+
@@attributes[col.to_s] ||= {}
|
64
|
+
@@attributes[col.to_s][symbol.to_sym] = val.to_i
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
module ClassMethods
|
70
|
+
# Defines an attribute as a sequence of names. :name1=>1, :name2=>2, etc.
|
71
|
+
# attr_sequence :attr, :name, ... :start=>n, :step=>:n
|
72
|
+
def attr_sequence(attribute, *names)
|
73
|
+
opt = EasyAttributes.pop_options(names)
|
74
|
+
values = {}
|
75
|
+
names.inject(opt[:start]||1) { |seq, n| values[n]=seq; seq+=(opt[:step]||1)}
|
76
|
+
attr_values( attribute, values, opt)
|
77
|
+
end
|
78
|
+
|
79
|
+
# Defines an attribute as a hash like {:key=>value,...} where key names are used interchangably with values
|
80
|
+
def attr_values(attribute, *args)
|
81
|
+
opt = args.size > 1 ? args.pop : {}
|
82
|
+
hash = args.first
|
83
|
+
|
84
|
+
# Use :like=>colname to copy from another definition (ClassName#attribute) or from the loaded table columns
|
85
|
+
if opt[:like]
|
86
|
+
hash = EasyAttributes::Config.attributes[opt[:like]]
|
87
|
+
end
|
88
|
+
|
89
|
+
name = "#{self.name}##{attribute}"
|
90
|
+
EasyAttributes.add_definition( name, hash)
|
91
|
+
code = ''
|
92
|
+
if EasyAttributes::Config.orm == :active_model
|
93
|
+
validates_inclusion_of attribute, :in=>hash.values
|
94
|
+
else
|
95
|
+
attr_accessor attribute
|
96
|
+
end
|
97
|
+
code += %Q(
|
98
|
+
def #{attribute}_sym=(v)
|
99
|
+
self.#{attribute} = EasyAttributes.value_for_sym("#{name}", v)
|
100
|
+
end
|
101
|
+
def #{attribute}_sym
|
102
|
+
EasyAttributes.sym_for_value("#{name}", #{attribute})
|
103
|
+
end
|
104
|
+
def self.#{attribute}_values
|
105
|
+
EasyAttributes::Config.attributes["#{name}"]
|
106
|
+
end
|
107
|
+
def #{attribute}_is?(*args)
|
108
|
+
EasyAttributes.value_is?("#{name}", attribute, *args)
|
109
|
+
end
|
110
|
+
)
|
111
|
+
#puts code
|
112
|
+
class_eval code
|
113
|
+
end
|
114
|
+
|
115
|
+
# attr_bytes allows manipultion and display as kb, mb, gb, tb, pb
|
116
|
+
# Adds method: attribute_bytes=() and attribute_bytes(:unit, :option=>value )
|
117
|
+
def attr_bytes(attribute, *args)
|
118
|
+
name = "#{self.name}##{attribute}"
|
119
|
+
opt = EasyAttributes.pop_options(args)
|
120
|
+
#getter, setter = EasyAttributes.getter_setter(attribute)
|
121
|
+
attr_accessor attribute if EasyAttributes::Config.orm == :attr
|
122
|
+
code = %Q(
|
123
|
+
def #{attribute}_bytes(*args)
|
124
|
+
args.size == 0 ? v : EasyAttributes::format_bytes(self.#{attribute}, *args)
|
125
|
+
end
|
126
|
+
def #{attribute}_bytes=(v)
|
127
|
+
self.#{attribute} = EasyAttributes.parse_bytes(v)
|
128
|
+
end
|
129
|
+
)
|
130
|
+
#puts code
|
131
|
+
class_eval code
|
132
|
+
end
|
133
|
+
|
134
|
+
# Creates an money instance method for the given method, named "#{attribute}_money" which returns
|
135
|
+
# a formatted money string, and a #{attribute}_money= method used to set an edited money string.
|
136
|
+
# The original method stores the value as integer (cents, or other precision/currency setting). Options:
|
137
|
+
# * :money_method - Use this as the alternative name to the money-access methods
|
138
|
+
# * :units - Use this as an alternative suffix name to the money methods ('dollars' gives 'xx_dollars')
|
139
|
+
# * :precision - The number of digits implied after the decimal, default is 2
|
140
|
+
# * :separator - The character to use after the integer part, default is '.'
|
141
|
+
# * :delimiter - The character to use between every 3 digits of the integer part, default none
|
142
|
+
# * :positive - The sprintf format to use for positive numbers, default is based on precision
|
143
|
+
# * :negative - The sprintf format to use for negative numbers, default is same as :positive
|
144
|
+
# * :zero - The sprintf format to use for zero, default is same as :positive
|
145
|
+
# * :nil - The sprintf format to use for nil values, default none
|
146
|
+
# * :unit - Prepend this to the front of the money value, say '$', default none
|
147
|
+
# * :blank - Return this value when the money string is empty or has no digits on assignment
|
148
|
+
# * :negative_regex - A Regular Expression used to determine if a number is negative (and without a - sign)
|
149
|
+
#
|
150
|
+
def attr_money(attribute, *args)
|
151
|
+
opt = args.last.is_a?(Hash) ? args.pop : {}
|
152
|
+
money_method = opt.delete(:money_method) || "#{attribute}_#{opt.delete(:units)||'money'}"
|
153
|
+
|
154
|
+
class_eval %Q(
|
155
|
+
def #{money_method}(*args)
|
156
|
+
opt = args.last.is_a?(Hash) ? args.pop : {}
|
157
|
+
EasyAttributes.integer_to_money( #{attribute}, #{opt.inspect}.merge(opt))
|
158
|
+
end
|
159
|
+
|
160
|
+
def #{money_method}=(v, *args)
|
161
|
+
opt = args.last.is_a?(Hash) ? args.pop : {}
|
162
|
+
self.#{attribute} = EasyAttributes.money_to_integer( v, #{opt.inspect}.merge(opt))
|
163
|
+
end
|
164
|
+
)
|
165
|
+
end
|
166
|
+
|
167
|
+
end
|
168
|
+
|
169
|
+
# Returns a [getter_code, setter_code] depending on the orm configuration
|
170
|
+
def self.getter_setter(attribute)
|
171
|
+
if EasyAttributes::Config.orm == :active_model
|
172
|
+
["self.attributes[:#{attribute}]", "self.write_attribute(:#{attribute}, v)"]
|
173
|
+
else
|
174
|
+
["@#{attribute}", "@#{attribute} = v"]
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def self.pop_options(args, defaults={})
|
179
|
+
args.last.is_a?(Hash) ? defaults.merge(args.pop) : defaults
|
180
|
+
end
|
181
|
+
|
182
|
+
def self.add_definition(attribute, hash, opt={})
|
183
|
+
EasyAttributes::Config.define attribute, hash
|
184
|
+
end
|
185
|
+
|
186
|
+
##############################################################################
|
187
|
+
# attr_values helpers
|
188
|
+
##############################################################################
|
189
|
+
|
190
|
+
# Returns the defined value for the given symbol and attribute
|
191
|
+
def self.value_for_sym(attribute, sym)
|
192
|
+
EasyAttributes::Config.attributes[attribute][sym]
|
193
|
+
end
|
194
|
+
|
195
|
+
# Returns the defined symbol for the given value on the attribute
|
196
|
+
def self.sym_for_value(attribute, value)
|
197
|
+
EasyAttributes::Config.attributes[attribute].each {|k,v| return k if v==value}
|
198
|
+
end
|
199
|
+
|
200
|
+
def self.value_is?(attribute, value, *args)
|
201
|
+
case args.first
|
202
|
+
when :between then
|
203
|
+
value >= EasyAttributes::Config.attributes[attribute][args[1]] && value <= EasyAttributes::Config.attributes[attribute][args[2]]
|
204
|
+
when :gt, :greater_than then
|
205
|
+
value > EasyAttributes::Config.attributes[attribute][args[1]]
|
206
|
+
when :ge, :greater_than_or_equal_to then
|
207
|
+
value >= EasyAttributes::Config.attributes[attribute][args[1]]
|
208
|
+
when :lt, :less_than then
|
209
|
+
value < EasyAttributes::Config.attributes[attribute][args[1]]
|
210
|
+
when :le, :less_than_or_equal_to then
|
211
|
+
value <= EasyAttributes::Config.attributes[attribute][args[1]]
|
212
|
+
#when :not, :not_in
|
213
|
+
# ! args.include? EasyAttributes::Config.attributes[attribute].keys
|
214
|
+
else
|
215
|
+
args.include? EasyAttributes.sym_for_value(v)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
##############################################################################
|
220
|
+
# attr_byte helpers
|
221
|
+
##############################################################################
|
222
|
+
|
223
|
+
# Official Definitions for kilobyte and kibibyte quantity prefixes
|
224
|
+
KB =1000; MB =KB **2; GB= KB **3; TB =KB **4; PB =KB **5; EB =KB **6; ZB =KB **7; YB =KB **8
|
225
|
+
KiB=1024; MiB=KiB**2; GiB=KiB**3; TiB=KiB**4; PiB=KiB**5; EiB=KiB**6; ZiB=KiB**7; YiB=KiB**8
|
226
|
+
DECIMAL_PREFIXES = {:B=>1, :KB=>KB, :MB=>MB, :GB=>GB, :TB=>TB, :PB=>PB, :EB=>EB, :ZB=>ZB, :TB=>YB}
|
227
|
+
BINARY_PREFIXES = {:B=>1, :KiB=>KiB, :MiB=>MiB, :GiB=>GiB, :TiB=>TiB, :PiB=>PiB, :EiB=>EiB, :ZiB=>ZiB, :TiB=>YiB}
|
228
|
+
|
229
|
+
# Returns a hash of prefix names to decimal quantities for the given setting
|
230
|
+
def self.byte_prefixes(kb_size=0)
|
231
|
+
case kb_size
|
232
|
+
when 1000, :decimal, :si then DECIMAL_PREFIXES
|
233
|
+
when :old, :jedec, 1024 then {:KB=>KiB, :MB=>MiB, :GB=>GiB, :TB=>TiB, :PB=>PiB, :EB=>EiB, :ZB=>ZiB, :TB=>YiB}
|
234
|
+
when :new, :iec then BINARY_PREFIXES
|
235
|
+
else DECIMAL_PREFIXES.merge(BINARY_PREFIXES) # Both? What's the least surprise?
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
# Takes a number of bytes and an optional :unit argument and :precision option, returns a formatted string of units
|
240
|
+
def self.format_bytes(v, *args)
|
241
|
+
opt = EasyAttributes.pop_options(args, :precision=>3)
|
242
|
+
prefixes = EasyAttributes.byte_prefixes(opt[:kb_size]||EasyAttributes::Config.kb_size||0)
|
243
|
+
if args.size > 0 && args.first.is_a?(Symbol)
|
244
|
+
(unit, precision) = args
|
245
|
+
v = "%.#{precision||opt[:precision]}f" % (1.0 * v / (prefixes[unit]||1))
|
246
|
+
return "#{v} #{unit}"
|
247
|
+
else
|
248
|
+
precision = args.shift || opt[:precision]
|
249
|
+
prefixes.sort{|a,b| a[1]<=>b[1]}.reverse.each do |pv|
|
250
|
+
next if pv[1] > v
|
251
|
+
v = "%f.10f" % (1.0 * v / pv[1])
|
252
|
+
v = v[0,precision+1] if v =~ /^(\d)+\.(\d+)/ && v.size > (precision+1)
|
253
|
+
v.gsub!(/\.0*$/, '')
|
254
|
+
return "#{v} #{pv[0]}"
|
255
|
+
end
|
256
|
+
end
|
257
|
+
v.to_s
|
258
|
+
end
|
259
|
+
|
260
|
+
# Takes a string of "number units" or Array of [number, :units] and returns the number of bytes represented.
|
261
|
+
def self.parse_bytes(v, *args)
|
262
|
+
opt = EasyAttributes.pop_options(args, :precision=>3)
|
263
|
+
# Handle v= [100, :KB]
|
264
|
+
if v.is_a?(Array)
|
265
|
+
bytes = v.shift
|
266
|
+
v = "#{bytes} #{v.shift}"
|
267
|
+
else
|
268
|
+
bytes = v.to_f
|
269
|
+
end
|
270
|
+
|
271
|
+
if v.downcase =~ /^\s*(?:[\d\.]+)\s*([kmgtpezy]i?b)/i
|
272
|
+
units = ($1.size==2 ? $1.upcase : $1[0,1].upcase+$1[1,1]+$1[2,1].upcase).to_sym
|
273
|
+
prefixes = EasyAttributes.byte_prefixes(opt[:kb_size]||EasyAttributes::Config.kb_size||0)
|
274
|
+
bytes *= prefixes[units] if prefixes.has_key?(units)
|
275
|
+
#puts "v=#{v} b=#{bytes} u=#{units} #{units.class} bp=#{prefixes[units]} kb=#{opt[:kb_size]} P=#{prefixes.inspect}"
|
276
|
+
end
|
277
|
+
(bytes*100).to_i/100
|
278
|
+
end
|
279
|
+
|
280
|
+
##############################################################################
|
281
|
+
# attr_money helpers
|
282
|
+
##############################################################################
|
283
|
+
|
284
|
+
# Returns the money string of the given integer value. Uses relevant options from #easy_money
|
285
|
+
def self.integer_to_money(value, *args)
|
286
|
+
opt = args.last.is_a?(Hash) ? args.pop : {}
|
287
|
+
opt[:positive] ||= "%.#{opt[:precision]||2}f"
|
288
|
+
pattern =
|
289
|
+
if value.nil?
|
290
|
+
value = 0
|
291
|
+
opt[:nil] || opt[:positive]
|
292
|
+
else
|
293
|
+
case value <=> 0
|
294
|
+
when 1 then opt[:positive]
|
295
|
+
when 0 then opt[:zero] || opt[:positive]
|
296
|
+
else
|
297
|
+
value = -value if opt[:negative] && opt[:negative] != opt[:positive]
|
298
|
+
opt[:negative] || opt[:positive]
|
299
|
+
end
|
300
|
+
end
|
301
|
+
value = self.format_money( value, pattern, opt)
|
302
|
+
value = opt[:unit]+value if opt[:unit]
|
303
|
+
value.gsub!(/\./,opt[:separator]) if opt[:separator]
|
304
|
+
if opt[:delimiter] && (m = value.match(/^(\D*)(\d+)(.*)/))
|
305
|
+
# Adapted From Rails' ActionView::Helpers::NumberHelper
|
306
|
+
n = m[2].gsub(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{opt[:delimiter]}")
|
307
|
+
value=m[1]+n+m[3]
|
308
|
+
end
|
309
|
+
value
|
310
|
+
end
|
311
|
+
|
312
|
+
def self.integer_to_float(value, *args)
|
313
|
+
opt = args.last.is_a?(Hash) ? args.pop : {}
|
314
|
+
return (opt[:blank]||nil) if value.nil?
|
315
|
+
value = 1.0 * value / (10**(opt[:precision]||2))
|
316
|
+
end
|
317
|
+
|
318
|
+
# Returns the integer of the given money string. Uses relevant options from #easy_money
|
319
|
+
def self.money_to_integer(value, *args)
|
320
|
+
opt = args.last.is_a?(Hash) ? args.pop : {}
|
321
|
+
value = value.gsub(opt[:delimiter],'') if opt[:delimiter]
|
322
|
+
value = value.gsub(opt[:separator],'.') if opt[:separator]
|
323
|
+
value = value.gsub(/^[^\d\.\-\,]+/,'')
|
324
|
+
return (opt[:blank]||nil) unless value =~ /\d/
|
325
|
+
m = value.to_s.match(opt[:negative_regex]||/^(-?)(.+\d)\s*cr/i)
|
326
|
+
value = value.match(/^-/) ? m[2] : "-#{m[2]}" if m && m[2]
|
327
|
+
|
328
|
+
# Money string ("123.45") to proper integer withough passing through the float transformation
|
329
|
+
match = value.match(/(-?\d*)\.?(\d*)/)
|
330
|
+
return 0 unless match
|
331
|
+
value = match[1].to_i * (10 ** (opt[:precision]||2))
|
332
|
+
cents = match[2]
|
333
|
+
cents = cents + '0' while cents.length < (opt[:precision]||2)
|
334
|
+
cents = cents.to_s[0,opt[:precision]||2]
|
335
|
+
value += cents.to_i * (value<0 ? -1 : 1)
|
336
|
+
value
|
337
|
+
end
|
338
|
+
|
339
|
+
# Returns the integer (cents) value from a Float
|
340
|
+
def self.float_to_integer(value, *args)
|
341
|
+
opt = args.last.is_a?(Hash) ? args.pop : {}
|
342
|
+
return (opt[:blank]||nil) if value.nil?
|
343
|
+
value = (value.to_f*(10**((opt[:precision]||2)+1))).to_i/10 # helps rounding 4.56 -> 455 ouch!
|
344
|
+
end
|
345
|
+
|
346
|
+
# Replacing the sprintf function to deal with money as float. "... %[flags]m ..."
|
347
|
+
def self.format_money(value, pattern="%.2m", *args)
|
348
|
+
opt = args.last.is_a?(Hash) ? args.pop : {}
|
349
|
+
sign = value < 0 ? -1 : 1
|
350
|
+
dollars, cents = value.abs.divmod( 10 ** (opt[:precision]||2))
|
351
|
+
dollars *= sign
|
352
|
+
parts = pattern.match(/^(.*)%([-\. \d+0]*)[fm](.*)/)
|
353
|
+
return pattern unless parts
|
354
|
+
intdec = parts[2].match(/(.*)\.(\d*)/)
|
355
|
+
dprec, cprec = intdec ? [intdec[1], intdec[2]] : ['', '']
|
356
|
+
dollars = sprintf("%#{dprec}d", dollars)
|
357
|
+
cents = '0' + cents.to_s while cents.to_s.length < (opt[:precision]||2)
|
358
|
+
cents = cents.to_s[0,cprec.to_i]
|
359
|
+
cents = cents + '0' while cents.length < cprec.to_i
|
360
|
+
value = parts[1] + "#{(dollars.to_i==0 && sign==-1) ? '-' : '' }#{dollars}#{cents>' '? '.':''}#{cents}" + parts[3]
|
361
|
+
value
|
362
|
+
end
|
363
|
+
|
364
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'test/unit'
|
3
|
+
|
4
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
5
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
6
|
+
require 'easy_attributes'
|
7
|
+
|
8
|
+
class Test::Unit::TestCase
|
9
|
+
end
|
10
|
+
require 'rubygems'
|
11
|
+
require 'test/unit'
|
12
|
+
|
13
|
+
|
14
|
+
class Sample
|
15
|
+
include EasyAttributes
|
16
|
+
attr_accessor :price, :balance
|
17
|
+
attr_money :price
|
18
|
+
attr_money :balance
|
19
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
require 'helper'
|
2
|
+
EasyAttributes::Config.orm = :attr
|
3
|
+
|
4
|
+
class TestEasyAttributes < Test::Unit::TestCase
|
5
|
+
include EasyAttributes
|
6
|
+
attr_sequence :tas, :n1, :n2
|
7
|
+
attr_values :tav, :k1=>1, :k2=>2, :k3=>3
|
8
|
+
attr_values :status, {}, :like=>'TestEasyAttributes#tav'
|
9
|
+
attr_bytes :bw
|
10
|
+
attr_money :amount
|
11
|
+
|
12
|
+
def test_attr_sequence
|
13
|
+
self.tas_sym = :n1
|
14
|
+
assert_equal self.tas, 1
|
15
|
+
assert_equal self.tas_sym, :n1
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_attr_values
|
19
|
+
self.tav_sym = :k1
|
20
|
+
assert_equal tav, 1
|
21
|
+
self.tav_sym = :k2
|
22
|
+
assert_equal tav, 2
|
23
|
+
assert_equal tav_sym, :k2
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_like
|
27
|
+
self.status_sym = :k1
|
28
|
+
assert_equal self.status, 1
|
29
|
+
end
|
30
|
+
|
31
|
+
# Removed for now, not shipping my data file!
|
32
|
+
def test_load
|
33
|
+
#EasyAttributes::Config.load "values"
|
34
|
+
#assert_equal EasyAttributes::Config.attributes['status'][:ok], 8
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_attr_bytes
|
38
|
+
self.bw = 1024
|
39
|
+
assert_equal bw, 1024
|
40
|
+
assert_equal bw_bytes(:KiB, :precision=>0), "1 KiB"
|
41
|
+
self.bw = [1, :kb]
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_format_bytes
|
45
|
+
EasyAttributes::Config.kb_size = :both
|
46
|
+
assert_equal EasyAttributes.format_bytes( 900 ), "900 B"
|
47
|
+
assert_equal EasyAttributes.format_bytes( 1000 ), "1 KB"
|
48
|
+
assert_equal EasyAttributes.format_bytes( 12345 ), "12 KiB"
|
49
|
+
assert_equal EasyAttributes.format_bytes( 123456789 ), "117 MiB"
|
50
|
+
assert_equal EasyAttributes.format_bytes( 9999999999 ), "9.31 GiB"
|
51
|
+
assert_equal EasyAttributes.format_bytes( 123456789, :KiB ), "120563.271 KiB"
|
52
|
+
assert_equal EasyAttributes.format_bytes( 123456789, :KiB, 1 ), "120563.3 KiB"
|
53
|
+
assert_equal EasyAttributes.format_bytes( 123456789, :KiB, 0 ), "120563 KiB"
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_parse_bytes
|
57
|
+
EasyAttributes::Config.kb_size=:both
|
58
|
+
assert_equal EasyAttributes.parse_bytes( "1.5 KiB" ), 1536
|
59
|
+
assert_equal EasyAttributes.parse_bytes( "1 gb" ), EasyAttributes::GB
|
60
|
+
assert_equal EasyAttributes.parse_bytes( "1kb", :kb_size=>1000 ), 1000
|
61
|
+
assert_equal EasyAttributes.parse_bytes( "1kb", :kb_size=>1024 ), 1024
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_include
|
65
|
+
sample = Sample.new
|
66
|
+
flunk "no price_money method" unless sample.respond_to?(:price_money)
|
67
|
+
flunk "no price_money= method" unless sample.respond_to?(:price_money=)
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_method_money
|
71
|
+
s = Sample.new
|
72
|
+
[ 10000, 123456, 0, -1 -9876 ].each do |p|
|
73
|
+
s.price = p
|
74
|
+
m = s.price_money
|
75
|
+
s.price_money = m
|
76
|
+
flunk "Assignment error: p=#{p} m=#{m} price=#{s.price}" unless s.price = p
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_method_money=
|
81
|
+
s = Sample.new
|
82
|
+
{ "0.00"=>0, "12.34"=>1234, "-1.2345"=>-123, "12"=>1200, "4.56CR"=>-456 }.each do |m,p|
|
83
|
+
s.price_money = m
|
84
|
+
flunk "Assignment error: p=#{p} m=#{m} price=#{s.price}" unless s.price = p
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_integer_to_money
|
89
|
+
assert EasyAttributes.integer_to_money(123) == '1.23'
|
90
|
+
assert EasyAttributes.integer_to_money(-12333) == '-123.33'
|
91
|
+
assert EasyAttributes.integer_to_money(0) == '0.00'
|
92
|
+
assert EasyAttributes.integer_to_money(nil, :nil=>'?') == '?'
|
93
|
+
assert EasyAttributes.integer_to_money(-1, :negative=>'%.2f CR') == '0.01 CR'
|
94
|
+
assert EasyAttributes.integer_to_money(0, :zero=>'free') == 'free'
|
95
|
+
assert EasyAttributes.integer_to_money(100, :unit=>'$') == '$1.00'
|
96
|
+
assert EasyAttributes.integer_to_money(100, :separator=>',') == '1,00'
|
97
|
+
assert EasyAttributes.integer_to_money(12345678900, :separator=>',', :delimiter=>'.') == '123.456.789,00'
|
98
|
+
assert EasyAttributes.integer_to_money(333, :precision=>3) == '0.333'
|
99
|
+
assert EasyAttributes.integer_to_money(111, :precision=>1) == '11.1'
|
100
|
+
assert EasyAttributes.integer_to_money(111, :precision=>0) == '111'
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_money_to_integer
|
104
|
+
assert EasyAttributes.money_to_integer('1.23' ) == 123
|
105
|
+
assert EasyAttributes.money_to_integer('0.00' ) == 0
|
106
|
+
assert EasyAttributes.money_to_integer('-1.23' ) == -123
|
107
|
+
assert EasyAttributes.money_to_integer('1.23 CR' ) == -123
|
108
|
+
assert EasyAttributes.money_to_integer('$-2.34 CR' ) == 234
|
109
|
+
assert EasyAttributes.money_to_integer(' 1.234' ) == 123
|
110
|
+
assert EasyAttributes.money_to_integer('$1' ) == 100
|
111
|
+
assert EasyAttributes.money_to_integer('1' ) == 100
|
112
|
+
assert EasyAttributes.money_to_integer('' ) == nil
|
113
|
+
assert EasyAttributes.money_to_integer('1,00', :separator=>',',:delimiter=>'.') == 100
|
114
|
+
assert EasyAttributes.money_to_integer('$123.456.789,00 CR', :separator=>',',:delimiter=>'.') == -12345678900
|
115
|
+
assert EasyAttributes.money_to_integer('4.44', :precision=>4 ) == 44400
|
116
|
+
assert EasyAttributes.money_to_integer('4.44', :precision=>0 ) == 4
|
117
|
+
end
|
118
|
+
|
119
|
+
def test_float_to_integer
|
120
|
+
assert EasyAttributes.float_to_integer(1.00 ) == 100
|
121
|
+
assert EasyAttributes.float_to_integer(1.001 ) == 100
|
122
|
+
assert EasyAttributes.float_to_integer(-1.23 ) == -123
|
123
|
+
assert EasyAttributes.float_to_integer(9.0 ) == 900
|
124
|
+
assert EasyAttributes.float_to_integer(nil ) == nil
|
125
|
+
assert EasyAttributes.float_to_integer(0.00 ) == 0
|
126
|
+
end
|
127
|
+
|
128
|
+
def test_integer_to_float
|
129
|
+
assert EasyAttributes.integer_to_float(1 ) == 0.01
|
130
|
+
assert EasyAttributes.integer_to_float(0 ) == 0.0
|
131
|
+
assert EasyAttributes.integer_to_float(-100 ) == -1.00
|
132
|
+
assert EasyAttributes.integer_to_float(nil ) == nil
|
133
|
+
assert EasyAttributes.integer_to_float(9999888, :precision=>3 ) == 9999.888
|
134
|
+
end
|
135
|
+
|
136
|
+
def test_format_money
|
137
|
+
assert EasyAttributes.format_money(12345) == '123.45'
|
138
|
+
assert EasyAttributes.format_money(12345, "%07.2m") == '0000123.45'
|
139
|
+
assert EasyAttributes.format_money(12345, "%07.3m") == '0000123.450'
|
140
|
+
assert EasyAttributes.format_money(12345, "%m") == '123'
|
141
|
+
assert EasyAttributes.format_money(12345, "free") == 'free'
|
142
|
+
assert EasyAttributes.format_money(-12345) == '-123.45'
|
143
|
+
assert EasyAttributes.format_money(-12345, "%07.1m") == '-000123.4'
|
144
|
+
assert EasyAttributes.format_money(-1) == '-0.01'
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
metadata
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: easy_attributes
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
version: 0.1.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Allen Fair
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-04-28 00:00:00 -04:00
|
18
|
+
default_executable:
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description: Easy Attributes is a Ruby DSL to give more control to attributes.
|
22
|
+
email: allen.fair@gmail.com
|
23
|
+
executables: []
|
24
|
+
|
25
|
+
extensions: []
|
26
|
+
|
27
|
+
extra_rdoc_files:
|
28
|
+
- LICENSE
|
29
|
+
- README.rdoc
|
30
|
+
files:
|
31
|
+
- .document
|
32
|
+
- .gitignore
|
33
|
+
- LICENSE
|
34
|
+
- README.rdoc
|
35
|
+
- Rakefile
|
36
|
+
- VERSION
|
37
|
+
- easy_attributes.gemspec
|
38
|
+
- lib/easy_attributes.rb
|
39
|
+
- test/helper.rb
|
40
|
+
- test/test_easy_attributes.rb
|
41
|
+
has_rdoc: true
|
42
|
+
homepage: http://github.com/afair/easy_attributes
|
43
|
+
licenses: []
|
44
|
+
|
45
|
+
post_install_message:
|
46
|
+
rdoc_options:
|
47
|
+
- --charset=UTF-8
|
48
|
+
require_paths:
|
49
|
+
- lib
|
50
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
segments:
|
55
|
+
- 0
|
56
|
+
version: "0"
|
57
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
segments:
|
62
|
+
- 0
|
63
|
+
version: "0"
|
64
|
+
requirements: []
|
65
|
+
|
66
|
+
rubyforge_project:
|
67
|
+
rubygems_version: 1.3.6
|
68
|
+
signing_key:
|
69
|
+
specification_version: 3
|
70
|
+
summary: Easy Attributes for Ruby
|
71
|
+
test_files:
|
72
|
+
- test/helper.rb
|
73
|
+
- test/test_easy_attributes.rb
|