serial_preference 0.0.1

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 ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in serial_preference.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 amitsuroliya
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,75 @@
1
+ # SerialPreference
2
+
3
+ If you have a large number of settings/preferences on your model
4
+ (like a company or a businesss) and you store each preference in
5
+ a separate model or in separate columns on the model itself, it
6
+ gets hairy, quickly.
7
+
8
+ Additionally you require those settings/preferences to be read in
9
+ from a form and then you need an easy way to validate them too.
10
+
11
+ Personally, I found that putting settings in the database relationally
12
+ was hellish.
13
+
14
+ SerialPreference stores preferences serialized in a hash in your model.
15
+ All in one place with a DSL to define your settings along with validations
16
+ and other niceties.
17
+
18
+ Scratching my own itch.
19
+
20
+ ## Installation
21
+
22
+ Add this line to your application's Gemfile:
23
+
24
+ gem 'serial_preference'
25
+
26
+ And then execute:
27
+
28
+ $ bundle
29
+
30
+ Or install it yourself as:
31
+
32
+ $ gem install serial_preference
33
+
34
+ ## Usage
35
+
36
+ class Company < ActiveRecord::Base
37
+
38
+ include SerialPreference::Preferencability # will change this
39
+
40
+ preference_map :preferences do
41
+
42
+ preference :taxable data_type: :boolean, required: true, label: "Taxable?", hint: "Is this business taxable?"
43
+ preference :vat_no required: false, label: "VAT"
44
+ preference :max_invoice_items data_type: :integer
45
+
46
+ # default data type is :string
47
+ # default label is name of preference titleized
48
+ # if the preference is required, then a validation is added to the model
49
+ # if the data type is numerical, then a numericality validation is added
50
+ # preferences can be grouped in preference groups
51
+
52
+ preference_group :ledgers, label: "Preferred Ledgers" do
53
+ income_ledger_id data_type: :integer, default: 1
54
+ end
55
+
56
+ # Let me know what you think of this experimental new DSL?
57
+
58
+ + :name_of_preference, data_type: :string
59
+ + :name_of_another_preference, default: "Hello"
60
+
61
+ * :name_of_preference_group, label: "Notifications" do
62
+ + :email_delivery, data_type: :boolean, default: true
63
+ end
64
+
65
+ end
66
+
67
+ end
68
+
69
+ ## Contributing
70
+
71
+ 1. Fork it
72
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
73
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
74
+ 4. Push to the branch (`git push origin my-new-feature`)
75
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,67 @@
1
+ module Preferencability
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ class_attribute :preference_context
6
+ class_attribute :preference_storage_attribute
7
+ self.preference_context = table_name.to_sym
8
+ self.preference_storage_attribute = :preferences
9
+ end
10
+
11
+ def default_preference_for(name)
12
+ self.class.default_preference_for(name)
13
+ end
14
+
15
+ def preferences_for(group_name)
16
+ send(preference_storage_attribute).slice(*self.class.preferences_for(group_name))
17
+ end
18
+
19
+ module ClassMethods
20
+
21
+ def preferences_for(group_name)
22
+ SerialPreference::Preferenzer.group_for(self.preference_context)[group_name].try(:preference_keys) || []
23
+ end
24
+
25
+ def preference_map(store_accessor = :preferences, context = nil, &block)
26
+ self.preference_context = context || self.preference_context
27
+ SerialPreference::Preferenzer.draw(preference_context,&block)
28
+ prefers(store_accessor,preference_context)
29
+ end
30
+
31
+ def default_preference_for(name)
32
+ SerialPreference::Preferenzer.preference(name,nil,preference_context)
33
+ end
34
+
35
+ def prefers(store_accessor = :preferences, context = nil)
36
+ self.preference_context = context || self.preference_context
37
+ self.preference_storage_attribute = store_accessor || self.preference_storage_attribute
38
+ serialize preference_storage_attribute, Hash
39
+
40
+ preferences = SerialPreference::Preferenzer.preferences_for(preference_context)
41
+
42
+ preferences.each do |preference|
43
+ key = preference.name
44
+ define_method("#{key}=") do |value|
45
+ send(:preferences)[key] = SerialPreference::Preferenzer.preference(key,value,context)
46
+ send("preferences_will_change!")
47
+ end
48
+
49
+ define_method(key) do
50
+ SerialPreference::Preferenzer.preference(key,send(:preferences)[key],context)
51
+ end
52
+
53
+ if preference.required?
54
+ validates key, :presence => true
55
+ end
56
+
57
+ if preference.numerical?
58
+ validates key, :numericality => true, :allow_blank => true
59
+ end
60
+
61
+ end
62
+
63
+ end
64
+
65
+ end
66
+
67
+ end
@@ -0,0 +1,42 @@
1
+ class Preference
2
+
3
+ SUPPORTED_TYPES = [:string,:integer,:real,:float,:boolean,:password]
4
+
5
+ attr_accessor :data_type, :name, :default, :required, :label, :hint
6
+
7
+ def initialize(name,opts = {})
8
+ self.data_type = opts[:data_type] || :string
9
+ self.name = name
10
+ self.default = opts[:default]
11
+ self.required = !!opts[:required]
12
+ self.label = opts[:label]
13
+ self.hint = opts[:hint]
14
+ end
15
+
16
+ def required?
17
+ required
18
+ end
19
+
20
+ def numerical?
21
+ [:integer,:float,:real].include?(data_type)
22
+ end
23
+
24
+ def value(value)
25
+ value = value.presence || default
26
+ if !value.nil?
27
+ case data_type
28
+ when :string, :password
29
+ value.to_s
30
+ when :integer
31
+ value.to_i
32
+ when :float, :real
33
+ value.to_f
34
+ when :boolean
35
+ !!value
36
+ else
37
+ nil
38
+ end
39
+ end
40
+ end
41
+
42
+ end
@@ -0,0 +1,41 @@
1
+ class PreferenceGroup
2
+
3
+ attr_accessor :name, :label
4
+
5
+ def initialize(name, opts = {})
6
+ @preferences = {}
7
+ @name = name
8
+ @label = opts[:label]
9
+ end
10
+
11
+ def label
12
+ @label.presence || name.to_s.titleize
13
+ end
14
+
15
+ def preference_keys
16
+ @preferences.keys
17
+ end
18
+
19
+ def preferences
20
+ @preferences.values
21
+ end
22
+
23
+ def pref(name,opts = {})
24
+ @preferences[name] = Preference.new(name,opts)
25
+ end
26
+
27
+ Preference::SUPPORTED_TYPES.each do |dt|
28
+ define_method dt do |name,opts = {}|
29
+ pref(name,opts.merge!(:data_type => dt))
30
+ end
31
+ end
32
+
33
+ def respond_to?(name,*opts)
34
+ @preferences[name].present?
35
+ end
36
+
37
+ def method_missing(name,*opts,&block)
38
+ pref(name,*opts)
39
+ end
40
+
41
+ end
@@ -0,0 +1,3 @@
1
+ module SerialPreference
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,95 @@
1
+ require 'singleton'
2
+ require "serial_preference/version"
3
+ require 'serial_preference/preference'
4
+ require 'serial_preference/preference_group'
5
+ require "serial_preference/preferencability"
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
+ end
21
+
22
+ def +(name,opts = {})
23
+ preference(name,opts)
24
+ end
25
+
26
+ def *(name,opts = {},&block)
27
+ preference_group(name,opts,&block)
28
+ end
29
+
30
+ def preference(name,opts = {})
31
+ pg = base_group
32
+ pg.pref(name,opts)
33
+ end
34
+
35
+ def preference_group(name, opts={},&block)
36
+ self.preference_groups[current_context] ||= {}
37
+ self.preference_groups[current_context][name] ||= PreferenceGroup.new(name,opts)
38
+ self.preference_groups[current_context][name].instance_exec(&block)
39
+ end
40
+
41
+ def self.method_missing(name,*args,&block)
42
+ if instance.respond_to?(name)
43
+ instance.send(name,*args,&block)
44
+ else
45
+ super
46
+ end
47
+ end
48
+
49
+ def all_preference_names(context = :base)
50
+ group_for(context).values.map do |pg|
51
+ pg.preferences.map do |pref|
52
+ pref.name
53
+ end
54
+ end.flatten
55
+ end
56
+
57
+ def preferences_for(context = :base)
58
+ group_for(context).values.map do |pg|
59
+ pg.preferences.map do |pref|
60
+ pref
61
+ end
62
+ end.flatten
63
+ end
64
+
65
+ def each_preference(context = :base)
66
+ group_for(context).values.each do |pg|
67
+ pg.preferences.each do |pref|
68
+ yield(pref)
69
+ end
70
+ end
71
+ end
72
+
73
+ def preference(name,value,context = :base)
74
+ p = preferences_for(context).find{|x| x.name == name }
75
+ p ? p.value(value) : nil
76
+ end
77
+
78
+ def group_for(context = :base)
79
+ preference_groups[context] || {}
80
+ end
81
+
82
+ private
83
+
84
+ def base_group
85
+ @base_group ||= begin
86
+ pg = PreferenceGroup.new(:base,:label => current_context.to_s.titleize)
87
+ self.preference_groups[current_context] ||= {}
88
+ self.preference_groups[current_context][:base] = pg
89
+ pg
90
+ end
91
+ end
92
+
93
+ end
94
+ end
95
+
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'serial_preference/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "serial_preference"
8
+ gem.version = SerialPreference::VERSION
9
+ gem.authors = ["Aditya Sanghi"]
10
+ gem.email = ["aditya.sanghi@risingsuntech.net"]
11
+ gem.description = %q{Serialized Preferences for your models}
12
+ gem.summary = %q{Serialized Preferences for your models}
13
+ gem.homepage = ""
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+ end
metadata ADDED
@@ -0,0 +1,56 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: serial_preference
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Aditya Sanghi
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-09-09 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Serialized Preferences for your models
15
+ email:
16
+ - aditya.sanghi@risingsuntech.net
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - .gitignore
22
+ - Gemfile
23
+ - LICENSE.txt
24
+ - README.md
25
+ - Rakefile
26
+ - lib/serial_preference.rb
27
+ - lib/serial_preference/preferencability.rb
28
+ - lib/serial_preference/preference.rb
29
+ - lib/serial_preference/preference_group.rb
30
+ - lib/serial_preference/version.rb
31
+ - serial_preference.gemspec
32
+ homepage: ''
33
+ licenses: []
34
+ post_install_message:
35
+ rdoc_options: []
36
+ require_paths:
37
+ - lib
38
+ required_ruby_version: !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ required_rubygems_version: !ruby/object:Gem::Requirement
45
+ none: false
46
+ requirements:
47
+ - - ! '>='
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ requirements: []
51
+ rubyforge_project:
52
+ rubygems_version: 1.8.24
53
+ signing_key:
54
+ specification_version: 3
55
+ summary: Serialized Preferences for your models
56
+ test_files: []