preferred 0.1.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 845a796bc25a6fbbfdca3d033a224e6d5dc0f9d4
4
+ data.tar.gz: 417e5f78aeab9ae1e551207bf7c1d7cfc46cc07e
5
+ SHA512:
6
+ metadata.gz: cfce22e8f4fe07323d9f6d67af82dfea84591e19c7e8291cc247899c330d553352dc54f4ec3cb921529c0b71712cf96d0531d08b1e719b95bf60f829b27f3408
7
+ data.tar.gz: 4d43fdb6179fac9ba952c4d830edb042d8888f9c50c626a0bfed68caac9c2be628c6bcdd2149bbfab067240cd7cc6c18126b840026b157ff59a75ccb892b3287
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2018
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,101 @@
1
+ # preferred
2
+
3
+ preferred provides a simple mechanism defining and storing preferences on a model.
4
+ This becomes powerful when used in conjunction with Single Table Inheritance
5
+ in Rails. Concepts for this gem were initially taken from the Spree open source
6
+ project and ported to use PostgreSQL JSONB columns instead of separate preferences
7
+ table.
8
+
9
+ # Usage
10
+
11
+ To install preferred add the following to your Gemfile
12
+
13
+ ```ruby
14
+ gem 'preferred', git: 'https://github.com/nwwatson/preferred.git'
15
+ ```
16
+
17
+ Once in your Gemfile
18
+
19
+ ```shell
20
+ bundle install
21
+ ```
22
+
23
+ # Simple Example
24
+
25
+ This simple example shows how to use preferred in a Rails model. Default values are optional. Preferred will provides types for string, decimal, integer, boolean, and date. Preferences are prefixed with "preferred_".
26
+
27
+ Create a model and ensure that it has a JSONB column called preference_hash
28
+
29
+ ```shell
30
+ bin/rails g model example_model preference_hash:jsonb
31
+ ```
32
+
33
+ Define preferences in the model and use
34
+
35
+ ```ruby
36
+ class ExampleModel < ApplicationRecord
37
+ include Preferred::Preferable
38
+
39
+ preference :nickname, :string
40
+ preference :min_value, :decimal, default: 32.0
41
+ preference :year, :integer, default: 2018
42
+ preference :has_example, :boolean, default: true
43
+ preference :birthday, :date, default: Date.today
44
+ end
45
+
46
+ example_model = ExampleModel.new
47
+ example_model.has_preference?(:min_value) # returns true
48
+ example_model.preferred_min_value # returns 32.0
49
+ example_model.preferred_min_value = 0 # sets min_value to 0
50
+ example_model.preference_default(:min_value) # returns 32.0
51
+ example_model.preference_type(:min_value) # returns :decimal
52
+ ```
53
+
54
+ # Complex example using Single Table Inheritance
55
+
56
+ Create base model
57
+
58
+ ```
59
+ bin/rails g model strategy description:string type:string preference_hash:jsonb
60
+ ```
61
+
62
+ ## Include Preferable in Strategy model
63
+
64
+ ```ruby
65
+ class Strategy < ApplicationRecord
66
+ include Preferred::Preferable
67
+
68
+ validates_presence_of :description
69
+
70
+ end
71
+ ```
72
+
73
+ Define a models that extends Strategy
74
+
75
+ ## WithinRange Strategy
76
+
77
+ ```ruby
78
+ class WithinRange < Strategy
79
+ # The minimum temperature value for the range
80
+ preference :min, :decimal, default: 28.0
81
+ # The maximum temperature value for the range
82
+ preference :max, :decimal, default: 42.0
83
+
84
+ def good?(value)
85
+ (value => preferred_min) and (value <= preferred_max)
86
+ end
87
+ end
88
+ ```
89
+
90
+ ## BelowMaximum Strategy
91
+
92
+ ```ruby
93
+ class BelowMaximum < Strategy
94
+ # The maximum temperature allowed
95
+ preference :max, :decimal, default: 160.0
96
+
97
+ def good?(value)
98
+ value < preferred_max
99
+ end
100
+ end
101
+ ```
data/Rakefile ADDED
@@ -0,0 +1,27 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'Preferred'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.md')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ require 'bundler/gem_tasks'
18
+
19
+ require 'rake/testtask'
20
+
21
+ Rake::TestTask.new(:test) do |t|
22
+ t.libs << 'test'
23
+ t.pattern = 'test/**/*_test.rb'
24
+ t.verbose = false
25
+ end
26
+
27
+ task default: :test
data/lib/preferred.rb ADDED
@@ -0,0 +1,7 @@
1
+ require "preferred/railtie"
2
+ require "preferred/preferable_class_methods"
3
+ require "preferred/preferable"
4
+
5
+ module Preferred
6
+ # Your code goes here...
7
+ end
@@ -0,0 +1,84 @@
1
+ module Preferred::Preferable
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ extend PreferableClassMethods
6
+ end
7
+
8
+ def get_preference(name)
9
+ has_preference! name
10
+ send self.class.preference_getter_method(name)
11
+ end
12
+ alias :preferred :get_preference
13
+ alias :prefers? :get_preference
14
+
15
+ def set_preference(name, value)
16
+ has_preference! name
17
+ send self.class.preference_setter_method(name), value
18
+ end
19
+
20
+ def preference_type(name)
21
+ has_preference! name
22
+ send self.class.preference_type_getter_method(name)
23
+ end
24
+
25
+ def preference_default(name)
26
+ has_preference! name
27
+ send self.class.preference_default_getter_method(name)
28
+ end
29
+
30
+ def preference_description(name)
31
+ has_preference! name
32
+ send self.class.preference_description_getter_method(name)
33
+ end
34
+
35
+ def has_preference!(name)
36
+ raise NoMethodError.new "#{name} preference not defined" unless has_preference? name
37
+ end
38
+
39
+ def has_preference?(name)
40
+ respond_to? self.class.preference_getter_method(name)
41
+ end
42
+
43
+ def preferences
44
+ prefs = {}
45
+ methods.grep(/^prefers_.*\?$/).each do |pref_method|
46
+ prefs[pref_method.to_s.gsub(/prefers_|\?/, '').to_sym] = send(pref_method)
47
+ end
48
+ prefs
49
+ end
50
+
51
+ def clear_preferences
52
+ preference_hash.keys.each {|pref| preference_hash.delete pref} if preference_hash.is_a? Hash
53
+ end
54
+
55
+ private
56
+
57
+ def convert_preference_value(value, type)
58
+ case type
59
+ when :string, :text
60
+ value.to_s
61
+ when :password
62
+ value.to_s
63
+ when :decimal
64
+ BigDecimal.new(value.to_s)
65
+ when :integer
66
+ value.to_i
67
+ when :boolean
68
+ if value.is_a?(FalseClass) ||
69
+ value.nil? ||
70
+ value == 0 ||
71
+ value =~ /^(f|false|0)$/i ||
72
+ (value.respond_to? :empty? and value.empty?)
73
+ false
74
+ else
75
+ true
76
+ end
77
+ when :date
78
+ value.is_a?(Date) ? value : Date.parse(value)
79
+ else
80
+ value
81
+ end
82
+ end
83
+
84
+ end
@@ -0,0 +1,69 @@
1
+ module Preferred::Preferable
2
+
3
+ def preference(name, type, *args)
4
+ options = args.extract_options!
5
+ options.assert_valid_keys(:default, :description)
6
+ default = options[:default]
7
+ description = options[:description] || name
8
+
9
+ # cache_key will be nil for new objects, then if we check if there
10
+ # is a pending preference before going to default
11
+ define_method preference_getter_method(name) do
12
+ if self.preference_hash && preference_hash.key?(name.to_s)
13
+ convert_preference_value(preference_hash[name.to_s]["value"], preference_hash[name.to_s]["type"])
14
+ else
15
+ send self.class.preference_default_getter_method(name)
16
+ end
17
+ end
18
+
19
+ define_method preference_setter_method(name) do |value|
20
+ value = convert_preference_value(value, type)
21
+ self.preference_hash = {} if preference_hash.nil?
22
+ self.preference_hash[name.to_s] = {
23
+ value: value,
24
+ type: type
25
+ }
26
+ end
27
+
28
+ define_method preference_default_getter_method(name) do
29
+ default
30
+ end
31
+
32
+ define_method preference_type_getter_method(name) do
33
+ type
34
+ end
35
+
36
+ define_method preference_description_getter_method(name) do
37
+ description
38
+ end
39
+ end
40
+
41
+ def remove_preference(name)
42
+ remove_method preference_getter_method(name) if method_defined? preference_getter_method(name)
43
+ remove_method preference_setter_method(name) if method_defined? preference_setter_method(name)
44
+ remove_method preference_default_getter_method(name) if method_defined? preference_default_getter_method(name)
45
+ remove_method preference_type_getter_method(name) if method_defined? preference_type_getter_method(name)
46
+ remove_method preference_description_getter_method(name) if method_defined? preference_description_getter_method(name)
47
+ end
48
+
49
+ def preference_getter_method(name)
50
+ "preferred_#{name}".to_sym
51
+ end
52
+
53
+ def preference_setter_method(name)
54
+ "preferred_#{name}=".to_sym
55
+ end
56
+
57
+ def preference_default_getter_method(name)
58
+ "preferred_#{name}_default".to_sym
59
+ end
60
+
61
+ def preference_type_getter_method(name)
62
+ "preferred_#{name}_type".to_sym
63
+ end
64
+
65
+ def preference_description_getter_method(name)
66
+ "preferred_#{name}_description".to_sym
67
+ end
68
+
69
+ end
@@ -0,0 +1,4 @@
1
+ module Preferred
2
+ class Railtie < ::Rails::Railtie
3
+ end
4
+ end
@@ -0,0 +1,3 @@
1
+ module Preferred
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :preferred do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,96 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: preferred
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Nicholas W. Watson
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-03-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">"
18
+ - !ruby/object:Gem::Version
19
+ version: '4.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">"
25
+ - !ruby/object:Gem::Version
26
+ version: '4.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: pg
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.18.1
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.18.1
41
+ - !ruby/object:Gem::Dependency
42
+ name: sqlite3
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: Preferred allows you to define preferences on a model and stores them
56
+ in a jsonb column in PostgreSQL
57
+ email:
58
+ - nicholas.w.watson@me.com
59
+ executables: []
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - MIT-LICENSE
64
+ - README.md
65
+ - Rakefile
66
+ - lib/preferred.rb
67
+ - lib/preferred/preferable.rb
68
+ - lib/preferred/preferable_class_methods.rb
69
+ - lib/preferred/railtie.rb
70
+ - lib/preferred/version.rb
71
+ - lib/tasks/preferred_tasks.rake
72
+ homepage: https://github.com/nwwatson/preferred
73
+ licenses:
74
+ - MIT
75
+ metadata: {}
76
+ post_install_message:
77
+ rdoc_options: []
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ requirements: []
91
+ rubyforge_project:
92
+ rubygems_version: 2.5.2
93
+ signing_key:
94
+ specification_version: 4
95
+ summary: Preferences on your Rails models stored in a JSONB column in PostgreSQL
96
+ test_files: []