hash_accessor 1.0.2 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -1,21 +1,21 @@
1
1
  = HashAccessor
2
2
 
3
- This gem provides accessor methods to hash keys with enough intelligence to make them useful!
3
+ This gem provides similar functionality to Rails' new ActiveAttr, except with a bunch of powerful methods behind it. Type definitions, defaults, lambdas on arrays, and more.
4
4
 
5
- The purpose behind building HashAccessor was to be able to quickly add/modify/remove variables being stored in a serialized hash of a rails model. This is very useful if you have a large list of often changing variables on a model which don't get queried against. You can create new variables without messing up your DB. Storing account configurations or custom themes is a common scenario.
5
+ The purpose behind building HashAccessor was to be able to quickly add/modify/remove variables being stored in a serialized hash of a rails model. This is very useful if you have a large list of often changing variables on a model which don't get queried against. You can create new variables without messing up your DB. Storing account configurations or custom themes is a common scenario.
6
6
 
7
7
  This gem was designed to have HTML forms update directly to the hash, but maintain the correct class (respecting :attr_accessible of course). Options like :default, :type, and :collects are particularly helpful when dealing with forms.
8
8
 
9
- == Installation
9
+ == Installation
10
10
 
11
11
  In your <code>Gemfile</code>:
12
12
 
13
13
  gem "hash_accessor"
14
14
 
15
15
  Then run:
16
-
16
+
17
17
  bundle install
18
-
18
+
19
19
  == Usage
20
20
 
21
21
  You define each accessor you want to be stored inside the serialized hash
@@ -30,24 +30,24 @@ Here is an example:
30
30
  hash_accessor :options, :currency, :default => "$USD"
31
31
  hash_accessor :options, :display_currency_on_invoices, :type => :boolean, :default => true
32
32
  hash_accessor :options, :invoice_due_date_net, :type => :integer, :default => 3
33
-
34
-
33
+
34
+
35
35
  def some_method
36
-
36
+
37
37
  self.currency = "$CAD"
38
-
38
+
39
39
  display_currency_on_invoices?
40
-
40
+
41
41
  ...
42
42
  end
43
-
43
+
44
44
  end
45
45
 
46
46
  === Valid Options:
47
47
 
48
48
  <code>:default</code> - if undefined, this plugin will create an empty instance of the defined type or null
49
49
 
50
- <code>:type</code> - defaults to :string. Can also be :integer, :float, :boolean, or :array
50
+ <code>:type</code> - defaults to :string. Can also be :integer, :float, :decimal, :boolean, or :array
51
51
 
52
52
  ==== For Arrays only:
53
53
  <code>:collects</code> - only runs on arrays. Calls the lambda method on each item in the array before saving
@@ -6,20 +6,20 @@ Gem::Specification.new do |s|
6
6
  s.author = ["Forrest"]
7
7
  s.email = ["development@forrestzeisler.com"]
8
8
  s.date = Time.now.utc.strftime("%Y-%m-%d")
9
-
10
-
9
+
10
+
11
11
  s.description = 'This gem provides accessor methods to hash keys.'
12
12
  s.summary = "This gem provides extended functionality to serialized hashed in rails. It allows you to define accessor methods for variable that rest "+
13
13
  "inside a serialized hash. This is very useful if you have a large list of often changing DB variables on a model which don't get queried against."
14
-
14
+
15
15
  s.required_rubygems_version = ">= 1.3.6"
16
16
  s.platform = Gem::Platform::RUBY
17
- s.add_dependency 'activesupport', '>= 3.1.0'
17
+ s.add_dependency 'activesupport', '>= 3.2.0'
18
18
 
19
19
  s.files = `git ls-files`.split("\n")
20
20
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
21
21
  s.require_path = "lib"
22
-
22
+
23
23
  s.has_rdoc = true
24
24
  s.extra_rdoc_files = ["README.rdoc"]
25
- end
25
+ end
data/lib/hash_accessor.rb CHANGED
@@ -4,12 +4,12 @@ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname
4
4
  require 'hash_accessor/railtie' if defined?(Rails)
5
5
 
6
6
  module HashAccessor
7
- VERSION = "1.0.2"
8
-
9
- autoload :ClassMethods, 'hash_accessor/class_methods'
10
-
7
+ VERSION = "1.0.4"
8
+
9
+ autoload :ClassMethods, 'hash_accessor/class_methods'
10
+
11
11
  def self.included(mod)
12
12
  mod.extend(ClassMethods)
13
13
  end
14
14
 
15
- end
15
+ end
@@ -1,7 +1,12 @@
1
1
  require 'active_support/core_ext/object/blank'
2
+ require 'active_support/core_ext/object/try'
3
+ require 'active_support/core_ext/array/wrap'
4
+ require "bigdecimal"
5
+ require "bigdecimal/util"
2
6
 
3
7
  module HashAccessor
4
8
  module ClassMethods
9
+
5
10
  #valid options:
6
11
  # :default - if undefined, this plugin will create an empty instance of the defined type or null
