acts_as_preferenced 0.9.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/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in ..gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 TODO: Write your name
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 ADDED
@@ -0,0 +1,75 @@
1
+ ActsAsPreferenced
2
+ ===========
3
+
4
+ ActsAsPreferenced helps with handling of some settings you might want to store
5
+ per-object (usually per-user) in Rails applications. It provides unified API to
6
+ access those, ways to handle default values and some useful view helpers.
7
+ Preferences may be divided into sections for easier categorization if many are
8
+ present.
9
+
10
+ Preferences can be stored in one of pluggable stores. Currently two stores are
11
+ implemented: Field (stores in serialized db column) and Association (stores in
12
+ associated table). One of the aims of this gem was to provide smooth transition
13
+ between different stores - API stays the same for all of them, so you may start
14
+ with preferences being stored in a serialized field and then transition to
15
+ associated table.
16
+
17
+ Example
18
+ =======
19
+
20
+ # Association store - use whatever association you like, there are just 2
21
+ # requirements:
22
+ # * associated table needs to have field for every preference (type matching)
23
+ # * the name of the association cannot be "preferences", as it is used
24
+ # internally by ActsAsPreferenced
25
+
26
+ class User
27
+ attr_accessor :user_preferences
28
+
29
+ acts_as_preferenced( :association => :user_preferences ) do |config|
30
+
31
+ # Just an integer preference with allowed range
32
+ config.preference :items_per_page, :section => :general, :choices => (1..100), :default => 20
33
+ # Define the whole section of preferences. :prefix => true means
34
+ # preference names will start with section name, so :flowers will become
35
+ # "likes_flowers?" method ("?" added because it's boolean)
36
+ config.section :likes, :prefix => true do |section|
37
+ section.preference :flowers, :default => true
38
+ # No default - if not set will be nil
39
+ section.preference :animals
40
+ end
41
+ # Enumerated preference with no section (it belongs to nil section)
42
+ config.preference :likes_people, :choices => [:no, :little, :yes]
43
+ end
44
+
45
+ end
46
+
47
+ OR
48
+
49
+ # Field store
50
+
51
+ class User
52
+ acts_as_preferenced( :field => :prefs, ...
53
+ end
54
+
55
+
56
+ # Usage
57
+
58
+ user = User.new
59
+ user.likes_flowers? # True - default; as preference is boolean question mark is appended to getter
60
+ user.likes_flowers = false
61
+ user.likes_flowers? # False
62
+ user.likes_animals? # Nil - no default present
63
+ user.items_per_page = 120 # ArgumentError - value out of range
64
+ user.likes_people = :yes
65
+ user.likes_people # :yes - name might be misleading, but it's not boolean, so no question mark here
66
+
67
+ TODO
68
+ ====
69
+
70
+ Helpers
71
+ API documentation
72
+ Migration generator for Association store.
73
+ I18n tests.
74
+
75
+ Copyright (c) 2009-2013 Marek Janukowicz, released under the MIT license
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,72 @@
1
+ require 'acts_as_preferenced/version'
2
+ require 'acts_as_preferenced/store/base'
3
+ require 'acts_as_preferenced/store/association'
4
+ require 'acts_as_preferenced/store/field'
5
+ require 'acts_as_preferenced/preference'
6
+ require 'acts_as_preferenced/section'
7
+
8
+ module ActsAsPreferenced
9
+
10
+ def self.included( klass )
11
+ klass.extend( ActMethods )
12
+ end
13
+
14
+ module ActMethods
15
+
16
+ def acts_as_preferenced( options = {} )
17
+ options.assert_valid_keys( :field, :association, :translation_scope )
18
+ class_attribute :preference_config
19
+ include InstanceMethods
20
+ extend ClassMethods
21
+ if options[:field]
22
+ field = options[:field]
23
+ self.module_eval { serialize field, Hash } # TODO: move this line into config initialization
24
+ config = ActsAsPreferenced::Store::Field.new( self, field, options[:translation_scope] )
25
+ self.preference_config = config
26
+ yield config
27
+ elsif options[:association]
28
+ config = ActsAsPreferenced::Store::Association.new( self, options[:association], options[:translation_scope] )
29
+ self.preference_config = config
30
+ yield config
31
+ else
32
+ raise ArgumentError, "Invalid options for acts_as_preferenced: #{options.inspect}"
33
+ end
34
+ end
35
+
36
+ end
37
+
38
+ module ClassMethods
39
+
40
+ # TODO: Those methods should only be available when preferences are actually defined
41
+ def preference_sections
42
+ preference_config.sections.keys
43
+ end
44
+
45
+ def preferences_for_section( section )
46
+ preference_config.sections[section]
47
+ end
48
+
49
+ def all_preferences
50
+ preference_config.all_preferences
51
+ end
52
+
53
+ end
54
+
55
+ module InstanceMethods
56
+
57
+ def preference_value( name )
58
+ # TODO: implement
59
+ end
60
+
61
+ #def preferences
62
+ # Preferences.configs[self.class].all
63
+ #end
64
+
65
+ #def preferences= (prefs)
66
+ # Preferences.configs[self.class].all = prefs
67
+ #end
68
+ end
69
+
70
+ end
71
+
72
+ ActiveRecord::Base.send( :include, ActsAsPreferenced )
@@ -0,0 +1,48 @@
1
+ module ActsAsPreferenced
2
+ class Preference
3
+
4
+ attr_reader :name, :default, :section
5
+
6
+ def initialize( store, name, options = {} )
7
+ options.assert_valid_keys( :section, :label, :choices, :default )
8
+ @store, @name = store, name
9
+ @section = options[:section]
10
+ @label = options[:label]
11
+ @choices = options[:choices]
12
+ @default = options[:default]
13
+ store.sections[@section] << self
14
+ store.all_preferences << self
15
+ end
16
+
17
+ def label
18
+ if @store.translation_scope && @label.nil?
19
+ I18n.t( @name, :scope => [@store.translation_scope, @section] )
20
+ else
21
+ @label
22
+ end
23
+ end
24
+
25
+ # Options translations are stored under hardcoded :choices key in Preferences
26
+ # translation_scope. TODO: make it not hardcoded and make it work for other
27
+ # options than Array (eg. Range?)
28
+ # TODO: it should be cached
29
+ def choices
30
+ if @choices.is_a?( Array )
31
+ # TODO: I don't quite understand checking for an array here
32
+ @choices.collect { |choice| choice.is_a?( Array ) ? choice : [I18n.t( choice, :scope => [@store.translation_scope, :choices] ), opt] }
33
+ else
34
+ @choices
35
+ end
36
+ end
37
+
38
+ def value_valid?( value )
39
+ value = value.to_sym if value.is_a?( String )
40
+ if @choices
41
+ return @choices.include?( value )
42
+ else
43
+ return [true, false].include?( value )
44
+ end
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,23 @@
1
+ module ActsAsPreferenced
2
+
3
+ # This class only helps with defining of preference sections, not with storage
4
+ # (as I see no reason to make storage more complicated while bringing no real
5
+ # benefit)
6
+ class Section
7
+
8
+ # Options:
9
+ # * prefix - if true, section name will be prepended to all preferences
10
+ # defined within. False by default
11
+ def initialize( store, name, options = {} )
12
+ options.assert_valid_keys( :prefix )
13
+ @store, @name = store, name
14
+ @prefix = options[:prefix]
15
+ end
16
+
17
+ def preference( name, options = {} )
18
+ pref_name = (@prefix ? "#{@name}_#{name}".to_sym : name)
19
+ @store.preference( pref_name, options.merge( :section => @name ))
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,66 @@
1
+ module ActsAsPreferenced
2
+ module Store
3
+
4
+ class Association < Base
5
+
6
+ attr_reader :association
7
+
8
+ def initialize(klass, assoc, translation_scope = nil)
9
+ super( klass, translation_scope )
10
+ @association = assoc
11
+ @klass.send( :define_method, "preferences" ) do
12
+ prefs = send( preference_config.association ) || send( "build_#{preference_config.association}" )
13
+ return prefs
14
+ end
15
+ @klass.send( :define_method, "preferences=" ) do |new_prefs|
16
+ pref_object = send( preference_config.association ) || send( "build_#{preference_config.association}" )
17
+ self.class.all_preferences.each do |pref|
18
+ old_value = pref_object.send( pref.name )
19
+ new_value = new_prefs[pref.name]
20
+ if new_value
21
+ stringified_value = new_value.is_a?( Symbol ) ? new_value.to_s : new_value
22
+ new_prefs[pref.name] = stringified_value
23
+ else
24
+ # Hack to allow boolean preferences to be set to false. This looks
25
+ # wrong from model point of view (if you mass assign preferences,
26
+ # absent boolean ones will be set to false even though default is
27
+ # true), but it works well for forms.
28
+ # TODO: find a way to make it work properly both for defaults and
29
+ # forms (if at all possible)
30
+ if pref.default == true || old_value == true
31
+ new_prefs[pref.name] = false
32
+ end
33
+ end
34
+ end
35
+ pref_object.attributes = new_prefs
36
+ end
37
+
38
+ @klass.send( :define_method, "save_preferences" ) do
39
+ pref_object = send( preference_config.association )
40
+ pref_object.save! if pref_object
41
+ end
42
+ @klass.before_save :save_preferences
43
+ end
44
+
45
+ def preference( name, options = {} )
46
+ options.assert_valid_keys( :section, :label, :choices, :default )
47
+ pref = Preference.new( self, name, options )
48
+ method_name = options[:choices] ? name.to_s : "#{name}?"
49
+ @klass.send( :define_method, method_name ) do
50
+ value = preferences[name]
51
+ value = pref.default if value.nil?
52
+ value &&= value.to_sym if value.is_a?( String )
53
+ value
54
+ end
55
+ @klass.send( :define_method, "#{name}=" ) do |value|
56
+ if pref.value_valid?( value )
57
+ preferences[name] = (value.is_a?( Symbol ) ? value.to_s : value)
58
+ else
59
+ raise ArgumentError, "Value #{value} invalid for preference #{pref.name}"
60
+ end
61
+ end
62
+ end
63
+
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,23 @@
1
+ module ActsAsPreferenced
2
+ module Store
3
+
4
+ # Base class for all stores for preferences
5
+ class Base
6
+
7
+ attr_reader :sections, :all_preferences, :translation_scope
8
+
9
+ def initialize( klass, translation_scope = nil )
10
+ @klass = klass
11
+ @translation_scope = translation_scope
12
+ @sections = Hash.new { |h,k| h[k] = [] }
13
+ @all_preferences = []
14
+ end
15
+
16
+ def section( name, options = {} )
17
+ section = Section.new( self, name, options )
18
+ yield section
19
+ end
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,61 @@
1
+ module ActsAsPreferenced
2
+ module Store
3
+
4
+ # This store holds preferences in a serialized field
5
+ class Field < Base
6
+
7
+ def initialize( klass, field, translation_scope = nil )
8
+ super( klass, translation_scope )
9
+ @field = field
10
+ @klass.send( :define_method, "preferences" ) do
11
+ prefs = read_attribute(field)
12
+ unless prefs
13
+ prefs = HashWithIndifferentAccess.new
14
+ write_attribute(field, prefs)
15
+ end
16
+ return prefs
17
+ end
18
+
19
+ @klass.send( :define_method, "preferences=" ) do |new_prefs|
20
+ self.class.all_preferences.each do |pref|
21
+ # Hack to allow boolean preferences to be set to false. This looks
22
+ # wrong from model point of view (if you mass assign preferences,
23
+ # absent boolean ones will be set to false even though default is
24
+ # true), but it works well for forms.
25
+ # TODO: find a way to make it work properly both for defaults and
26
+ # forms (if at all possible)
27
+ new_prefs[pref.name] ||= false if pref.default == true
28
+ end
29
+ write_attribute(field, new_prefs)
30
+ end
31
+ end
32
+
33
+ def preference( name, options = {} )
34
+ options.assert_valid_keys( :section, :label, :choices, :default )
35
+ pref = Preference.new( self, name, options )
36
+ if options[:choices] # Choice
37
+ @klass.send( :define_method, "#{name}" ) do
38
+ # This symbolizes strings and leave other values (eg. numbers)
39
+ # intact
40
+ value = preferences[name].is_a?( String ) ? preferences[name].to_sym : preferences[name]
41
+ value || pref.default
42
+ end
43
+ else # Boolean
44
+ @klass.send( :define_method, "#{name}?" ) do
45
+ # We check for nil to allow "false" here
46
+ preferences[name].nil? ? pref.default : preferences[name]
47
+ end
48
+ end
49
+ @klass.send( :define_method, "#{name}=" ) do |value|
50
+ if pref.value_valid?( value )
51
+ preferences[name] = value
52
+ else
53
+ raise ArgumentError, "Value #{value} invalid for preference #{pref.name}"
54
+ end
55
+ end
56
+
57
+ end
58
+
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,3 @@
1
+ module ActsAsPreferenced
2
+ VERSION = "0.9.0"
3
+ end
@@ -0,0 +1,253 @@
1
+ require 'test_helper'
2
+
3
+ class ActsAsPreferencedFieldTest < ActiveSupport::TestCase
4
+
5
+ class User < FakeModel
6
+
7
+ attr_accessor :hold_preferences_here
8
+
9
+ acts_as_preferenced( :field => :hold_preferences_here ) do |config|
10
+ config.preference :items_per_page, :section => :general, :choices => (1..100), :default => 20
11
+ config.section :likes, :prefix => true do |section|
12
+ section.preference :flowers, :default => true
13
+ section.preference :animals
14
+ end
15
+ config.preference :likes_people, :choices => [:no, :little, :yes]
16
+ end
17
+ end
18
+
19
+ def setup
20
+ @user = User.new
21
+ end
22
+
23
+ test "all preferences" do
24
+ all = User.all_preferences
25
+ assert_equal [:items_per_page, :likes_flowers, :likes_animals, :likes_people], all.collect(&:name)
26
+ end
27
+
28
+ test "preference sections" do
29
+ assert_equal [:general, nil, :likes], User.preference_sections
30
+ prefs = User.preferences_for_section( :sdjkfajsdf )
31
+ assert prefs.empty?
32
+ prefs = User.preferences_for_section( :likes )
33
+ assert_equal [:likes_flowers, :likes_animals], prefs.collect(&:name)
34
+ prefs = User.preferences_for_section( nil )
35
+ assert_equal [:likes_people], prefs.collect(&:name)
36
+ end
37
+
38
+ test "defaults" do
39
+ assert_equal true, @user.likes_flowers?
40
+ assert_equal 20, @user.items_per_page
41
+ assert_nil @user.likes_animals?
42
+ assert_nil @user.likes_people
43
+ end
44
+
45
+ test "set boolean" do
46
+ @user.likes_flowers = false
47
+ assert_equal false, @user.likes_flowers?
48
+ end
49
+
50
+ test "set integer" do
51
+ @user.items_per_page = 11
52
+ assert_equal 11, @user.items_per_page
53
+ end
54
+
55
+ test "set enumerable" do
56
+ @user.likes_people = :little
57
+ assert_equal :little, @user.likes_people
58
+ end
59
+
60
+ test "set integer as boolean" do
61
+ assert_raises( ArgumentError ) do
62
+ @user.items_per_page = true
63
+ end
64
+ end
65
+
66
+ test "set integer out of range" do
67
+ assert_raises( ArgumentError ) do
68
+ @user.items_per_page = 0
69
+ end
70
+ assert_raises( ArgumentError ) do
71
+ @user.items_per_page = 101
72
+ end
73
+ end
74
+
75
+ test "set boolean as integer" do
76
+ assert_raises( ArgumentError ) do
77
+ @user.likes_flowers = 10
78
+ end
79
+ end
80
+
81
+ test "set enumerable out of range" do
82
+ assert_raises( ArgumentError ) do
83
+ @user.likes_people = :lot
84
+ end
85
+ end
86
+
87
+ test "set enumerable as string" do
88
+ @user.likes_people = "yes"
89
+ assert_equal :yes, @user.likes_people
90
+ end
91
+
92
+ test "set batch preferences" do
93
+ @user.likes_flowers = true
94
+ @user.likes_animals = true
95
+ @user.preferences = { :items_per_page => 23 }
96
+ assert_equal 23, @user.items_per_page
97
+ # No value for boolean defaulting to true - we assume it was unset
98
+ # TODO: in fact Rails handle this by sending hidden field with the same
99
+ # name, use the same approach
100
+ assert_equal false, @user.likes_flowers?
101
+ # No value for this boolean without default - reset it
102
+ # TODO: this also doesn't seem correct
103
+ assert_nil @user.likes_animals?
104
+ end
105
+ end
106
+
107
+ class ActsAsPreferencedAssociationTest < ActiveSupport::TestCase
108
+
109
+ class UserPreference < FakeModel
110
+
111
+ # Tons of fakes here
112
+ attr_accessor :attributes
113
+
114
+ def items_per_page
115
+ attributes[:items_per_page]
116
+ end
117
+
118
+ def items_per_page= (value)
119
+ attributes[:items_per_page] = value
120
+ end
121
+
122
+ def likes_flowers?
123
+ attributes[:likes_flowers]
124
+ end
125
+
126
+ def likes_flowers= (value)
127
+ attributes[:likes_flowers] = value
128
+ end
129
+
130
+ def likes_animals?
131
+ attributes[:likes_animals]
132
+ end
133
+
134
+ def likes_animals= (value)
135
+ attributes[:likes_animals] = value
136
+ end
137
+
138
+ def likes_people?
139
+ attributes[:likes_people]
140
+ end
141
+
142
+ def likes_people= (value)
143
+ attributes[:likes_people] = value
144
+ end
145
+
146
+ alias_method :likes_flowers, :likes_flowers?
147
+ alias_method :likes_animals, :likes_animals?
148
+ alias_method :likes_people, :likes_people?
149
+ delegate :[], :[]=, :to => :attributes
150
+ end
151
+
152
+ class User < FakeModel
153
+
154
+ attr_accessor :user_preferences
155
+
156
+ acts_as_preferenced( :association => :user_preferences ) do |config|
157
+ config.preference :items_per_page, :section => :general, :choices => (1..100), :default => 20
158
+ config.section :likes, :prefix => true do |section|
159
+ section.preference :flowers, :default => true
160
+ section.preference :animals
161
+ end
162
+ config.preference :likes_people, :choices => [:no, :little, :yes]
163
+ end
164
+ end
165
+
166
+ def setup
167
+ @user = User.new
168
+ @user.user_preferences = UserPreference.new
169
+ end
170
+
171
+ test "all preferences" do
172
+ all = User.all_preferences
173
+ assert_equal [:items_per_page, :likes_flowers, :likes_animals, :likes_people], all.collect(&:name)
174
+ end
175
+
176
+ test "preference sections" do
177
+ assert_equal [:general, nil, :likes], User.preference_sections
178
+ prefs = User.preferences_for_section( :sdjkfajsdf )
179
+ assert prefs.empty?
180
+ prefs = User.preferences_for_section( :likes )
181
+ assert_equal [:likes_flowers, :likes_animals], prefs.collect(&:name)
182
+ prefs = User.preferences_for_section( nil )
183
+ assert_equal [:likes_people], prefs.collect(&:name)
184
+ end
185
+
186
+ test "defaults" do
187
+ assert_equal true, @user.likes_flowers?
188
+ assert_equal 20, @user.items_per_page
189
+ assert_nil @user.likes_animals?
190
+ assert_nil @user.likes_people
191
+ end
192
+
193
+ test "set boolean" do
194
+ @user.likes_flowers = false
195
+ assert_equal false, @user.likes_flowers?
196
+ end
197
+
198
+ test "set integer" do
199
+ @user.items_per_page = 11
200
+ assert_equal 11, @user.items_per_page
201
+ end
202
+
203
+ test "set enumerable" do
204
+ @user.likes_people = :little
205
+ assert_equal :little, @user.likes_people
206
+ end
207
+
208
+ test "set integer as boolean" do
209
+ assert_raises( ArgumentError ) do
210
+ @user.items_per_page = true
211
+ end
212
+ end
213
+
214
+ test "set integer out of range" do
215
+ assert_raises( ArgumentError ) do
216
+ @user.items_per_page = 0
217
+ end
218
+ assert_raises( ArgumentError ) do
219
+ @user.items_per_page = 101
220
+ end
221
+ end
222
+
223
+ test "set boolean as integer" do
224
+ assert_raises( ArgumentError ) do
225
+ @user.likes_flowers = 10
226
+ end
227
+ end
228
+
229
+ test "set enumerable out of range" do
230
+ assert_raises( ArgumentError ) do
231
+ @user.likes_people = :lot
232
+ end
233
+ end
234
+
235
+ test "set enumerable as string" do
236
+ @user.likes_people = "yes"
237
+ assert_equal :yes, @user.likes_people
238
+ end
239
+
240
+ test "set batch preferences" do
241
+ @user.likes_flowers = true
242
+ @user.likes_animals = false
243
+ @user.preferences = { :items_per_page => 23 }
244
+ assert_equal 23, @user.items_per_page
245
+ # No value for boolean defaulting to true - we assume it was unset
246
+ # TODO: in fact Rails handle this by sending hidden field with the same
247
+ # name, use the same approach
248
+ assert_equal false, @user.likes_flowers?
249
+ # No value for this boolean without default - reset it
250
+ # TODO: this also doesn't seem correct
251
+ assert_nil @user.likes_animals?
252
+ end
253
+ end
@@ -0,0 +1,29 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'set'
4
+ gem 'activesupport', "> 3.0.0"
5
+ require 'active_support/test_case'
6
+ require 'active_record'
7
+ require 'active_record/base'
8
+ require 'acts_as_preferenced'
9
+ require 'acts_as_preferenced/preference'
10
+ require 'acts_as_preferenced/section'
11
+ require 'acts_as_preferenced/store/base'
12
+ require 'acts_as_preferenced/store/association'
13
+ require 'acts_as_preferenced/store/field'
14
+
15
+ # Class faking AR model behavior - needed to test the validations without the database
16
+ class FakeModel < ActiveRecord::Base
17
+
18
+ self.abstract_class = true
19
+
20
+ def self.columns
21
+ @columns ||= [];
22
+ end
23
+
24
+ def self.column(name, sql_type = nil, default = nil, null = true)
25
+ columns << ActiveRecord::ConnectionAdapters::Column.new(name.to_s, default, sql_type.to_s, null)
26
+ end
27
+
28
+ end
29
+
metadata ADDED
@@ -0,0 +1,60 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: acts_as_preferenced
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Marek Janukowicz
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-01-07 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Preferences for Rails
15
+ email:
16
+ - marek@janukowicz.net
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - lib/acts_as_preferenced.rb
22
+ - lib/acts_as_preferenced/version.rb
23
+ - lib/acts_as_preferenced/section.rb
24
+ - lib/acts_as_preferenced/store/field.rb
25
+ - lib/acts_as_preferenced/store/association.rb
26
+ - lib/acts_as_preferenced/store/base.rb
27
+ - lib/acts_as_preferenced/preference.rb
28
+ - Gemfile
29
+ - LICENSE.txt
30
+ - Rakefile
31
+ - README
32
+ - test/acts_as_preferences_test.rb
33
+ - test/test_helper.rb
34
+ homepage: ''
35
+ licenses: []
36
+ post_install_message:
37
+ rdoc_options: []
38
+ require_paths:
39
+ - lib
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ required_rubygems_version: !ruby/object:Gem::Requirement
47
+ none: false
48
+ requirements:
49
+ - - ! '>='
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ requirements: []
53
+ rubyforge_project:
54
+ rubygems_version: 1.8.24
55
+ signing_key:
56
+ specification_version: 3
57
+ summary: ''
58
+ test_files:
59
+ - test/acts_as_preferences_test.rb
60
+ - test/test_helper.rb