preferencias 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.
- checksums.yaml +15 -0
- data/.gitignore +23 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +47 -0
- data/Rakefile +6 -0
- data/lib/generators/preferences/migration_generator.rb +22 -0
- data/lib/generators/preferences/templates/create_preferences.rb +10 -0
- data/lib/preferences/preferences/preferable_class_methods.rb +51 -0
- data/lib/preferencias.rb +7 -0
- data/lib/preferencias/base.rb +14 -0
- data/lib/preferencias/engine.rb +17 -0
- data/lib/preferencias/preference.rb +6 -0
- data/lib/preferencias/preferences/configuration.rb +71 -0
- data/lib/preferencias/preferences/preferable.rb +116 -0
- data/lib/preferencias/preferences/preferable_class_methods.rb +51 -0
- data/lib/preferencias/preferences/scoped_store.rb +33 -0
- data/lib/preferencias/preferences/store.rb +98 -0
- data/lib/preferencias/version.rb +3 -0
- data/log/development.log +0 -0
- data/preferences.gemspec +29 -0
- data/spec/preference_spec.rb +81 -0
- data/spec/preferencias/configuration_spec.rb +27 -0
- data/spec/preferencias/preferable_spec.rb +275 -0
- data/spec/preferencias/scoped_store_spec.rb +58 -0
- data/spec/preferencias/store_spec.rb +46 -0
- data/spec/spec_helper.rb +24 -0
- data/spec/support/schema.rb +11 -0
- data/spree_license.md +13 -0
- metadata +198 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
ZmQyMjVhN2RkOTExNzIyYmE2OGI4YmM4MWI2N2E4Yjg3Yzc1MmJkOQ==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
MzcyMjBiNDdlYjFkZmNmODA0MThmODc3OWRkYzkzMDM4OTc0ODFhMg==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
Mzk4YTkyNTVkYzBkYzcwZTZhYTU5Y2M3ODI2MWQxMjJmNTc3NGFhZTAwZDJk
|
10
|
+
MWJmZjJkMDQ1MzY3ZWMyZTA0ZTBjZjljMTgxMTY3OGQ3ZjZhZDVmNWU0M2Jh
|
11
|
+
YTk5ODllNDY0MGI0ZjY2YWI5ZDUxMGMyYTdiZDkwOGEyZDRkZmY=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
MTNjNzhkOTQ0YTA1YWRjMDMxZGExY2E3NTJjMTlmMTQ0MTY0NzQ5OWNmZjE5
|
14
|
+
MGVlOWNlYWJkZDBiYjJlNmU5ZWE4NjgzOTk0MTViOWE0ZDUyZGI0OWI2N2Jl
|
15
|
+
OWQ0NjNhYTc3OGJjYWUxNDQ4OWEzNzU4YjA1MmI2NTQzN2FhOTc=
|
data/.gitignore
ADDED
@@ -0,0 +1,23 @@
|
|
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
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
23
|
+
.DS_Store
|
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 David Silva
|
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,47 @@
|
|
1
|
+
# PreferĂȘncias
|
2
|
+
|
3
|
+
[](https://travis-ci.org/davidslv/preferences)
|
4
|
+
|
5
|
+
This gem is an extraction of the [Spree Ecommerce](https://github.com/spree/spree) Open Source Software.
|
6
|
+
|
7
|
+
I couldn't find anything as robust as their solution so I decided to extract it into a gem.
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
gem 'preferencias'
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install preferencias
|
22
|
+
|
23
|
+
Run migrations
|
24
|
+
|
25
|
+
$ rails generate preferencias:migration
|
26
|
+
$ bundle exec rake db:migrate db:test:prepare
|
27
|
+
|
28
|
+
## Usage
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
class YourModel < ActiveRecord::Base
|
32
|
+
preference :color, :string, default: 'red'
|
33
|
+
preference :number_of_pokemons, :integer, default: 151
|
34
|
+
end
|
35
|
+
|
36
|
+
@model = YourModel.create(preferences: {number_of_pokemons: 649})
|
37
|
+
@model.preferred_number_of_pokemons # => 649
|
38
|
+
@model.preferred_color # => "red"
|
39
|
+
```
|
40
|
+
|
41
|
+
## Contributing
|
42
|
+
|
43
|
+
1. Fork it ( https://github.com/davidslv/preferences/fork )
|
44
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
45
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
46
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
47
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
require 'rails/generators/migration'
|
3
|
+
|
4
|
+
module Preferencias
|
5
|
+
class MigrationGenerator < ::Rails::Generators::Base
|
6
|
+
include ::Rails::Generators::Migration
|
7
|
+
source_root File.expand_path('../templates', __FILE__)
|
8
|
+
|
9
|
+
def self.next_migration_number( dirname )
|
10
|
+
next_migration_number = current_migration_number(dirname) + 1
|
11
|
+
if ActiveRecord::Base.timestamped_migrations
|
12
|
+
[Time.now.utc.strftime("%Y%m%d%H%M%S%6N"), "%.20d" % next_migration_number].max
|
13
|
+
else
|
14
|
+
"%.3d" % next_migration_number
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def create_model_file
|
19
|
+
migration_template "create_preferences.rb", "db/migrate/create_preferences.rb"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Preferencias
|
2
|
+
module PreferableClassMethods
|
3
|
+
|
4
|
+
def preference(name, type, *args)
|
5
|
+
options = args.extract_options!
|
6
|
+
options.assert_valid_keys(:default)
|
7
|
+
default = options[:default]
|
8
|
+
default = ->{ options[:default] } unless default.is_a?(Proc)
|
9
|
+
|
10
|
+
# cache_key will be nil for new objects, then if we check if there
|
11
|
+
# is a pending preference before going to default
|
12
|
+
define_method preference_getter_method(name) do
|
13
|
+
preferences.fetch(name) do
|
14
|
+
default.call
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
define_method preference_setter_method(name) do |value|
|
19
|
+
value = convert_preference_value(value, type)
|
20
|
+
preferences[name] = value
|
21
|
+
|
22
|
+
# If this is an activerecord object, we need to inform
|
23
|
+
# ActiveRecord::Dirty that this value has changed, since this is an
|
24
|
+
# in-place update to the preferences hash.
|
25
|
+
preferences_will_change! if respond_to?(:preferences_will_change!)
|
26
|
+
end
|
27
|
+
|
28
|
+
define_method preference_default_getter_method(name), &default
|
29
|
+
|
30
|
+
define_method preference_type_getter_method(name) do
|
31
|
+
type
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def preference_getter_method(name)
|
36
|
+
"preferred_#{name}".to_sym
|
37
|
+
end
|
38
|
+
|
39
|
+
def preference_setter_method(name)
|
40
|
+
"preferred_#{name}=".to_sym
|
41
|
+
end
|
42
|
+
|
43
|
+
def preference_default_getter_method(name)
|
44
|
+
"preferred_#{name}_default".to_sym
|
45
|
+
end
|
46
|
+
|
47
|
+
def preference_type_getter_method(name)
|
48
|
+
"preferred_#{name}_type".to_sym
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/preferencias.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
3
|
+
module Preferencias
|
4
|
+
class Base < ActiveRecord::Base
|
5
|
+
include Preferencias::Preferable
|
6
|
+
|
7
|
+
serialize :preferences, Hash
|
8
|
+
after_initialize do
|
9
|
+
self.preferences = default_preferences.merge(preferences) if has_attribute?(:preferences)
|
10
|
+
end
|
11
|
+
|
12
|
+
self.abstract_class = true
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'preferencias/preferences/preferable_class_methods'
|
2
|
+
require 'preferencias/preferences/preferable'
|
3
|
+
require 'preferencias/base'
|
4
|
+
require 'preferencias/preferences/configuration'
|
5
|
+
require 'preferencias/preferences/scoped_store'
|
6
|
+
require 'preferencias/preferences/store'
|
7
|
+
require 'preferencias/preference.rb'
|
8
|
+
|
9
|
+
require 'rails'
|
10
|
+
|
11
|
+
module Preferencias
|
12
|
+
class Engine < ::Rails::Engine
|
13
|
+
initializer "preferences" do
|
14
|
+
::ActiveRecord::Base.send :include, Preferencias::Preferable
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# This takes the preferrable methods and adds some
|
2
|
+
# syntatic sugar to access the preferences
|
3
|
+
#
|
4
|
+
# class App < Configuration
|
5
|
+
# preference :color, :string
|
6
|
+
# end
|
7
|
+
#
|
8
|
+
# a = App.new
|
9
|
+
#
|
10
|
+
# setters:
|
11
|
+
# a.color = :blue
|
12
|
+
# a[:color] = :blue
|
13
|
+
# a.set :color = :blue
|
14
|
+
# a.preferred_color = :blue
|
15
|
+
#
|
16
|
+
# getters:
|
17
|
+
# a.color
|
18
|
+
# a[:color]
|
19
|
+
# a.get :color
|
20
|
+
# a.preferred_color
|
21
|
+
#
|
22
|
+
#
|
23
|
+
module Preferencias
|
24
|
+
class Configuration
|
25
|
+
include Preferencias::Preferable
|
26
|
+
|
27
|
+
def configure
|
28
|
+
yield(self) if block_given?
|
29
|
+
end
|
30
|
+
|
31
|
+
def preferences
|
32
|
+
ScopedStore.new(self.class.name.underscore)
|
33
|
+
end
|
34
|
+
|
35
|
+
def reset
|
36
|
+
preferences.each do |name, value|
|
37
|
+
set_preference name, preference_default(name)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
alias :[] :get_preference
|
42
|
+
alias :[]= :set_preference
|
43
|
+
|
44
|
+
alias :get :get_preference
|
45
|
+
|
46
|
+
def set(*args)
|
47
|
+
options = args.extract_options!
|
48
|
+
options.each do |name, value|
|
49
|
+
set_preference name, value
|
50
|
+
end
|
51
|
+
|
52
|
+
if args.size == 2
|
53
|
+
set_preference args[0], args[1]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def method_missing(method, *args)
|
58
|
+
name = method.to_s.gsub('=', '')
|
59
|
+
if has_preference? name
|
60
|
+
if method.to_s =~ /=$/
|
61
|
+
set_preference(name, args.first)
|
62
|
+
else
|
63
|
+
get_preference name
|
64
|
+
end
|
65
|
+
else
|
66
|
+
super
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
# Preferable allows defining preference accessor methods.
|
2
|
+
#
|
3
|
+
# A class including Preferable must implement #preferences which should return
|
4
|
+
# an object responding to .fetch(key), []=(key, val), and .delete(key).
|
5
|
+
#
|
6
|
+
# The generated writer method performs typecasting before assignment into the
|
7
|
+
# preferences object.
|
8
|
+
#
|
9
|
+
# Examples:
|
10
|
+
#
|
11
|
+
# # Base includes Preferable and defines preferences as a serialized
|
12
|
+
# # column.
|
13
|
+
# class Settings < Base
|
14
|
+
# preference :color, :string, default: 'red'
|
15
|
+
# preference :temperature, :integer, default: 21
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# s = Settings.new
|
19
|
+
# s.preferred_color # => 'red'
|
20
|
+
# s.preferred_temperature # => 21
|
21
|
+
#
|
22
|
+
# s.preferred_color = 'blue'
|
23
|
+
# s.preferred_color # => 'blue'
|
24
|
+
#
|
25
|
+
# # Typecasting is performed on assignment
|
26
|
+
# s.preferred_temperature = '24'
|
27
|
+
# s.preferred_color # => 24
|
28
|
+
#
|
29
|
+
# # Modifications have been made to the .preferences hash
|
30
|
+
# s.preferences #=> {color: 'blue', temperature: 24}
|
31
|
+
#
|
32
|
+
# # Save the changes. All handled by activerecord
|
33
|
+
# s.save!
|
34
|
+
|
35
|
+
require 'active_support'
|
36
|
+
|
37
|
+
module Preferencias::Preferable
|
38
|
+
extend ActiveSupport::Concern
|
39
|
+
|
40
|
+
included do
|
41
|
+
extend Preferencias::PreferableClassMethods
|
42
|
+
end
|
43
|
+
|
44
|
+
def get_preference(name)
|
45
|
+
has_preference! name
|
46
|
+
send self.class.preference_getter_method(name)
|
47
|
+
end
|
48
|
+
|
49
|
+
def set_preference(name, value)
|
50
|
+
has_preference! name
|
51
|
+
send self.class.preference_setter_method(name), value
|
52
|
+
end
|
53
|
+
|
54
|
+
def preference_type(name)
|
55
|
+
has_preference! name
|
56
|
+
send self.class.preference_type_getter_method(name)
|
57
|
+
end
|
58
|
+
|
59
|
+
def preference_default(name)
|
60
|
+
has_preference! name
|
61
|
+
send self.class.preference_default_getter_method(name)
|
62
|
+
end
|
63
|
+
|
64
|
+
def has_preference!(name)
|
65
|
+
raise NoMethodError.new "#{name} preference not defined" unless has_preference? name
|
66
|
+
end
|
67
|
+
|
68
|
+
def has_preference?(name)
|
69
|
+
respond_to? self.class.preference_getter_method(name)
|
70
|
+
end
|
71
|
+
|
72
|
+
def defined_preferences
|
73
|
+
methods.grep(/\Apreferred_.*=\Z/).map do |pref_method|
|
74
|
+
pref_method.to_s.gsub(/\Apreferred_|=\Z/, '').to_sym
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def default_preferences
|
79
|
+
Hash[
|
80
|
+
defined_preferences.map do |preference|
|
81
|
+
[preference, preference_default(preference)]
|
82
|
+
end
|
83
|
+
]
|
84
|
+
end
|
85
|
+
|
86
|
+
def clear_preferences
|
87
|
+
preferences.keys.each {|pref| preferences.delete pref}
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
def convert_preference_value(value, type)
|
93
|
+
case type
|
94
|
+
when :string, :text
|
95
|
+
value.to_s
|
96
|
+
when :password
|
97
|
+
value.to_s
|
98
|
+
when :decimal
|
99
|
+
BigDecimal.new(value.to_s)
|
100
|
+
when :integer
|
101
|
+
value.to_i
|
102
|
+
when :boolean
|
103
|
+
if value.is_a?(FalseClass) ||
|
104
|
+
value.nil? ||
|
105
|
+
value == 0 ||
|
106
|
+
value =~ /^(f|false|0)$/i ||
|
107
|
+
(value.respond_to? :empty? and value.empty?)
|
108
|
+
false
|
109
|
+
else
|
110
|
+
true
|
111
|
+
end
|
112
|
+
else
|
113
|
+
value
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|