hash_accessor 1.0.2 → 1.0.4

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/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