cockpit 0.0.1.5
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/MIT-LICENSE +20 -0
- data/README.markdown +175 -0
- data/Rakefile +78 -0
- data/init.rb +1 -0
- data/lib/cockpit.rb +22 -0
- data/lib/cockpit/cockpit.rb +94 -0
- data/lib/cockpit/configuration.rb +218 -0
- data/lib/cockpit/definition.rb +55 -0
- data/lib/cockpit/extensions.rb +25 -0
- data/lib/cockpit/helper.rb +44 -0
- data/lib/cockpit/store.rb +103 -0
- data/lib/cockpit/tree_hash.rb +113 -0
- data/rails/init.rb +1 -0
- data/test/lib/database.rb +22 -0
- data/test/lib/user.rb +8 -0
- data/test/test_helper.rb +90 -0
- data/test/test_settings.rb +228 -0
- data/test/test_settings_in_database.rb +153 -0
- data/test/test_settings_on_model.rb +68 -0
- metadata +86 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Lance Pollard (lancejpollard@gmail.com)
|
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.markdown
ADDED
@@ -0,0 +1,175 @@
|
|
1
|
+
# Cockpit
|
2
|
+
|
3
|
+
<q>Super DRY Settings for Ruby, Rails, and Sinatra Apps.</q>
|
4
|
+
|
5
|
+
## Install
|
6
|
+
|
7
|
+
sudo gem install cockpit
|
8
|
+
|
9
|
+
## Usage
|
10
|
+
|
11
|
+
### Migration
|
12
|
+
|
13
|
+
create_table :settings, :force => true do |t|
|
14
|
+
t.string :key
|
15
|
+
t.string :value
|
16
|
+
t.string :cast_as
|
17
|
+
t.string :configurable_type
|
18
|
+
t.integer :configurable_id
|
19
|
+
end
|
20
|
+
|
21
|
+
### Setup (`config/initializers/settings.rb`)
|
22
|
+
|
23
|
+
Cockpit do
|
24
|
+
site do
|
25
|
+
title "Martini", :tooltip => "Set your title!"
|
26
|
+
tagline "Developer Friendly, Client Ready Blog with Rails 3"
|
27
|
+
keywords "Rails 3, Heroku, JQuery, HTML 5, Blog Engine, CSS3"
|
28
|
+
copyright "© 2010 Viatropos. All rights reserved."
|
29
|
+
timezones :value => lambda { TimeZone.first }, :options => lambda { TimeZone.all }
|
30
|
+
date_format "%m %d, %Y"
|
31
|
+
time_format "%H"
|
32
|
+
week_starts_on "Monday", :options => ["Monday", "Sunday", "Friday"]
|
33
|
+
language "en-US", :options => ["en-US", "de"]
|
34
|
+
touch_enabled true
|
35
|
+
touch_as_subdomain false
|
36
|
+
google_analytics ""
|
37
|
+
teasers :title => "Teasers" do
|
38
|
+
disable false
|
39
|
+
left 1, :title => "Left Teaser"
|
40
|
+
right 2
|
41
|
+
center 3
|
42
|
+
end
|
43
|
+
main_quote 1
|
44
|
+
end
|
45
|
+
asset :title => "Asset (and related) Settings" do
|
46
|
+
thumb do
|
47
|
+
width 100, :tip => "Thumb's width"
|
48
|
+
height 100, :tip => "Thumb's height"
|
49
|
+
end
|
50
|
+
medium do
|
51
|
+
width 600, :tip => "Thumb's width"
|
52
|
+
height 250, :tip => "Thumb's height"
|
53
|
+
end
|
54
|
+
large do
|
55
|
+
width 600, :tip => "Large's width"
|
56
|
+
height 295, :tip => "Large's height"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
authentication :title => "Authentication Settings" do
|
60
|
+
use_open_id true
|
61
|
+
use_oauth true
|
62
|
+
end
|
63
|
+
front_page do
|
64
|
+
slideshow_tag "slideshow"
|
65
|
+
slideshow_effect "fade"
|
66
|
+
end
|
67
|
+
page do
|
68
|
+
per_page 10
|
69
|
+
feed_per_page 10
|
70
|
+
end
|
71
|
+
people do
|
72
|
+
show_avatars true
|
73
|
+
default_avatar "/images/missing-person.png"
|
74
|
+
end
|
75
|
+
social do
|
76
|
+
facebook "http://facebook.com/viatropos"
|
77
|
+
twitter "http://twitter.com/viatropos"
|
78
|
+
end
|
79
|
+
s3 do
|
80
|
+
key "my_key"
|
81
|
+
secret "my_secret"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
#### Get
|
86
|
+
|
87
|
+
Settings.get("site.title").value #=> "Martini"
|
88
|
+
Settings.get("site.title.value") #=> "Martini"
|
89
|
+
Settings("site.title").value #=> "Martini"
|
90
|
+
Settings("site.title.value") #=> "Martini"
|
91
|
+
Settings["site.title"].value #=> "Martini"
|
92
|
+
Settings["site.title.value"] #=> "Martini"
|
93
|
+
Settings.site.title.value #=> "Martini" # doesn't pass through store yet
|
94
|
+
|
95
|
+
#### Set
|
96
|
+
|
97
|
+
Settings.set("site.title" => "Martini") #=> {:site => {:title => {:value => "Martini"}}}
|
98
|
+
Settings("site.title" => "Martini") #=> {:site => {:title => {:value => "Martini"}}}
|
99
|
+
Settings["site.title"] = "Martini" #=> {:site => {:title => {:value => "Martini"}}}
|
100
|
+
Settings.site.title = "Martini" #=> {:site => {:title => {:value => "Martini"}}} # doesn't pass through store yet
|
101
|
+
|
102
|
+
### Key points
|
103
|
+
|
104
|
+
- Each node is any word you want
|
105
|
+
- You can nest them arbitrarily deep
|
106
|
+
- You can use Procs
|
107
|
+
- Values are type casted
|
108
|
+
- Settings can be defined in yaml or using the DSL.
|
109
|
+
- The preferred way to _get_ values is `Settings("path.to.value").value`
|
110
|
+
- You can add custom properties to each setting:
|
111
|
+
- `Settings("site.title").tooltip #=> "Set your title!"`
|
112
|
+
- You have multiple storage options:
|
113
|
+
- `Settings.store = :db`: Syncs setting to/from ActiveRecord
|
114
|
+
- `Settings.store = :memory`: Stores everything in a Hash (memoized, super fast)
|
115
|
+
- You can specify them on a per-model basis.
|
116
|
+
|
117
|
+
Example:
|
118
|
+
|
119
|
+
class User < ActiveRecord::Base
|
120
|
+
acts_as_configurable :settings do
|
121
|
+
name "Lance", :title => "First Name", :options => ["Lance", "viatropos"]
|
122
|
+
favorite do
|
123
|
+
color "red"
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
User.new.settings #=> <#Settings @tree={
|
129
|
+
:favorite => {
|
130
|
+
:color => {:type=>:string, :value=>"red"}
|
131
|
+
},
|
132
|
+
:name => {:type=>:string, :title=>"First Name", :value=>"Lance", :options=>["Lance", "Viatropos"]}
|
133
|
+
}/>
|
134
|
+
|
135
|
+
### Why
|
136
|
+
|
137
|
+
There's no standard yet for organizing random properties in Rails apps. And settings should be able to be modified through an interface (think Admin panel).
|
138
|
+
|
139
|
+
Cockpit encapsulates the logic common to:
|
140
|
+
|
141
|
+
- Options
|
142
|
+
- Preferences
|
143
|
+
- Settings
|
144
|
+
- Configuration
|
145
|
+
- Properties and Attributes
|
146
|
+
- Key/Value stores
|
147
|
+
|
148
|
+
Sometimes you need a global store, sometimes that global store needs to be customizable by the user, sometimes each user has their own set of configurations. This handles all of those cases.
|
149
|
+
|
150
|
+
## Todo
|
151
|
+
|
152
|
+
- Settings should be sorted by the way they were constructed
|
153
|
+
- Check type, so when it is saved it knows what to do.
|
154
|
+
|
155
|
+
This ended up being very similar to i18n:
|
156
|
+
|
157
|
+
- [http://guides.rubyonrails.org/i18n.html](http://guides.rubyonrails.org/i18n.html)
|
158
|
+
- [I asked about this on the i18n lighthouse](http://i18n.lighthouseapp.com/projects/14947/tickets/21-abstract-out-configuration-functionality-from-i18n-into-separate-gem#ticket-21-1)
|
159
|
+
|
160
|
+
I think the i18n gem should be broken down into two parts: Configuration (key/value store), and Translation.
|
161
|
+
|
162
|
+
#### End Goal
|
163
|
+
|
164
|
+
- Base key-value functionality gem, which allows you to store arbitrary key values in any database (similar to moneta).
|
165
|
+
- i18n and Cockpit build on top of that
|
166
|
+
|
167
|
+
### Alternatives
|
168
|
+
|
169
|
+
- [Preferences](http://github.com/pluginaweek/preferences)
|
170
|
+
- [SettingsGoo](http://rubygems.org/gems/settings-goo)
|
171
|
+
- [RailsSettings](http://github.com/Squeegy/rails-settings)
|
172
|
+
- [SimpleConfig](http://github.com/lukeredpath/simpleconfig)
|
173
|
+
- [Configatron](http://github.com/markbates/configatron)
|
174
|
+
- [RConfig](http://github.com/rahmal/rconfig)
|
175
|
+
- [Serenity](http://github.com/progressions/serenity)
|
data/Rakefile
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require "rake/rdoctask"
|
3
|
+
require 'rake/gempackagetask'
|
4
|
+
|
5
|
+
spec = Gem::Specification.new do |s|
|
6
|
+
s.name = "cockpit"
|
7
|
+
s.authors = ["Lance Pollard"]
|
8
|
+
s.version = "0.0.1.5"
|
9
|
+
s.summary = "Cockpit: Super DRY Configuration for Ruby, Rails, and Sinatra Apps"
|
10
|
+
s.homepage = "http://github.com/viatropos/cockpit"
|
11
|
+
s.email = "lancejpollard@gmail.com"
|
12
|
+
s.description = "Super DRY Configuration for Ruby, Rails, and Sinatra Apps"
|
13
|
+
s.has_rdoc = false
|
14
|
+
s.rubyforge_project = "cockpit"
|
15
|
+
s.platform = Gem::Platform::RUBY
|
16
|
+
s.files = %w(README.markdown Rakefile init.rb MIT-LICENSE) + Dir["{lib,rails,test}/**/*"] - Dir["test/tmp"]
|
17
|
+
s.require_path = "lib"
|
18
|
+
end
|
19
|
+
|
20
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
21
|
+
pkg.gem_spec = spec
|
22
|
+
pkg.package_dir = "pkg"
|
23
|
+
end
|
24
|
+
|
25
|
+
desc 'run unit tests'
|
26
|
+
task :test do
|
27
|
+
Dir["test/**/*"].each do |file|
|
28
|
+
next unless File.basename(file) =~ /test_/
|
29
|
+
next unless File.extname(file) == ".rb"
|
30
|
+
system "ruby #{file}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
desc "Create .gemspec file (useful for github)"
|
35
|
+
task :gemspec do
|
36
|
+
File.open("pkg/#{spec.name}.gemspec", "w") do |f|
|
37
|
+
f.puts spec.to_ruby
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
desc "Build the gem into the current directory"
|
42
|
+
task :gem => :gemspec do
|
43
|
+
`gem build pkg/#{spec.name}.gemspec`
|
44
|
+
end
|
45
|
+
|
46
|
+
desc "Publish gem to rubygems"
|
47
|
+
task :publish => [:package] do
|
48
|
+
%x[gem push pkg/#{spec.name}-#{spec.version}.gem]
|
49
|
+
end
|
50
|
+
|
51
|
+
desc "Print a list of the files to be put into the gem"
|
52
|
+
task :manifest do
|
53
|
+
File.open("Manifest", "w") do |f|
|
54
|
+
spec.files.each do |file|
|
55
|
+
f.puts file
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
desc "Install the gem locally"
|
61
|
+
task :install => [:package] do
|
62
|
+
File.mkdir("pkg") unless File.exists?("pkg")
|
63
|
+
command = "gem install pkg/#{spec.name}-#{spec.version} --no-ri --no-rdoc"
|
64
|
+
command = "sudo #{command}" if ENV["SUDO"] == true
|
65
|
+
sh %{#{command}}
|
66
|
+
end
|
67
|
+
|
68
|
+
desc "Generate the rdoc"
|
69
|
+
Rake::RDocTask.new do |rdoc|
|
70
|
+
files = ["README.markdown", "lib/**/*.rb"]
|
71
|
+
rdoc.rdoc_files.add(files)
|
72
|
+
rdoc.main = "README.markdown"
|
73
|
+
rdoc.title = spec.summary
|
74
|
+
end
|
75
|
+
|
76
|
+
task :yank do
|
77
|
+
`gem yank #{spec.name} -v #{spec.version}`
|
78
|
+
end
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
File.dirname(__FILE__) + "/rails/init.rb"
|
data/lib/cockpit.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'active_support'
|
3
|
+
require 'active_record'
|
4
|
+
|
5
|
+
this = File.dirname(__FILE__)
|
6
|
+
Dir["#{this}/cockpit/*"].each { |c| require c }
|
7
|
+
|
8
|
+
class Settings
|
9
|
+
include Cockpit::Configuration
|
10
|
+
end
|
11
|
+
|
12
|
+
def Settings(*args, &block)
|
13
|
+
Settings.configure(*args, &block)
|
14
|
+
end
|
15
|
+
|
16
|
+
def Cockpit(*args, &block)
|
17
|
+
Settings(*args, &block)
|
18
|
+
end
|
19
|
+
|
20
|
+
ActiveRecord::Base.send(:include, Cockpit) if defined?(ActiveRecord::Base)
|
21
|
+
|
22
|
+
require "#{this}/../app/models/setting.rb"
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module Cockpit
|
2
|
+
|
3
|
+
def self.included(base)
|
4
|
+
base.extend ClassMethods
|
5
|
+
end
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def acts_as_configurable(*args, &block)
|
9
|
+
options = args.extract_options!
|
10
|
+
settings_name = (args.shift || "settings").to_s
|
11
|
+
clazz_name = self.to_s.downcase.split("::").last
|
12
|
+
|
13
|
+
class_inheritable_accessor settings_name
|
14
|
+
has_many settings_name, :class_name => "Setting", :as => :configurable
|
15
|
+
|
16
|
+
Settings { send(clazz_name, &block) }
|
17
|
+
|
18
|
+
self.send("#{settings_name}=", ::Settings.for(clazz_name))
|
19
|
+
|
20
|
+
define_method settings_name do |*value|
|
21
|
+
unless @settings
|
22
|
+
@settings = self.class.send(settings_name).dup
|
23
|
+
@settings.configurable = self
|
24
|
+
end
|
25
|
+
|
26
|
+
unless value.empty?
|
27
|
+
@settings[value.first]
|
28
|
+
else
|
29
|
+
@settings
|
30
|
+
end
|
31
|
+
# model-dependent settings.
|
32
|
+
# requires refactoring the Settings module
|
33
|
+
# so none of it uses class methods...
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
def acts_as_settable
|
39
|
+
belongs_to :configurable, :polymorphic => true
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.get_type(object)
|
44
|
+
result = case object
|
45
|
+
when Fixnum
|
46
|
+
:integer
|
47
|
+
when Array
|
48
|
+
:array
|
49
|
+
when Float # decimal
|
50
|
+
:float
|
51
|
+
when String
|
52
|
+
:string
|
53
|
+
when Proc
|
54
|
+
:proc
|
55
|
+
when TrueClass
|
56
|
+
:boolean
|
57
|
+
when FalseClass
|
58
|
+
:boolean
|
59
|
+
when DateTime
|
60
|
+
:datetime
|
61
|
+
when Time
|
62
|
+
:time
|
63
|
+
else
|
64
|
+
:string
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.type_cast(object, type)
|
69
|
+
return object if type.nil?
|
70
|
+
result = case type.to_sym
|
71
|
+
when :integer
|
72
|
+
object.to_i
|
73
|
+
when :array
|
74
|
+
object.to_a
|
75
|
+
when :float, :decimal # decimal
|
76
|
+
object.to_f
|
77
|
+
when :string, :text
|
78
|
+
object.to_s
|
79
|
+
when :boolean
|
80
|
+
if object == "true" || object == true || object == "1" || object == 1 || object == "t"
|
81
|
+
true
|
82
|
+
else
|
83
|
+
false
|
84
|
+
end
|
85
|
+
when :datetime, :timestamp
|
86
|
+
object.is_a?(String) ? DateTime.parse(object) : object
|
87
|
+
when :time
|
88
|
+
object.is_a?(String) ? Time.parse(object) : object
|
89
|
+
else
|
90
|
+
object.to_s
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
@@ -0,0 +1,218 @@
|
|
1
|
+
module Cockpit
|
2
|
+
module Configuration
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.extend ClassMethods
|
6
|
+
base.class_eval do
|
7
|
+
include InstanceMethods
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
module InstanceMethods
|
12
|
+
|
13
|
+
attr_accessor :setting_class, :configurable
|
14
|
+
|
15
|
+
def setting_class
|
16
|
+
@setting_class ||= ::Setting
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(*args, &block)
|
20
|
+
store.tree = args.extract_options!
|
21
|
+
value = args
|
22
|
+
build(&block)
|
23
|
+
end
|
24
|
+
|
25
|
+
def build(&block)
|
26
|
+
tree.instance_eval(&block) if block_given?
|
27
|
+
end
|
28
|
+
|
29
|
+
def configurable=(object)
|
30
|
+
@configurable = object
|
31
|
+
store.configurable = object
|
32
|
+
end
|
33
|
+
|
34
|
+
# something like this
|
35
|
+
# Settings.for(@user.id).set(:allow_email => params[:allow_email])
|
36
|
+
# or
|
37
|
+
# @user.settings(:allow_email => params[:allow_email])
|
38
|
+
def for(configurable_id)
|
39
|
+
self
|
40
|
+
end
|
41
|
+
|
42
|
+
def each_setting(&block)
|
43
|
+
tree.each_setting(&block)
|
44
|
+
end
|
45
|
+
|
46
|
+
def tree
|
47
|
+
store.tree
|
48
|
+
end
|
49
|
+
|
50
|
+
def defaults
|
51
|
+
store.defaults
|
52
|
+
end
|
53
|
+
|
54
|
+
def store
|
55
|
+
self.store = :memory if @store.nil?
|
56
|
+
@store
|
57
|
+
end
|
58
|
+
|
59
|
+
def empty?
|
60
|
+
tree.empty?
|
61
|
+
end
|
62
|
+
|
63
|
+
def store=(value)
|
64
|
+
options = {:configurable => configurable}
|
65
|
+
options[:tree] = @store.tree unless @store.nil?
|
66
|
+
@store = case value
|
67
|
+
when :memory
|
68
|
+
Cockpit::Store::Memory.new(self, options)
|
69
|
+
when :db
|
70
|
+
Cockpit::Store::Database.new(self, options)
|
71
|
+
else
|
72
|
+
value
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def get(path)
|
77
|
+
store.get(path)
|
78
|
+
end
|
79
|
+
alias_method :[], :get
|
80
|
+
|
81
|
+
def get!(path)
|
82
|
+
store.get!(path)
|
83
|
+
end
|
84
|
+
|
85
|
+
def set(value)
|
86
|
+
store.set(value)
|
87
|
+
end
|
88
|
+
|
89
|
+
def set!(value)
|
90
|
+
store.set!(value)
|
91
|
+
end
|
92
|
+
|
93
|
+
def []=(key, value)
|
94
|
+
store.set(key => value)
|
95
|
+
end
|
96
|
+
|
97
|
+
def clear(options = {})
|
98
|
+
store.clear(options)
|
99
|
+
end
|
100
|
+
|
101
|
+
def inspect
|
102
|
+
"<##{self.class.to_s} @tree=#{tree.inspect}/>"
|
103
|
+
end
|
104
|
+
|
105
|
+
def to_yaml
|
106
|
+
to_hash.to_yaml
|
107
|
+
end
|
108
|
+
|
109
|
+
def to_hash
|
110
|
+
store.tree.to_hash
|
111
|
+
end
|
112
|
+
|
113
|
+
def method_missing(meth, *args, &block)
|
114
|
+
if args.empty?
|
115
|
+
store.get(meth)
|
116
|
+
else
|
117
|
+
store.set(meth, args.first)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
module ClassMethods
|
124
|
+
|
125
|
+
def setting_class
|
126
|
+
global.setting_class
|
127
|
+
end
|
128
|
+
|
129
|
+
def global(&block)
|
130
|
+
@global ||= new
|
131
|
+
@global.build(&block)
|
132
|
+
@global
|
133
|
+
end
|
134
|
+
|
135
|
+
def configure(*args, &block)
|
136
|
+
options = args.extract_options!
|
137
|
+
path = args.first
|
138
|
+
if path && !path.is_a?(Hash)
|
139
|
+
global[path]
|
140
|
+
elsif !options.empty?
|
141
|
+
global.set(options)
|
142
|
+
else
|
143
|
+
global(&block)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
# something like this
|
148
|
+
# Settings.for(@user.id).set(:allow_email => params[:allow_email])
|
149
|
+
# or
|
150
|
+
# @user.settings(:allow_email => params[:allow_email])
|
151
|
+
def for(name)
|
152
|
+
Settings.new(get(name).dup)
|
153
|
+
end
|
154
|
+
|
155
|
+
def tree
|
156
|
+
global.tree
|
157
|
+
end
|
158
|
+
|
159
|
+
def defaults
|
160
|
+
global.defaults
|
161
|
+
end
|
162
|
+
|
163
|
+
def store
|
164
|
+
global.store
|
165
|
+
end
|
166
|
+
|
167
|
+
def store=(value)
|
168
|
+
global.store = value
|
169
|
+
end
|
170
|
+
|
171
|
+
def get(path)
|
172
|
+
global.get(path)
|
173
|
+
end
|
174
|
+
alias_method :[], :get
|
175
|
+
|
176
|
+
def get!(path)
|
177
|
+
global.get!(path)
|
178
|
+
end
|
179
|
+
|
180
|
+
def set(value)
|
181
|
+
global.set(value)
|
182
|
+
end
|
183
|
+
|
184
|
+
def set!(value)
|
185
|
+
global.set!(value)
|
186
|
+
end
|
187
|
+
|
188
|
+
def []=(key, value)
|
189
|
+
global.set(key => value)
|
190
|
+
end
|
191
|
+
|
192
|
+
def clear(options = {})
|
193
|
+
global.clear(options)
|
194
|
+
end
|
195
|
+
|
196
|
+
def empty?
|
197
|
+
global.empty?
|
198
|
+
end
|
199
|
+
|
200
|
+
def inspect
|
201
|
+
global.inspect
|
202
|
+
end
|
203
|
+
|
204
|
+
def to_yaml
|
205
|
+
global.to_yaml
|
206
|
+
end
|
207
|
+
|
208
|
+
def to_hash
|
209
|
+
global.to_hash
|
210
|
+
end
|
211
|
+
|
212
|
+
def method_missing(meth, *args, &block)
|
213
|
+
global.method_missing(meth, *args, &block)
|
214
|
+
end
|
215
|
+
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|