serial_preference 0.2.2 → 1.0.0

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/.gitignore CHANGED
@@ -15,3 +15,4 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
+ spec/*.log
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ -c
data/Gemfile CHANGED
@@ -2,3 +2,5 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in serial_preference.gemspec
4
4
  gemspec
5
+
6
+ gem 'debugger'
data/README.md CHANGED
@@ -36,38 +36,47 @@ Or install it yourself as:
36
36
  ````ruby
37
37
  class Company < ActiveRecord::Base
38
38
 
39
- include HasPreferenceMap
39
+ include SerialPreference::HasSerialPreferences
40
40
 
41
- preference_map :preferences do
41
+ preferences do
42
42
 
43
- preference :taxable data_type: :boolean, required: true, label: "Taxable?", hint: "Is this business taxable?"
44
- preference :vat_no required: false, label: "VAT"
43
+ preference :taxable data_type: :boolean, required: true
44
+ preference :vat_no required: false
45
45
  preference :max_invoice_items data_type: :integer
46
46
 
47
+ float :rate_of_interest
48
+
47
49
  # default data type is :string
48
- # default label is name of preference titleized
49
50
  # if the preference is required, then a validation is added to the model
50
51
  # if the data type is numerical, then a numericality validation is added
51
52
  # preferences can be grouped in preference groups
52
53
 
53
- preference_group :ledgers, label: "Preferred Ledgers" do
54
+ preference_group "Preferred Ledgers" do
54
55
  income_ledger_id data_type: :integer, default: 1
55
56
  end
56
57
 
57
- # Let me know what you think of this experimental new DSL?
58
+ password field_type: :password
58
59
 
59
- + :name_of_preference, data_type: :string
60
- + :name_of_another_preference, default: "Hello"
60
+ end
61
61
 
62
- * :name_of_preference_group, label: "Notifications" do
63
- + :email_delivery, data_type: :boolean, default: true
64
- end
62
+ end
63
+ ````
65
64
 
66
- end
65
+ * Fetching Preference/Groups
67
66
 
67
+ ````ruby
68
+ # something you can customize in your form perhaps?
69
+ Company.preference_groups.each do |pg| # => returns an array of preference groups
70
+ # pg.name => Name of Preference Group as specified in map e.g. Preferred Ledgers
71
+ # pg.preferences => Hash of Preference Definitions keyed by Preference Name e.g. :taxable, :vat_no etc.
72
+ pg.preferences.values.each do |preference|
73
+ # preference => PreferenceDefinition
74
+ f.input preference.name, required: preference.required?, placeholder: preference.default, as: preference.field_type
75
+ end
68
76
  end
69
77
  ````
70
78
 
79
+
71
80
  ## Contributing
72
81
 
73
82
  1. Fork it
data/Rakefile CHANGED
@@ -1 +1,7 @@
1
+ #!/usr/bin/env rake
1
2
  require "bundler/gem_tasks"
3
+ require 'rspec/core/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => :spec
@@ -1,78 +1,67 @@
1
- module HasPreferenceMap
2
- extend ActiveSupport::Concern
1
+ module SerialPreference
2
+ module HasSerialPreferences
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ class_attribute :_preferences_attribute
7
+ self._preferences_attribute = :preferences
8
+ class_attribute :_preference_map
9
+ self._preference_map = SerialPreference::Preferenzer.new
10
+ end
3
11
 
4
- included do
5
- class_attribute :preference_context
6
- class_attribute :preference_storage_attribute
7
- self.preference_storage_attribute = :preferences
8
- self.preference_context = "#{preference_storage_attribute}_#{table_name.downcase}".to_sym
9
- end
12
+ module ClassMethods
10
13
 
11
- def default_preference_for(name)
12
- self.class.default_preference_for(name)
13
- end
14
+ def preference_groups
15
+ _preference_map.preference_groups
16
+ end
14
17
 
15
- def preferences_for(group_name)
16
- send(preference_storage_attribute).slice(*self.class.preferences_for(group_name))
17
- end
18
+ def preferences(storage_attribute = nil, &block)
19
+ self._preferences_attribute = storage_attribute || self._preferences_attribute
20
+ _preference_map.draw(&block)
21
+ build_preference_definitions
22
+ end
18
23
 
19
- def preference_map
20
- SerialPreference::Preferenzer.preferences_for(self.class.preference_context)
21
- end
24
+ private
22
25
 
23
- module ClassMethods
26
+ def build_preference_definitions
27
+ serialize self._preferences_attribute, Hash
24
28
 
25
- def preference_groups
26
- SerialPreference::Preferenzer.group_for(preference_context).try(:values) || []
27
- end
29
+ _preference_map.all_preference_definitions.each do |preference|
28
30
 
29
- def preferences_for(group_name)
30
- SerialPreference::Preferenzer.group_for(preference_context)[group_name].try(:preference_keys) || []
31
- end
31
+ key = preference.name
32
+ define_method("#{key}=") do |value|
33
+ write_preference_attribute(_preferences_attribute,key,preference.value(value))
34
+ end
32
35
 
33
- def preference_map(store_attribute = nil, &block)
34
- self.preference_storage_attribute = store_attribute || preference_storage_attribute
35
- self.preference_context = "#{preference_storage_attribute}_#{table_name.downcase}".to_sym
36
- SerialPreference::Preferenzer.reset(preference_context)
37
- preferences = SerialPreference::Preferenzer.draw(preference_context,&block)
36
+ define_method(key) do
37
+ value = read_preference_attribute(_preferences_attribute,key)
38
+ preference.value(value)
39
+ end
38
40
 
39
- make_functions(preferences,store_attribute,preference_context)
40
- end
41
+ if preference.boolean?
42
+ define_method("#{key}?") do
43
+ read_preference_attribute(_preferences_attribute,key).present?
44
+ end
45
+ end
41
46
 
42
- def default_preference_for(name)
43
- SerialPreference::Preferenzer.preference(name,nil,preference_context)
44
- end
45
-
46
- private
47
-
48
- def make_functions(preferences,store_attribute,context)
49
- serialize store_attribute, Hash
50
-
51
- preferences.each do |preference|
52
- key = preference.name
53
- define_method("#{key}=") do |value|
54
- send(store_attribute)[key] = SerialPreference::Preferenzer.preference(key,value,context)
55
- send("#{store_attribute}_will_change!")
56
47
  end
48
+ end
49
+ end
57
50
 
58
- define_method(key) do
59
- value = send(store_attribute)[key]
60
- SerialPreference::Preferenzer.preference(key,value,context)
61
- end
51
+ protected
62
52
 
63
- opts = {}
64
- if preference.required?
65
- opts[:presence] = true
66
- end
67
- if preference.numerical?
68
- opts[:numericality] = true
69
- opts[:allow_blank] = true unless opts[:presence].present?
70
- end
71
- validates key, opts if opts.present?
53
+ def read_preference_attribute(store_attribute, key)
54
+ attribute = send(store_attribute)
55
+ attribute[key]
56
+ end
72
57
 
58
+ def write_preference_attribute(store_attribute, key, value)
59
+ attribute = send(store_attribute)
60
+ if value != attribute[key]
61
+ send :"#{store_attribute}_will_change!"
62
+ attribute[key] = value
73
63
  end
74
64
  end
75
65
 
76
66
  end
77
-
78
- end
67
+ end
@@ -0,0 +1,83 @@
1
+ module SerialPreference
2
+ class PreferenceDefinition
3
+
4
+ SUPPORTED_TYPES = [:string,:integer,:decimal,:float,:boolean]
5
+
6
+ attr_accessor :data_type, :name, :default, :required, :field_type
7
+
8
+ def initialize(name,*args)
9
+ opts = args.extract_options!
10
+ self.name = name.to_s
11
+ opts.assert_valid_keys(:data_type,:default,:required,:field_type)
12
+ self.data_type = @type = opts[:data_type] || :string
13
+ @column = ActiveRecord::ConnectionAdapters::Column.new(name.to_s,opts[:default],@type.to_s)
14
+ self.default = opts[:default]
15
+ self.required = !!opts[:required]
16
+ self.field_type = opts[:field_type]
17
+ end
18
+
19
+ def name
20
+ @column.name
21
+ end
22
+
23
+ def default_value
24
+ @column.default
25
+ end
26
+
27
+ def required?
28
+ required
29
+ end
30
+
31
+ def numerical?
32
+ @column.number?
33
+ end
34
+
35
+ def boolean?
36
+ @column.type == :boolean
37
+ end
38
+
39
+ def type_cast(value)
40
+ v = @column.type_cast(value)
41
+ v.nil? ? default_value : v
42
+ end
43
+
44
+ def field_type
45
+ @field_type || (numerical? ? :string : data_type)
46
+ end
47
+
48
+ def query(value)
49
+ if !(value = type_cast(value))
50
+ false
51
+ elsif numerical?
52
+ !value.zero?
53
+ else
54
+ !value.blank?
55
+ end
56
+ end
57
+
58
+ def value(v)
59
+ v = v.nil? ? default : v
60
+ if !v.nil?
61
+ case data_type
62
+ when :string, :password
63
+ v.to_s
64
+ when :integer
65
+ v.respond_to?(:to_i) ? v.to_i : nil
66
+ when :float, :real
67
+ v.respond_to?(:to_f) ? v.to_f : nil
68
+ when :boolean
69
+ return false if v == 0
70
+ return false if v == ""
71
+ return false if v == nil
72
+ return false if v.to_s.downcase == "false"
73
+ return false if v == "0"
74
+ return false if v.to_s.downcase == "no"
75
+ !!v
76
+ else
77
+ nil
78
+ end
79
+ end
80
+ end
81
+
82
+ end
83
+ end
@@ -0,0 +1,81 @@
1
+ module SerialPreference
2
+ class Preferenzer
3
+ PreferenceGroup = Struct.new(:name,:preferences)
4
+
5
+ attr_reader :preference_groups, :current_group
6
+
7
+ def initialize
8
+ @preference_names_cache = HashWithIndifferentAccess.new
9
+ @preference_groups = []
10
+ activate_group
11
+ end
12
+
13
+ def draw(&block)
14
+ instance_exec(&block)
15
+ end
16
+
17
+ def respond_to?(name)
18
+ [:string, :integer, :boolean, :float].include?(name) || @preference_names_cache[name].present? || super
19
+ end
20
+
21
+ def method_missing(name,*args,&block)
22
+ preference(name,args.extract_options!)
23
+ end
24
+
25
+ [:string,:integer,:boolean,:float].each do |dt|
26
+ define_method(dt) do |name,opts = {}|
27
+ preference(name,opts.merge!(:data_type => dt))
28
+ end
29
+ end
30
+
31
+ def preference(name,opts = {})
32
+ Array(name).each do |n|
33
+ push_preference SerialPreference::PreferenceDefinition.new(n.to_sym,opts)
34
+ end
35
+ end
36
+ alias :pref :preference
37
+
38
+ def preference_group(name,&block)
39
+ activate_group(name)
40
+ instance_exec(&block)
41
+ end
42
+
43
+ def all_preference_definitions
44
+ preference_groups.map{|x|x.preferences.values}.flatten
45
+ end
46
+
47
+ def all_preference_names
48
+ @preference_names_cache.keys
49
+ end
50
+
51
+ def all_groups
52
+ @preference_groups.map{|x|x.name}
53
+ end
54
+
55
+ private
56
+
57
+ def activate_group(group_name = :base)
58
+ @current_group = find_or_create_group(group_name)
59
+ end
60
+
61
+ def push_preference(preference)
62
+ @preference_names_cache[preference.name] = 1
63
+ @current_group.preferences[preference.name] = preference
64
+ end
65
+
66
+ def find_or_create_group(name)
67
+ find_group(name) || create_group(name)
68
+ end
69
+
70
+ def find_group(name)
71
+ @preference_groups.find{|x|x.name == name}
72
+ end
73
+
74
+ def create_group(name = :base)
75
+ PreferenceGroup.new(name,{}).tap do |pg|
76
+ @preference_groups.push(pg)
77
+ end
78
+ end
79
+
80
+ end
81
+ end
@@ -1,3 +1,3 @@
1
1
  module SerialPreference
2
- VERSION = "0.2.2"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -1,100 +1,6 @@
1
- require 'singleton'
1
+ require 'active_support/all'
2
+ require 'active_record'
2
3
  require "serial_preference/version"
3
- require 'serial_preference/preference'
4
- require 'serial_preference/preference_group'
4
+ require 'serial_preference/preference_definition'
5
+ require "serial_preference/preferenzer"
5
6
  require "serial_preference/has_preference_map"
6
-
7
- module SerialPreference
8
- class Preferenzer
9
-
10
- include Singleton
11
-
12
- attr_accessor :preference_groups, :current_context
13
-
14
- def self.draw(context = :base, &block)
15
- i = instance
16
- i.preference_groups ||= {}
17
- i.preference_groups[context] ||= {}
18
- i.current_context = context
19
- i.instance_exec(&block)
20
- i.preferences_for(context)
21
- end
22
-
23
- def +(name,opts = {})
24
- preference(name,opts)
25
- end
26
-
27
- def *(name,opts = {},&block)
28
- preference_group(name,opts,&block)
29
- end
30
-
31
- def reset(context = :base)
32
- self.preference_groups.try(:delete,context)
33
- end
34
-
35
- def preference(name,opts = {})
36
- pg = base_group
37
- pg.pref(name,opts)
38
- end
39
-
40
- def preference_group(name, opts={},&block)
41
- self.preference_groups[current_context] ||= {}
42
- self.preference_groups[current_context][name] ||= SerialPreference::PreferenceGroup.new(name,opts)
43
- self.preference_groups[current_context][name].instance_exec(&block)
44
- end
45
-
46
- def self.method_missing(name,*args,&block)
47
- if instance.respond_to?(name)
48
- instance.send(name,*args,&block)
49
- else
50
- super
51
- end
52
- end
53
-
54
- def all_preference_names(context = :base)
55
- group_for(context).values.map do |pg|
56
- pg.preferences.map do |pref|
57
- pref.name
58
- end
59
- end.flatten
60
- end
61
-
62
- def preferences_for(context = :base)
63
- group_for(context).values.map do |pg|
64
- pg.preferences.map do |pref|
65
- pref
66
- end
67
- end.flatten
68
- end
69
-
70
- def each_preference(context = :base)
71
- group_for(context).values.each do |pg|
72
- pg.preferences.each do |pref|
73
- yield(pref)
74
- end
75
- end
76
- end
77
-
78
- def preference(name,value,context = :base)
79
- p = preferences_for(context).find{|x| x.name == name }
80
- p ? p.value(value) : nil
81
- end
82
-
83
- def group_for(context = :base)
84
- preference_groups[context] || {}
85
- end
86
-
87
- private
88
-
89
- def base_group
90
- @base_group ||= begin
91
- pg = SerialPreference::PreferenceGroup.new(:base,:label => current_context.to_s.titleize)
92
- self.preference_groups[current_context] ||= {}
93
- self.preference_groups[current_context][:base] = pg
94
- pg
95
- end
96
- end
97
-
98
- end
99
- end
100
-
@@ -18,5 +18,10 @@ Gem::Specification.new do |gem|
18
18
  gem.require_paths = ["lib"]
19
19
 
20
20
  gem.add_runtime_dependency "activesupport", ">= 3.0.0"
21
+ gem.add_runtime_dependency "activerecord", ">= 3.0.0"
22
+
23
+ gem.add_development_dependency 'sqlite3'
24
+ gem.add_development_dependency 'rspec-rails'
25
+ gem.add_development_dependency "shoulda"
21
26
 
22
27
  end
data/spec/database.yml ADDED
@@ -0,0 +1,3 @@
1
+ test:
2
+ adapter: sqlite3
3
+ database: ":memory:"
@@ -0,0 +1,12 @@
1
+ class DummyClass < ActiveRecord::Base
2
+ include SerialPreference::HasSerialPreferences
3
+ preferences do
4
+ preference :taxable, data_type: :boolean, required: true
5
+ preference :required_number, data_type: :integer, required: :true
6
+ preference :vat_no, required: false
7
+ preference :max_invoice_items, data_type: :integer
8
+ preference_group "Preferred Ledgers" do
9
+ income_ledger_id data_type: :integer, default: 1
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,83 @@
1
+ require 'spec_helper'
2
+ require 'fixtures/dummy_class'
3
+ describe SerialPreference::HasSerialPreferences do
4
+
5
+ before(:all) do
6
+ rebuild_model
7
+ end
8
+
9
+ context "default behaviour" do
10
+ it "should return preferences as a default _preferences_attribute" do
11
+ DummyClass._preferences_attribute.should eq(:preferences)
12
+ end
13
+ it "should return settings as a _preferences_attribute" do
14
+ class OverriddenPreferenceAttributeClass < ActiveRecord::Base
15
+ include SerialPreference::HasSerialPreferences
16
+ preferences :settings do
17
+ preference :abc
18
+ end
19
+ end
20
+ OverriddenPreferenceAttributeClass._preferences_attribute.should eq(:settings)
21
+ end
22
+ end
23
+
24
+ context "class methods behaviour" do
25
+ it "should be possible to describe preference map thru preferences" do
26
+ DummyClass.respond_to?(:preferences).should be_true
27
+ end
28
+
29
+ it "should be possble to retrieve preference groups from class" do
30
+ DummyClass.respond_to?(:preference_groups).should be_true
31
+ end
32
+ end
33
+
34
+
35
+ context "should define accessors" do
36
+ it "should have readers available" do
37
+ d = DummyClass.new
38
+ d.respond_to?(:taxable).should be_true
39
+ d.respond_to?(:vat_no).should be_true
40
+ d.respond_to?(:max_invoice_items).should be_true
41
+ d.respond_to?(:income_ledger_id).should be_true
42
+ d.respond_to?(:read_preference_attribute).should be_true
43
+ d.respond_to?(:write_preference_attribute).should be_true
44
+ end
45
+
46
+ it "should have writers available" do
47
+ d = DummyClass.new
48
+ d.respond_to?(:taxable=).should be_true
49
+ d.respond_to?(:vat_no=).should be_true
50
+ d.respond_to?(:max_invoice_items=).should be_true
51
+ d.respond_to?(:income_ledger_id=).should be_true
52
+ end
53
+
54
+ it "should have query methods available for booleans" do
55
+ DummyClass.new.respond_to?(:taxable?)
56
+ end
57
+
58
+ end
59
+
60
+ =begin
61
+ context "should define validations" do
62
+ it "should define presence validation on required preferences" do
63
+ d = DummyClass.new
64
+ d.should validate_presence_of(:taxable)
65
+ end
66
+
67
+ it "should define presence and numericality on required preference which are numeric" do
68
+ d = DummyClass.new
69
+ d.taxable = true
70
+ d.should validate_presence_of(:required_number)
71
+ d.should validate_numericality_of(:required_number)
72
+ end
73
+
74
+ it "should define numericality on preference which are numeric" do
75
+ d = DummyClass.new
76
+ d.should validate_numericality_of(:required_number)
77
+ d.should validate_numericality_of(:income_ledger_id)
78
+ end
79
+ end
80
+
81
+ =end
82
+
83
+ end
@@ -0,0 +1,184 @@
1
+ require 'spec_helper'
2
+
3
+ describe SerialPreference::PreferenceDefinition do
4
+
5
+ before do
6
+ @blank_pref = described_class.new("whatever")
7
+ end
8
+
9
+ it "should have proper accessors" do
10
+ [:data_type, :name, :default, :required, :field_type].each do |a|
11
+ @blank_pref.respond_to?(a).should be_true
12
+ end
13
+ end
14
+
15
+ it "should declare supported data types" do
16
+ described_class.constants.should include(:SUPPORTED_TYPES)
17
+ end
18
+
19
+ it "should stringify its name" do
20
+ described_class.new(:whatever).name.should eq("whatever")
21
+ end
22
+
23
+ context "required behaviour" do
24
+ it "should not be required when no required option provided" do
25
+ @blank_pref.should_not be_required
26
+ end
27
+
28
+ it "should be required when required option is truthy" do
29
+ [0,"yes","no","false",true].each do |truthy_values|
30
+ p = described_class.new("whatever",{required: truthy_values})
31
+ p.should be_required
32
+ end
33
+ end
34
+
35
+ it "should not be required when required option is falsy" do
36
+ [false,nil].each do |falsy_values|
37
+ p = described_class.new("whatever",{required: falsy_values})
38
+ p.should_not be_required
39
+ end
40
+ end
41
+ end
42
+
43
+ context "numericality behaviour" do
44
+ it "should not be numerical when no data_type is provided" do
45
+ @blank_pref.should_not be_numerical
46
+ end
47
+
48
+ it "should be numerical when data_type is numerical" do
49
+ [:integer,:float,:decimal].each do |dt|
50
+ described_class.new("whatever",{data_type: dt}).should be_numerical
51
+ end
52
+ end
53
+
54
+ it "should be not numerical when data_type is non numerical" do
55
+ [:string,:boolean,:password,:whatever].each do |dt|
56
+ described_class.new("whatever",{data_type: dt}).should_not be_numerical
57
+ end
58
+ end
59
+ end
60
+
61
+ context "default behaviour" do
62
+ it "should report correct name" do
63
+ @blank_pref.name.should eq("whatever")
64
+ end
65
+ it "should be a string" do
66
+ @blank_pref.data_type.should eq(:string)
67
+ end
68
+ it "should have nil default" do
69
+ @blank_pref.default.should be_nil
70
+ end
71
+ it "should be false for required" do
72
+ @blank_pref.required.should be_false
73
+ end
74
+ it "should have string field_type" do
75
+ @blank_pref.field_type.should eq(:string)
76
+ end
77
+ end
78
+
79
+ context "field_type behaviour" do
80
+ it "should report field_type as provided" do
81
+ described_class.new("whatever",{field_type: :xyz}).field_type.should eq(:xyz)
82
+ end
83
+ it "should report string for numerical data types" do
84
+ described_class.new("whatever",{data_type: :integer}).field_type.should eq(:string)
85
+ end
86
+ it "should report data type for non numeric data types" do
87
+ p = described_class.new("whatever",{data_type: :xyz})
88
+ p.field_type.should eq(p.data_type)
89
+ end
90
+ end
91
+
92
+ context "should report correct preferred values" do
93
+
94
+ context "when input is nil" do
95
+ it "should report nil when no default is given" do
96
+ @blank_pref.value(nil).should be_nil
97
+ end
98
+
99
+ it "should report default when input is nil" do
100
+ p = described_class.new("whatever",{default: "dog"})
101
+ p.value(nil).should eq("dog")
102
+ end
103
+
104
+ it "should report default in appropriate data type when input is nil" do
105
+ p = described_class.new("whatever",{default: "dog", data_type: :integer})
106
+ p.value(nil).should eq("dog".to_i)
107
+ end
108
+ end
109
+
110
+ context "should report correct string/password values" do
111
+ before do
112
+ @preference = described_class.new("whatever",{data_type: :string})
113
+ end
114
+
115
+ it "should return correct strings as passthru" do
116
+ ["",3.0,[],{},"dog",1].each do |input_val|
117
+ @preference.value(input_val).should eq(input_val.to_s)
118
+ end
119
+ end
120
+
121
+ end
122
+
123
+ context "should report correct integer values" do
124
+ before do
125
+ @preference = described_class.new("whatever",{data_type: :integer})
126
+ end
127
+
128
+ it "should return correct integers" do
129
+ ["",1,3.0,"dog"].each do |input_val|
130
+ @preference.value(input_val).should eq(input_val.to_i)
131
+ end
132
+ end
133
+
134
+ it "should report nil for non numeric input" do
135
+ [[],{}].each do |input_val|
136
+ @preference.value(input_val).should be_nil
137
+ end
138
+ end
139
+ end
140
+
141
+ context "should report correct floaty/real values" do
142
+ before do
143
+ @preference = described_class.new("whatever",{data_type: :float})
144
+ end
145
+
146
+ it "should return correct floats" do
147
+ ["",1,3.0,"dog"].each do |input_val|
148
+ @preference.value(input_val).should eq(input_val.to_f)
149
+ end
150
+ end
151
+
152
+ it "should report nil for non numeric input" do
153
+ [[],{}].each do |input_val|
154
+ @preference.value(input_val).should be_nil
155
+ end
156
+ end
157
+ end
158
+
159
+ context "should report correct boolean values" do
160
+ before do
161
+ @preference = described_class.new("whatever",{data_type: :boolean})
162
+ end
163
+ it "should report false for falsy values" do
164
+ [nil,false].each do |falsy|
165
+ @preference.value(falsy).should be_false
166
+ end
167
+ end
168
+
169
+ it "should report false for false looking values" do
170
+ [0,"0","false","FALSE","False","no","NO","No"].each do |falsy|
171
+ @preference.value(falsy).should be_false
172
+ end
173
+ end
174
+
175
+ it "should report true for truthy values" do
176
+ ["yes",true,100,0.1,[],{}].each do |truthy_value|
177
+ @preference.value(truthy_value).should be_true
178
+ end
179
+ end
180
+ end
181
+
182
+ end
183
+
184
+ end
@@ -0,0 +1,111 @@
1
+ require 'spec_helper'
2
+
3
+ describe SerialPreference::Preferenzer do
4
+
5
+ before(:each) do
6
+ @base = described_class::PreferenceGroup.new(:base,{})
7
+ @preferenzer = described_class.new
8
+ end
9
+
10
+ it "should have proper readers" do
11
+ [:preference_groups,:preference,:preference_groups,:all_preference_definitions,:all_preference_names,:current_group].each do |a|
12
+ @preferenzer.should respond_to(a)
13
+ end
14
+ end
15
+
16
+ context "default instance behaviour" do
17
+ it "should report empty preference groups" do
18
+ @preferenzer.preference_groups.should include(@base)
19
+ end
20
+ it "should report current_contex to be nil" do
21
+ @preferenzer.current_group.should eq(@base)
22
+ end
23
+ it "should report all preference name to be empty" do
24
+ @preferenzer.all_preference_names.should be_empty
25
+ end
26
+ it "should report all preference definitions to be empty" do
27
+ @preferenzer.all_preference_definitions.should be_empty
28
+ end
29
+ end
30
+
31
+ context "allows for preferences/groups to be setup using instance" do
32
+
33
+ it "should allow for addition of preference using pref" do
34
+ @preferenzer.pref("whatever")
35
+ @preferenzer.all_preference_names.should include("whatever")
36
+ end
37
+
38
+ it "should allow for addition of preference using preference" do
39
+ @preferenzer.preference("whatever")
40
+ @preferenzer.all_preference_names.should include("whatever")
41
+ end
42
+
43
+ it "should alias preference to pref" do
44
+ described_class.instance_method(:pref).should eq(described_class.instance_method(:preference))
45
+ end
46
+
47
+ it "should allow for addition of preference group" do
48
+ @preferenzer.preference_group(:new_group) do
49
+ preference :new_preference
50
+ end
51
+ @preferenzer.all_preference_names.should include("new_preference")
52
+ end
53
+
54
+ end
55
+
56
+ context "allows for drawing of preference map" do
57
+ it "should setup preferences using draw" do
58
+ @preferenzer.draw do
59
+ preference :name
60
+ pref :age, data_type: :integer
61
+ pref :sex, default: "male"
62
+ preference_group "Email Notifications" do
63
+ email default: false
64
+ switch_off_hour default: 23
65
+ end
66
+ end
67
+ @preferenzer.all_preference_names.should include("age","name","sex","email","switch_off_hour")
68
+ end
69
+
70
+ it "should allow for addition of preference in given context" do
71
+ @preferenzer.all_groups.should_not include(:new_group)
72
+ @preferenzer.preference_group(:new_group) do
73
+ preference "addition"
74
+ end
75
+ @preferenzer.all_preference_names.should include("addition")
76
+ end
77
+
78
+ it "should allow overriding of preference if defined twice" do
79
+ @preferenzer.preference_group(:overriding) do
80
+ preference :overriding_name
81
+ preference :overriding_name
82
+ end
83
+ @preferenzer.all_preference_names.should include("overriding_name", "overriding_name")
84
+ end
85
+
86
+ it "should allow addition of preference to an existing preference group" do
87
+ @preferenzer.preference_group(:notifications) do
88
+ preference :new_preference
89
+ end
90
+ @preferenzer.all_preference_names.should include("new_preference")
91
+ end
92
+
93
+ it "should allow for preference names to be strings or symbols" do
94
+ @preferenzer.preference_group(:notifications) do
95
+ preference "string"
96
+ preference :symbol
97
+ end
98
+ @preferenzer.all_preference_names.should include("string", "symbol")
99
+ end
100
+
101
+ it "should allow for preference_group names to be strings or symbols" do
102
+ @preferenzer.preference_group(:symbol) do
103
+ preference "string"
104
+ end
105
+ @preferenzer.preference_group("string") do
106
+ preference :symbol
107
+ end
108
+ @preferenzer.all_groups.should include("string", :symbol)
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,24 @@
1
+ $:.unshift File.expand_path('..', __FILE__)
2
+ $:.unshift File.expand_path('../../lib', __FILE__)
3
+ require 'active_support/all'
4
+ require 'active_record'
5
+ require 'rspec'
6
+ require 'shoulda'
7
+ require "serial_preference/version"
8
+ require 'serial_preference/preference_definition'
9
+ require "serial_preference/preferenzer"
10
+ require "serial_preference/has_preference_map"
11
+
12
+ FIXTURES_DIR = File.join(File.dirname(__FILE__), "fixtures")
13
+ config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
14
+ ActiveRecord::Base.logger = ActiveSupport::BufferedLogger.new(File.dirname(__FILE__) + "/debug.log")
15
+ ActiveRecord::Base.establish_connection(config['test'])
16
+
17
+ RSpec.configure do |config|
18
+ end
19
+
20
+ def rebuild_model options = {}
21
+ ActiveRecord::Base.connection.create_table :dummy_classes, :force => true do |table|
22
+ table.column :preferences, :text
23
+ end
24
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: serial_preference
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 1.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-09-09 00:00:00.000000000 Z
12
+ date: 2012-09-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -27,6 +27,70 @@ dependencies:
27
27
  - - ! '>='
28
28
  - !ruby/object:Gem::Version
29
29
  version: 3.0.0
30
+ - !ruby/object:Gem::Dependency
31
+ name: activerecord
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: 3.0.0
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: 3.0.0
46
+ - !ruby/object:Gem::Dependency
47
+ name: sqlite3
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rspec-rails
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: shoulda
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
30
94
  description: Serialized Preferences for your models
31
95
  email:
32
96
  - aditya.sanghi@risingsuntech.net
@@ -35,16 +99,23 @@ extensions: []
35
99
  extra_rdoc_files: []
36
100
  files:
37
101
  - .gitignore
102
+ - .rspec
38
103
  - Gemfile
39
104
  - LICENSE.txt
40
105
  - README.md
41
106
  - Rakefile
42
107
  - lib/serial_preference.rb
43
108
  - lib/serial_preference/has_preference_map.rb
44
- - lib/serial_preference/preference.rb
45
- - lib/serial_preference/preference_group.rb
109
+ - lib/serial_preference/preference_definition.rb
110
+ - lib/serial_preference/preferenzer.rb
46
111
  - lib/serial_preference/version.rb
47
112
  - serial_preference.gemspec
113
+ - spec/database.yml
114
+ - spec/fixtures/dummy_class.rb
115
+ - spec/has_preference_map_spec.rb
116
+ - spec/preference_definition_spec.rb
117
+ - spec/preferenzer_spec.rb
118
+ - spec/spec_helper.rb
48
119
  homepage: ''
49
120
  licenses: []
50
121
  post_install_message:
@@ -57,16 +128,28 @@ required_ruby_version: !ruby/object:Gem::Requirement
57
128
  - - ! '>='
58
129
  - !ruby/object:Gem::Version
59
130
  version: '0'
131
+ segments:
132
+ - 0
133
+ hash: 617750894719650316
60
134
  required_rubygems_version: !ruby/object:Gem::Requirement
61
135
  none: false
62
136
  requirements:
63
137
  - - ! '>='
64
138
  - !ruby/object:Gem::Version
65
139
  version: '0'
140
+ segments:
141
+ - 0
142
+ hash: 617750894719650316
66
143
  requirements: []
67
144
  rubyforge_project:
68
145
  rubygems_version: 1.8.24
69
146
  signing_key:
70
147
  specification_version: 3
71
148
  summary: Serialized Preferences for your models
72
- test_files: []
149
+ test_files:
150
+ - spec/database.yml
151
+ - spec/fixtures/dummy_class.rb
152
+ - spec/has_preference_map_spec.rb
153
+ - spec/preference_definition_spec.rb
154
+ - spec/preferenzer_spec.rb
155
+ - spec/spec_helper.rb
@@ -1,55 +0,0 @@
1
- module SerialPreference
2
- class Preference
3
-
4
- SUPPORTED_TYPES = [:string,:integer,:real,:float,:boolean,:password]
5
-
6
- attr_accessor :data_type, :name, :default, :required, :label, :hint, :field_type
7
-
8
- def initialize(name,opts = {})
9
- self.data_type = opts[:data_type] || :string
10
- self.name = name
11
- self.default = opts[:default]
12
- self.required = !!opts[:required]
13
- self.label = opts[:label]
14
- self.hint = opts[:hint]
15
- self.field_type = opts[:field_type]
16
- end
17
-
18
- def required?
19
- required
20
- end
21
-
22
- def numerical?
23
- [:integer,:float,:real].include?(data_type)
24
- end
25
-
26
- def field_type
27
- @field_type || (numerical? ? :string : data_type)
28
- end
29
-
30
- def value(value)
31
- value = value.nil? ? default : value
32
- if !value.nil?
33
- case data_type
34
- when :string, :password
35
- value.to_s
36
- when :integer
37
- value.to_i
38
- when :float, :real
39
- value.to_f
40
- when :boolean
41
- return false if value == 0
42
- return false if value == ""
43
- return false if value == nil
44
- return false if value.to_s.downcase == "false"
45
- return false if value == "0"
46
- return false if value.to_s.downcase == "no"
47
- !!value
48
- else
49
- nil
50
- end
51
- end
52
- end
53
-
54
- end
55
- end
@@ -1,51 +0,0 @@
1
- module SerialPreference
2
- class PreferenceGroup
3
-
4
- attr_accessor :name, :label
5
-
6
- def initialize(name, opts = {})
7
- @preferences = {}
8
- @name = name
9
- @label = opts[:label]
10
- end
11
-
12
- def to_s
13
- name.to_s
14
- end
15
-
16
- def titleize
17
- label
18
- end
19
-
20
- def label
21
- @label.presence || name.to_s.titleize
22
- end
23
-
24
- def preference_keys
25
- @preferences.keys
26
- end
27
-
28
- def preferences
29
- @preferences.values
30
- end
31
-
32
- def pref(name,opts = {})
33
- @preferences[name] = Preference.new(name,opts)
34
- end
35
-
36
- SerialPreference::Preference::SUPPORTED_TYPES.each do |dt|
37
- define_method dt do |name,opts = {}|
38
- pref(name,opts.merge!(:data_type => dt))
39
- end
40
- end
41
-
42
- def respond_to?(name,*opts)
43
- @preferences[name].present?
44
- end
45
-
46
- def method_missing(name,*opts,&block)
47
- pref(name,*opts)
48
- end
49
-
50
- end
51
- end