cantango-config 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.
Files changed (83) hide show
  1. data/.document +5 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +40 -0
  4. data/Gemfile.lock +163 -0
  5. data/LICENSE.txt +20 -0
  6. data/README.mdown +21 -0
  7. data/Rakefile +49 -0
  8. data/VERSION +1 -0
  9. data/cantango-config.gemspec +145 -0
  10. data/lib/cantango/adapter/compiler.rb +9 -0
  11. data/lib/cantango/adapter/moneta.rb +23 -0
  12. data/lib/cantango/config.rb +12 -0
  13. data/lib/cantango/configuration/ability.rb +14 -0
  14. data/lib/cantango/configuration/account.rb +23 -0
  15. data/lib/cantango/configuration/accounts.rb +8 -0
  16. data/lib/cantango/configuration/adapters.rb +24 -0
  17. data/lib/cantango/configuration/autoload.rb +38 -0
  18. data/lib/cantango/configuration/candidate_registry.rb +94 -0
  19. data/lib/cantango/configuration/categories.rb +57 -0
  20. data/lib/cantango/configuration/debug.rb +41 -0
  21. data/lib/cantango/configuration/engine.rb +33 -0
  22. data/lib/cantango/configuration/engines.rb +97 -0
  23. data/lib/cantango/configuration/factory.rb +59 -0
  24. data/lib/cantango/configuration/guest.rb +57 -0
  25. data/lib/cantango/configuration/hash_registry.rb +91 -0
  26. data/lib/cantango/configuration/hooks.rb +12 -0
  27. data/lib/cantango/configuration/localhosts.rb +12 -0
  28. data/lib/cantango/configuration/models/actions.rb +26 -0
  29. data/lib/cantango/configuration/models/active_record.rb +22 -0
  30. data/lib/cantango/configuration/models/data_mapper.rb +12 -0
  31. data/lib/cantango/configuration/models/generic.rb +12 -0
  32. data/lib/cantango/configuration/models/mongo.rb +12 -0
  33. data/lib/cantango/configuration/models/mongo_mapper.rb +11 -0
  34. data/lib/cantango/configuration/models/mongoid.rb +13 -0
  35. data/lib/cantango/configuration/models.rb +77 -0
  36. data/lib/cantango/configuration/modes.rb +21 -0
  37. data/lib/cantango/configuration/orms.rb +8 -0
  38. data/lib/cantango/configuration/registry.rb +56 -0
  39. data/lib/cantango/configuration/user.rb +47 -0
  40. data/lib/cantango/configuration/users.rb +8 -0
  41. data/lib/cantango/configuration.rb +99 -0
  42. data/spec/cantango/config_spec.rb +8 -0
  43. data/spec/cantango/configuration/ability_spec.rb +13 -0
  44. data/spec/cantango/configuration/account_spec.rb +21 -0
  45. data/spec/cantango/configuration/accounts_spec.rb +18 -0
  46. data/spec/cantango/configuration/adapters_spec.rb +30 -0
  47. data/spec/cantango/configuration/autoload_spec.rb +52 -0
  48. data/spec/cantango/configuration/candidate_registry_spec.rb +12 -0
  49. data/spec/cantango/configuration/categories_spec.rb +58 -0
  50. data/spec/cantango/configuration/debug_spec.rb +39 -0
  51. data/spec/cantango/configuration/engines/engine_shared.rb +22 -0
  52. data/spec/cantango/configuration/engines_spec.rb +102 -0
  53. data/spec/cantango/configuration/factory_spec.rb +18 -0
  54. data/spec/cantango/configuration/guest/find_guest_default_way_spec.rb +32 -0
  55. data/spec/cantango/configuration/guest_spec.rb +61 -0
  56. data/spec/cantango/configuration/hash_registry_spec.rb +22 -0
  57. data/spec/cantango/configuration/localhosts_spec.rb +9 -0
  58. data/spec/cantango/configuration/models_spec.rb +47 -0
  59. data/spec/cantango/configuration/orms_spec.rb +9 -0
  60. data/spec/cantango/configuration/registry_spec.rb +15 -0
  61. data/spec/cantango/configuration/shared/candidate_registry_ex.rb +47 -0
  62. data/spec/cantango/configuration/shared/factory_ex.rb +40 -0
  63. data/spec/cantango/configuration/shared/hash_registry_ex.rb +55 -0
  64. data/spec/cantango/configuration/shared/modes_ex.rb +14 -0
  65. data/spec/cantango/configuration/shared/registry_ex.rb +40 -0
  66. data/spec/cantango/configuration/shared/role_registry_ex.rb +22 -0
  67. data/spec/cantango/configuration/user_spec.rb +45 -0
  68. data/spec/cantango/configuration/users_spec.rb +18 -0
  69. data/spec/cantango/configuration_spec.rb +112 -0
  70. data/spec/db/database.yml +4 -0
  71. data/spec/factories/project.rb +6 -0
  72. data/spec/fixtures/models/admin.rb +2 -0
  73. data/spec/fixtures/models/admin_account.rb +22 -0
  74. data/spec/fixtures/models/items.rb +8 -0
  75. data/spec/fixtures/models/permission.rb +12 -0
  76. data/spec/fixtures/models/project.rb +2 -0
  77. data/spec/fixtures/models/simple_roles.rb +49 -0
  78. data/spec/fixtures/models/user.rb +52 -0
  79. data/spec/fixtures/models/user_account.rb +21 -0
  80. data/spec/fixtures/models.rb +2 -0
  81. data/spec/migrations/001_create_projects.rb +12 -0
  82. data/spec/spec_helper.rb +35 -0
  83. metadata +231 -0