7
12
  # :type - defaults to :string. Can also be :integer, :float, :boolean, or :array
@@ -10,81 +15,88 @@ module HashAccessor
10
15
  # :collects - only runs on arrays. Calls the lambda method on each item in the array before saving
11
16
  # :reject_blanks - removes all blank elements after the collect method
12
17
  def hash_accessor(hash_name, method_name, options = {})
13
- method_modifier = ""
14
18
  begin
15
-
16
- if options[:type]==:integer
17
- method_modifier = "new_val = new_val.to_i"
18
- elsif options[:type]==:float
19
- method_modifier = "new_val = new_val.to_f"
20
- elsif options[:type]==:boolean or options[:type]==:bool
21
- method_modifier = "new_val = (new_val.is_a?(TrueClass) or (new_val.is_a?(String) and (new_val=~/true|1/i).present?) or (new_val.is_a?(Fixnum) and new_val==1))"
22
- elsif options[:type]==:array
23
- method_modifier = "new_val = [new_val] unless new_val.is_a?(Array)"
19
+ method_modifier = hash_accessor_method_modifier(method_name, options)
20
+ default = hash_accessor_default(options)
24
21
 
25
- if options[:collects]
26
- self.class_variable_set("@@lambda_for_#{method_name}", options[:collects])
27
- method_modifier += "\nnew_val = new_val.collect(&@@lambda_for_#{method_name})"
28
- end
29
-
30
- if options[:reject_blanks]
31
- method_modifier += "\nnew_val = new_val.reject(&:blank?)"
22
+ # Define getter
23
+ define_method(method_name) do
24
+ send("#{hash_name}=", {}) if send(hash_name).blank?
25
+ if self.send(hash_name)[method_name].nil?
26
+ self.send(hash_name)[method_name] = default
32
27
  end
28
+ self.send(hash_name)[method_name]
33
29
  end
34
30
 
31
+ # Define setter
32
+ define_method("#{method_name}=") do |*args|
33
+ new_val = args[0]
34
+ self.send("#{hash_name}=", {}) if send(hash_name).blank?
35
+ new_val = method_modifier.call(new_val)
36
+ if self.send(hash_name)[method_name] != new_val
37
+ instance_variable_set("@#{method_name}_changed", true)
38
+ end
39
+ self.send(hash_name)[method_name] = new_val
40
+ end
35
41
 
36
-
37
- if options[:default].is_a?(String)
38
- default = "\"#{options[:default]}\""
39
- elsif options[:default].nil? and options[:type]==:array
40
- default = "[]"
41
- elsif options[:default].nil?
42
- default = "nil"
43
- else
44
- default = options[:default]
42
+ # Define changed?
43
+ define_method("#{method_name}_changed?") do
44
+ !!instance_variable_get("@#{method_name}_changed")
45
45
  end
46
46
 
47
- str = <<-EOS
48
- def #{method_name}
49
- self.#{hash_name} ||= {}
47
+ # Define special boolean accessor
48
+ if options[:type]==:boolean or options[:type]==:bool
49
+ define_method("#{method_name}?") do
50
+ !!send(method_name)
51
+ end
52
+ end
50
53
 
51
- if self.#{hash_name}[:#{method_name}].nil?
52
- self.#{hash_name}[:#{method_name}] = #{default}
53
- end
54
+ rescue Exception => e
55
+ puts "\n\nError adding hash_accessor:\n#{e.message}\n#{e.backtrace}\n\n"
56
+ end
57
+ end
54
58
 
55
- self.#{hash_name}[:#{method_name}]
56
- end
59
+ private
57
60
 
58
- def #{method_name}=(new_val)
59
- self.#{hash_name} ||= {}
60
- #{method_modifier}
61
+ def hash_accessor_method_modifier(method_name, options)
62
+ case options[:type]
63
+ when :integer
64
+ lambda {|new_val| new_val.try(:to_i) }
65
+ when :float
66
+ lambda {|new_val| new_val.try(:to_f) }
67
+ when :decimal
68
+ lambda {|new_val| new_val.try(:to_d) }
69
+ when :boolean, :bool
70
+ lambda {|new_val| (new_val.is_a?(TrueClass) or (new_val.is_a?(String) and (new_val=~/true|1/i).present?) or (new_val.is_a?(Fixnum) and new_val==1)) }
71
+ when :array
72
+ lambda {|new_val|
73
+ new_val = Array.wrap(new_val)
61
74
 
62
- if self.#{hash_name}[:#{method_name}] != new_val
63
- @#{method_name}_changed = true
64
- end
65
-
66
- self.#{hash_name}[:#{method_name}] = new_val
67
- end
75
+ if options[:collects]
76
+ new_val = new_val.collect(&options[:collects])
77
+ end
68
78
 
69
- def #{method_name}_changed?
70
- !!@#{method_name}_changed
71
- end
72
- EOS
79
+ if options[:reject_blanks]
80
+ new_val.reject!(&:blank?)
81
+ end
73
82
 
74
- if options[:type]==:boolean or options[:type]==:bool
75
- str += <<-EOS
76
- def #{method_name}?
77
- !!self.#{method_name}
78
- end
79
- EOS
80
- end
83
+ new_val
84
+ }
85
+ else lambda {|new_val| new_val}
86
+ end
87
+ end
81
88
 
