serial_preference 0.2.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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