@@ -0,0 +1,94 @@
1
+ require 'singleton'
2
+ require 'sugar-high/kind_of'
3
+
4
+ module CanTango
5
+ class Configuration
6
+ class CandidateRegistry
7
+ def register label, value
8
+ raise "first arg must be a label, was: #{label}" if !label.kind_of_label?
9
+ raise "second arg must be a valid Class, was: #{value}" if !valid? value
10
+ name_registry.register label.to_sym
11
+ class_registry.register value
12
+ end
13
+ alias_method :[]=, :register
14
+
15
+ def << hash
16
+ raise "Must be a hash" if !hash.is_a? Hash
17
+ hash.each_pair do |key, value|
18
+ register key, value
19
+ end
20
+ end
21
+
22
+ def registered
23
+ name_registry.registered
24
+ end
25
+ alias_method :registered_names, :registered
26
+
27
+ def clean!
28
+ name_registry.clean!
29
+ class_registry.clean!
30
+ end
31
+ alias_method :clear!, :clean!
32
+
33
+ def registered_classes
34
+ class_registry.registered
35
+ end
36
+
37
+ def registered? name
38
+ name_registry.registered? name
39
+ end
40
+
41
+ def registered_class? name
42
+ class_registry.registered? name
43
+ end
44
+
45
+ def name_registry
46
+ NameRegistry.instance
47
+ end
48
+
49
+ def class_registry
50
+ ClassRegistry.instance
51
+ end
52
+
53
+ def value_methods
54
+ class_registry.value_methods
55
+ end
56
+
57
+ def value_types
58
+ class_registry.types
59
+ end
60
+
61
+ class NameRegistry < Registry
62
+ include Singleton
63
+ end
64
+
65
+ class ClassRegistry < Registry
66
+ include Singleton
67
+
68
+ def types
69
+ [Class]
70
+ end
71
+
72
+ def value_methods
73
+ []
74
+ end
75
+ end
76
+
77
+ protected
78
+
79
+ def valid? value
80
+ valid_by_type?(value) && valid_by_methods?(value)
81
+ end
82
+
83
+ def valid_by_type? value
84
+ return true if value_types.blank?
85
+ value.any_kind_of?(*value_types)
86
+ end
87
+
88
+ def valid_by_methods? value
89
+ return true if value_methods.blank?
90
+ value_methods.all?{|m| value.respond_to(m)}
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,57 @@
1
+ module CanTango
2
+ class Configuration
3
+ class Categories < HashRegistry
4
+
5
+ include Singleton
6
+
7
+ def [] label
8
+ models = super
9
+ raise "Category '#{label}' either not exists or invalid!" if !models.kind_of?(Array)
10
+ models
11
+ end
12
+
13
+ def category label, &block
14
+ cat = Category.new self[label]
15
+ yield cat if block
16
+ cat
17
+ end
18
+
19
+ # test if a any of the categories contain the subject
20
+ def has_any? subject, &block
21
+ found = registered.any? {|cat, subjects| subjects.include? subject }
22
+ yield if found && block
23
+ found
24
+ end
25
+
26
+ # find the category of a subject if such a category exists
27
+ def category_names_of_subject subject, &block
28
+ categories_of_subject(subject).keys
29
+ end
30
+
31
+ # find the category of a subject if such a category exists
32
+ def categories_of_subject subject, &block
33
+ found_categories = registered.select do |cat, subjects|
34
+ subjects.include? subject.to_s
35
+ end
36
+ found_categories.empty? ? {} : found_categories
37
+ end
38
+
39
+ class Category
40
+ def initialize *subjects
41
+ @subjects = subjects.flatten
42
+ end
43
+
44
+ def subjects
45
+ @subjects ||= []
46
+ end
47
+
48
+ # test if a particular category has a certain subject
49
+ def has_any? subject, &block
50
+ found = subjects.include? subject
51
+ yield if found && block
52
+ found
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,41 @@
1
+ module CanTango
2
+ class Configuration
3
+ # Note: This config feature is currently not used, but could potentially be of use in the future
4
+ class Debug
5
+ include Singleton
6
+
7
+ def set state = :on
8
+ raise ArgumentError, "Must be :on or :off" unless !state || [:on, :off].include?(state)
9
+ @state = state || :on
10
+ end
11
+
12
+ def on?
13
+ @state == :on
14
+ end
15
+
16
+ def off?
17
+ !on?
18
+ end
19
+
20
+ def debug_writer= proc
21
+ raise ArgumentError, "Debug writer must be callable (lambda or Proc), was: #{proc}" if !callable?(proc)
22
+ @debug_writer = proc
23
+ end
24
+
25
+ def write msg
26
+ @debug_writer ||= Proc.new{|msg| puts msg}
27
+ @debug_writer.call(msg)
28
+ end
29
+
30
+ protected
31
+
32
+ def callable? obj
33
+ obj && obj.respond_to?(:call)
34
+ end
35
+ end
36
+ end
37
+ end
38
+
39
+
40
+
41
+
@@ -0,0 +1,33 @@
1
+ require 'singleton'
2
+
3
+ module CanTango
4
+ class Configuration
5
+ class Engine
6
+ include Singleton
7
+ include CanTango::Configuration::Modes
8
+
9
+ def set state = :on
10
+ raise ArgumentError, "Must be :on or :off" unless !state || [:on, :off].include?(state)
11
+ @state = state || :on
12
+ end
13
+
14
+ def reset!
15
+ @state = nil
16
+ end
17
+
18
+ def on?
19
+ @state == :on
20
+ end
21
+
22
+ def off?
23
+ !on?
24
+ end
25
+
26
+ protected
27
+
28
+ def ns
29
+ CanTango::Configuration::Engines
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,97 @@
1
+ module CanTango
2
+ class Configuration
3
+ class Engines < HashRegistry
4
+ autoload_modules :Permission, :Engine
5
+
6
+ include Singleton
7
+ include Enumerable
8
+
9
+ # engine registry is a simple hash
10
+ def register hash
11
+ hash.each_pair do |name, engine_class|
12
+ raise "Class must implement the CanTango Engine API. You can start by sublclassing CanTango::Engine" if !engine? engine_class
13
+ raise "Name of engine must be a String or Symbol" if !name.kind_of_label?
14
+ registered[name.to_s] = engine_class
15
+ end
16
+ end
17
+
18
+ # defines the order of execution of engine in ability
19
+ def set_execution_order *names
20
+ @execution_order = names.flatten.uniq.map(&:to_s).select {|name| available? name }
21
+ end
22
+
23
+ def dont_execute name
24
+ execution_order.delete(name.to_s)
25
+ end
26
+
27
+ def execute_first name
28
+ dont_execute name
29
+ execution_order.insert(0, name.to_s)
30
+ end
31
+
32
+ def execute_last name
33
+ dont_execute name
34
+ execution_order.insert(-1, name.to_s)
35
+ end
36
+
37
+ def execute_before existing, name
38
+ dont_execute name
39
+ index = execution_order.index(existing.to_s) || 0
40
+ execution_order.insert(index, name.to_s)
41
+ execution_order.compact!
42
+ end
43
+
44
+ def execute_after existing, name
45
+ dont_execute name
46
+ index = execution_order.index(existing.to_s)
47
+ index ? execution_order.insert(index +1, name.to_s) : execute_last(name)
48
+ execution_order.compact!
49
+ end
50
+
51
+ def execution_order
52
+ @execution_order ||= (available - [:cache])
53
+ end
54
+
55
+ def available
56
+ registered_names
57
+ end
58
+
59
+ def available? name
60
+ available.include? name.to_s
61
+ end
62
+
63
+ def all state
64
+ available.each {|engine| send(engine).set state }
65
+ end
66
+
67
+ def any? state
68
+ available.any? {|engine| send(engine).send(:"#{state}?") if respond_to?(engine) }
69
+ end
70
+
71
+ def clear!
72
+ each {|engine| engine.reset! }
73
+ @registered = nil
74
+ @execution_order = nil
75
+ end
76
+
77
+ def each
78
+ available.each {|engine| yield send(engine) if respond_to?(engine) }
79
+ end
80
+
81
+ def active? name
82
+ active.include? name.to_sym
83
+ end
84
+
85
+ def active
86
+ available.select {|engine| send(engine).on? if respond_to?(engine) }
87
+ end
88
+
89
+ protected
90
+
91
+ # does it implement the basic Engine API?
92
+ def engine? engine_class
93
+ [:execute!, :ability].all? {|meth| engine_class.instance_methods.include? meth }
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,59 @@
1
+ module CanTango
2
+ class Configuration
3
+ module Factory
4
+ def clear!
5
+ @factory = nil
6
+ end
7
+
8
+ def factory factory = nil
9
+ raise ArgumentError, "Factory must be a callable (lambda or Proc), was: #{proc}" if !callable? factory
10
+ @factory = factory
11
+ end
12
+
13
+ alias_method :factory=, :factory
14
+
15
+ def factory_build obj = nil, opts = {}
16
+ factory_method = @factory ? :call_factory : :default_factory
17
+ send(factory_method, obj, opts)
18
+ end
19
+
20
+ def call_factory obj = nil, opts = {}
21
+ @factory.respond_to?(:call) ? @factory.call(obj, opts) : @factory
22
+ end
23
+
24
+ def default_factory obj = nil, opts = {}
25
+ raise "Default factory must be defined" if !default_class
26
+ default_class.new obj, options.merge(opts)
27
+ end
28
+
29
+ attr_reader :default_class
30
+
31
+ # must be a Class of type Cache (Base?)
32
+ def default_class= clazz
33
+ raise ArgumentError, "default must be a Class" if !is_class? clazz
34
+ @default_class = clazz
35
+ end
36
+
37
+ def options= options = {}
38
+ raise ArgumentError, "Must be a Hash, was #{options}" if !options.kind_of? Hash
39
+ @options = options
40
+ end
41
+
42
+ def options
43
+ @options ? type_options : type_options.merge(@options || {})
44
+ end
45
+
46
+ def type_options
47
+ {}
48
+ end
49
+
50
+ protected
51
+
52
+ def callable? obj
53
+ obj && obj.respond_to?(:call)
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+
@@ -0,0 +1,57 @@
1
+ module CanTango
2
+ class Configuration
3
+ class Guest
4
+ include Singleton
5
+
6
+ def clear!
7
+ @user = nil
8
+ @account = nil
9
+ end
10
+
11
+ def user user = nil, &block
12
+ return (@user || guest_user) if !user && !block
13
+ @user = user || yield
14
+ end
15
+
16
+ alias_method :user=, :user
17
+
18
+ def account account = nil, &block
19
+ return (@account || guest_account) if !account && !block
20
+ @account = account || yield
21
+ end
22
+ alias_method :user_account, :account
23
+ alias_method :account=, :account
24
+
25
+ def default_user?
26
+ has_guest? base_user_class
27
+ end
28
+
29
+ def default_account?
30
+ has_guest? base_account_class
31
+ end
32
+
33
+ protected
34
+
35
+ def guest_user
36
+ base_user_class.guest if default_user?
37
+ end
38
+
39
+ def guest_account
40
+ base_account_class.guest if default_account?
41
+ end
42
+
43
+ def has_guest? clazz
44
+ clazz && defined?(clazz) && clazz.respond_to?(:guest)
45
+ end
46
+
47
+ def base_user_class
48
+ CanTango.config.user.base_class
49
+ end
50
+
51
+ def base_account_class
52
+ CanTango.config.user_account.base_class
53
+ end
54
+ end
55
+ end
56
+ end
57
+
@@ -0,0 +1,91 @@
1
+ require 'singleton'
2
+ require 'sugar-high/kind_of'
3
+
4
+ module CanTango
5
+ class Configuration
6
+ class HashRegistry < Registry
7
+
8
+ def types= *types
9
+ raise "This is a Hash registry!"
10
+ end
11
+
12
+ def types
13
+ [Hash]
14
+ end
15
+
16
+ def value_methods
17
+ []
18
+ end
19
+
20
+ def value_types
21
+ []
22
+ end
23
+
24
+ def clean!
25
+ registered = Hashie::Mash.new
26
+ end
27
+ alias_method :clear!, :clean!
28
+
29
+ def default!
30
+ @registered = default
31
+ end
32
+
33
+ def << hash
34
+ raise "Must be a hash" if !hash.is_a? Hash
35
+ registered.merge!(hash) and return if value_methods.empty? && value_types.empty?
36
+ hash.each_pair do |key, value|
37
+ registered[key] = value if value_api.all?{|m| value.respond_to(m)} && value.any_kind_of?(value_types)
38
+ end
39
+ end
40
+
41
+ def [] label
42
+ raise "Must be a label" if !label.kind_of_label?
43
+ registered[label.to_s]
44
+ end
45
+
46
+ def []= label, value
47
+ raise "Must be a label" if !label.kind_of_label?
48
+ registered[label.to_s] = value
49
+ end
50
+
51
+ def register hash
52
+ raise "Must be a hash" if !hash.is_a? Hash
53
+ registered.merge! hash
54
+ end
55
+
56
+ def unregister name
57
+ @registered = {} if name == :all
58
+ @registered.delete(name)
59
+ end
60
+
61
+ def registered
62
+ @registered ||= default
63
+ end
64
+
65
+ def registered_names
66
+ registered.keys
67
+ end
68
+
69
+ def registered_values
70
+ registered.values
71
+ end
72
+
73
+ def registered? label
74
+ registered_names.map(&:to_s).include? label.to_s
75
+ end
76
+ alias_method :registered_name, :registered?
77
+
78
+ def registered_value? value
79
+ registered_values.include? value
80
+ end
81
+
82
+ def default
83
+ @default ||= Hashie::Mash.new
84
+ end
85
+
86
+ def default= hash
87
+ @default = Hashie::Mash.new hash
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,12 @@
1
+ module CanTango
2
+ class Configuration
3
+ class Hooks < HashRegistry
4
+ include Singleton
5
+
6
+ def value_methods
7
+ [:call]
8
+ end
9
+ end
10
+ end
11
+ end
12
+
@@ -0,0 +1,12 @@
1
+ module CanTango
2
+ class Configuration
3
+ class Localhosts < Registry
4
+ include Singleton
5
+
6
+ def default
7
+ @default ||= ['localhost', '0.0.0.0', '127.0.0.1']
8
+ end
9
+ end
10
+ end
11
+ end
12
+
@@ -0,0 +1,26 @@
1
+ module CanTango
2
+ class Configuration
3
+ class Models
4
+ class Actions
5
+ attr_reader :collection, :member
6
+
7
+ def initialize
8
+ @collection = []
9
+ @member = []
10
+ end
11
+
12
+ def actions_for type
13
+ send(type.to_sym) || []
14
+ end
15
+
16
+ def add_member action
17
+ @member << action.to_sym
18
+ end
19
+
20
+ def add_collection action
21
+ @collection << action.to_sym
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,22 @@
1
+ module CanTango
2
+ class Configuration
3
+ class Models
4
+ class ActiveRecord < Generic
5
+ def models
6
+ ::ActiveRecord::Base.descendants
7
+ rescue
8
+ table_models
9
+ end
10
+
11
+ protected
12
+
13
+ def table_models
14
+ ActiveRecord::Base.connection.tables do |t|
15
+ t.classify.constantize
16
+ nil
17
+ end.compact
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,12 @@
1
+ module CanTango
2
+ class Configuration
3
+ class Models
4
+ class DataMapper < Generic
5
+ def models
6
+ DataMapper::Resource.descendants
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
12
+
@@ -0,0 +1,12 @@
1
+ module CanTango
2
+ class Configuration
3
+ class Models
4
+ class Generic
5
+ def available_models
6
+ models.map(&:name)
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
12
+
@@ -0,0 +1,12 @@
1
+ module CanTango
2
+ class Configuration
3
+ class Models
4
+ class Mongo
5
+ def available_models
6
+ models.map {|m| m.to_s.camelize }
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
12
+
@@ -0,0 +1,11 @@
1
+ module CanTango
2
+ class Configuration
3
+ class Models
4
+ module MongoMapper < Mongo
5
+ def models
6
+ MongoMapper.database.collections
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,13 @@
1
+ module CanTango
2
+ class Configuration
3
+ class Models
4
+ class Mongoid < Mongo
5
+ def models
6
+ ::Mongoid.database.collections
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
12
+
13
+