82
- class_eval str
83
- rescue Exception => e
84
- puts "\n\nError adding hash_accessor:\n#{e.message}\n#{e.backtrace}\n\n"
89
+ def hash_accessor_default(options)
90
+ if options[:default].is_a?(String)
91
+ default = options[:default]
92
+ elsif options[:default].nil? and options[:type]==:array
93
+ default = []
94
+ elsif options[:default].nil?
95
+ default = nil
96
+ else
97
+ default = options[:default]
85
98
  end
86
-
87
99
  end
88
100
  end
89
-
90
- end
101
+
102
+ end
@@ -2,8 +2,8 @@ module HashAccessor
2
2
  class Railtie < Rails::Railtie
3
3
 
4
4
  config.to_prepare do
5
- ActiveRecord::Base.send :include, HashAccessor
5
+ ActiveRecord::Base.send :include, HashAccessor
6
6
  end
7
-
7
+
8
8
  end
9
- end
9
+ end
@@ -1,4 +1,5 @@
1
1
  require 'test/unit'
2
+
2
3
  require File.expand_path("../lib/hash_accessor", File.dirname(__FILE__))
3
4
 
4
5
  class HashAccessorTest < Test::Unit::TestCase
@@ -6,50 +7,54 @@ class HashAccessorTest < Test::Unit::TestCase
6
7
  class TestClassWithHash
7
8
  include HashAccessor
8
9
  attr_accessor :options
9
-
10
+
10
11
  hash_accessor :options, :unspecified_variable
11
12
  hash_accessor :options, :test_integer, :type => :integer
13
+ hash_accessor :options, :test_decimal, :type => :decimal
12
14
  hash_accessor :options, :test_bool, :type => :bool
13
- hash_accessor :options, :test_array_1, :type => :array, :collects => lambda{|item| item.gsub(/li_/, "").to_i }
15
+ hash_accessor :options, :test_array_1, :type => :array, :collects => lambda{|item|
16
+ item.gsub(/li_/, "").to_i
17
+ }
14
18
  hash_accessor :options, :test_array_2, :type => :array, :reject_blanks => true
15
-
19
+
16
20
  def initialize
17
21
  options = {}
18
22
  end
19
23
  end
20
-
24
+
21
25
  def setup
22
26
  @tester = TestClassWithHash.new
23
27
  end
24
28
 
25
29
  def test_accessors_being_added_correct
26
30
  assert @tester.respond_to?(:unspecified_variable)
27
-
31
+
28
32
  @tester.unspecified_variable = "some test"
29
33
  assert_equal "some test", @tester.unspecified_variable
30
34
  end
31
-
35
+
32
36
  def test_accessors_being_casted_correctly
33
37
  @tester.test_integer = "3"
38
+ @tester.test_decimal = "3"
34
39
  assert_equal 3, @tester.test_integer
40
+ assert_equal 3.to_d, @tester.test_decimal
35
41
  end
36
-
42
+
37
43
  def test_boolean_question_mark_method_being_added
38
44
  assert !@tester.test_bool?
39
45
  @tester.test_bool = true
40
46
  assert @tester.test_bool?
41
47
  end
42
-
48
+
43
49
  def test_array_collect_method
44
50
  assert_equal [], @tester.test_array_1
45
51
  @tester.test_array_1 = ["li_1", "li_2", "li_3"]
46
52
  assert_equal [1, 2, 3], @tester.test_array_1
47
53
  end
48
-
54
+
49
55
  def test_array_reject_blank_method
50
56
  @tester.test_array_2 = ["", "1", "2"]
51
57
  assert_equal ["1", "2"], @tester.test_array_2
52
58
  end
53
-
54
-
55
- end
59
+
60
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hash_accessor
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,19 +9,24 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-01-22 00:00:00.000000000Z
12
+ date: 2012-09-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
16
- requirement: &70357302568320 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
20
20
  - !ruby/object:Gem::Version
21
- version: 3.1.0
21
+ version: 3.2.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70357302568320
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 3.2.0
25
30
  description: This gem provides accessor methods to hash keys.
26
31
  email:
27
32
  - development@forrestzeisler.com
@@ -60,7 +65,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
60
65
  version: 1.3.6
61
66
  requirements: []
62
67
  rubyforge_project:
63
- rubygems_version: 1.8.10
68
+ rubygems_version: 1.8.22
64
69
  signing_key:
65
70
  specification_version: 3
66
71
  summary: This gem provides extended functionality to serialized hashed in rails. It
@@ -69,3 +74,4 @@ summary: This gem provides extended functionality to serialized hashed in rails.
69
74
  on a model which don't get queried against.
70
75
  test_files:
71
76
  - test/hash_accessor_test.rb
77
+ has_rdoc: true