resourcelogic 0.0.11

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.
@@ -0,0 +1,32 @@
1
+ module Resourcelogic
2
+ class ResponseCollector
3
+
4
+ attr_reader :responses
5
+
6
+ delegate :clear, :to => :responses
7
+
8
+ def initialize
9
+ @responses = []
10
+ end
11
+
12
+ def method_missing(method_name, &block)
13
+ existing = self[method_name]
14
+ if existing
15
+ existing[0] = method_name
16
+ existing[1] = block || nil
17
+ else
18
+ @responses << [method_name, block || nil]
19
+ end
20
+ end
21
+
22
+ def [](symbol)
23
+ @responses.find { |method, block| method == symbol }
24
+ end
25
+
26
+ def dup
27
+ returning ResponseCollector.new do |duplicate|
28
+ duplicate.instance_variable_set(:@responses, responses.dup)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,36 @@
1
+ module Resourcelogic
2
+ module Scope
3
+ def self.included(klass)
4
+ klass.class_eval do
5
+ add_acts_as_resource_module(Methods)
6
+ end
7
+ end
8
+
9
+ module Methods
10
+ def self.included(klass)
11
+ klass.class_eval do
12
+ attr_accessor :scoping, :scoping_parent
13
+ end
14
+ end
15
+
16
+ private
17
+ def scope
18
+ return @scope if defined?(@scope)
19
+
20
+ if parent?
21
+ @scope = parent_object.send(parent_scope_name)
22
+ else
23
+ @scope = model
24
+ end
25
+ end
26
+
27
+ def parent_scope
28
+ parent_model
29
+ end
30
+
31
+ def parent_scope_name
32
+ @parent_scope_name ||= model_name.to_s.pluralize
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,148 @@
1
+ module Resourcelogic
2
+ module Self
3
+ def self.included(klass)
4
+ klass.class_eval do
5
+ extend Config
6
+ add_acts_as_resource_module(UrlParts)
7
+ add_acts_as_resource_module(Reflection)
8
+ end
9
+ end
10
+
11
+ module Config
12
+ def model_name(value = nil)
13
+ rw_config(:model_name, value, model_name_from_name)
14
+ end
15
+
16
+ def object_name(value = nil)
17
+ rw_config(:object_name, value, model_name_from_name)
18
+ end
19
+
20
+ private
21
+ def model_name_from_name
22
+ name.underscore.split("/").first.gsub(/_controller/, "").singularize.underscore.to_sym
23
+ end
24
+ end
25
+
26
+ module UrlParts
27
+ private
28
+ # Used internally to provide the options to smart_url from Urligence.
29
+ #
30
+ def collection_url_parts(action = nil, url_params = {})
31
+ [action] + contexts_url_parts + [route_name.to_s.pluralize.to_sym, url_params]
32
+ end
33
+
34
+ # Used internally to provide the options to smart_url from Urligence.
35
+ #
36
+ def object_url_parts(action = nil, *alternate_object_or_params)
37
+ alternate_object, url_params = identify_object_or_params(alternate_object_or_params)
38
+ url_object = alternate_object
39
+ url_object = object if url_object.nil? && object && !object.new_record?
40
+ object_parts = url_object ?
41
+ [route_name, url_object] :
42
+ (action == :new || singleton? ? route_name : route_name.to_s.pluralize.to_sym)
43
+ [action] + contexts_url_parts + [object_parts, url_params]
44
+ end
45
+
46
+ def identify_object_or_params(object_or_params)
47
+ obj = nil
48
+ url_params = {}
49
+ if object_or_params.size > 1
50
+ url_params = object_or_params.last if object_or_params.last.is_a?(Hash)
51
+ obj = object_or_params.first
52
+ elsif object_or_params.first.is_a?(Hash)
53
+ url_params = object_or_params.first
54
+ else
55
+ obj = object_or_params.first
56
+ end
57
+ [obj, url_params]
58
+ end
59
+ end
60
+
61
+ module Reflection
62
+ def self.included(klass)
63
+ klass.helper_method :model_name, :collection, :object, :path_name, :route_name
64
+ end
65
+
66
+ private
67
+ def path_name
68
+ return @path_name if defined?(@path_name)
69
+ path_parts = request.path.split("/")
70
+ path_parts.reverse.each do |path_part|
71
+ next if path_part.blank?
72
+ if model_name_from_path_part(path_part) == model_name
73
+ return @path_name = path_part.to_sym
74
+ end
75
+ end
76
+ @path_name = nil
77
+ end
78
+
79
+ def route_name
80
+ return @route_name if defined?(@route_name)
81
+ path_parts = request.path.split("/")
82
+ path_parts.reverse.each do |path_part|
83
+ next if path_part.blank?
84
+ if model_name_from_path_part(path_part) == model_name
85
+ return @route_name = route_name_from_path_part(path_part)
86
+ end
87
+ end
88
+ @route_name = model_name
89
+ end
90
+
91
+ # Convenience method for the class level model_name method
92
+ def model_name
93
+ @model_name ||= self.class.model_name.to_sym
94
+ end
95
+
96
+ def model
97
+ @model ||= model_name.to_s.camelize.constantize
98
+ end
99
+
100
+ # Convenience method for the class level object_name method
101
+ def object_name
102
+ @object_name ||= self.class.object_name.to_sym
103
+ end
104
+
105
+ # The collection for the resource.
106
+ def collection # :doc:
107
+ @collection ||= scope.all
108
+ end
109
+
110
+ # The current paremter than contains the object identifier.
111
+ def id # :doc:
112
+ params[:id]
113
+ end
114
+
115
+ def id?
116
+ params.key?(:id)
117
+ end
118
+
119
+ # The parameter hash that contains the object attributes.
120
+ def attributes
121
+ params[object_name]
122
+ end
123
+
124
+ def attributes?
125
+ params.key?(object_name)
126
+ end
127
+
128
+ # The current member being used. If no param is present, it will look for
129
+ # a current_#{object_name} method. For example, if you have a UsersController
130
+ # and its a singleton controller, meaning no identifier is needed, this will
131
+ # look for a current_user method. If this is not the behavioru you want, simply
132
+ # overwrite this method.
133
+ def object # :doc:
134
+ @object ||= id? ? find_object : build_object
135
+ end
136
+
137
+ def build_object
138
+ obj = scope.respond_to?(:build) ? scope.build : scope.new
139
+ obj.attributes = attributes
140
+ obj
141
+ end
142
+
143
+ def find_object
144
+ scope.find(id)
145
+ end
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,20 @@
1
+ module Resourcelogic
2
+ module Sibling
3
+ def self.included(klass)
4
+ klass.class_eval do
5
+ add_acts_as_resource_module(Urls)
6
+ end
7
+ end
8
+
9
+ module Urls
10
+ private
11
+ def sibling_url_parts(action = nil, sibling = nil, url_params = {})
12
+ [action] + contexts_url_parts + [sibling.is_a?(Symbol) ? sibling : [sibling.class.name.underscore.to_sym, sibling], url_params]
13
+ end
14
+
15
+ def sibling_collection_url_parts(action = nil, sibling_name = nil, url_params = {})
16
+ [action] + contexts_url_parts + [sibling_name, url_params]
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,55 @@
1
+ # Nested and Polymorphic Resource Helpers
2
+ #
3
+ module Resourcelogic
4
+ module Singleton
5
+ def self.included(klass)
6
+ klass.class_eval do
7
+ add_acts_as_resource_module(Methods)
8
+ end
9
+ end
10
+
11
+ module Methods
12
+ def object
13
+ return @object if defined?(@object)
14
+
15
+ if singleton?
16
+ if !parent? && respond_to?("current_#{model_name}", true)
17
+ @object = send("current_#{model_name}")
18
+ elsif parent? && parent_object.send(model_name)
19
+ @object = parent_object.send(model_name)
20
+ else
21
+ super
22
+ end
23
+ else
24
+ super
25
+ end
26
+ end
27
+
28
+ def build_object
29
+ if singleton? && parent?
30
+ scope.send("build_#{model_name}")
31
+ else
32
+ super
33
+ end
34
+ end
35
+
36
+ def scope
37
+ if singleton? && parent?
38
+ parent_object
39
+ else
40
+ super
41
+ end
42
+ end
43
+
44
+ # Route alises can only be used for singleton, like account => user. Otherwise the urligence wont work because there is no account model.
45
+ def object_url_parts(action = nil, *alternate_object_or_params)
46
+ singleton? ? ([action] + contexts_url_parts + [route_name]) : super
47
+ end
48
+
49
+ # Override me with true to make singleton
50
+ def singleton?
51
+ false
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,98 @@
1
+ # Nested and Polymorphic Resource Helpers
2
+ #
3
+ module Resourcelogic
4
+ module SubViews
5
+ def self.included(klass)
6
+ klass.class_eval do
7
+ extend Config
8
+ add_acts_as_resource_module(Methods)
9
+ end
10
+ end
11
+
12
+ module Config
13
+ def namespace_views_by_context(value = nil)
14
+ rw_config(:namespace_views_by_context, value)
15
+ end
16
+
17
+ def namespace_views_by_context?
18
+ !namespace_views_by_context.blank?
19
+ end
20
+
21
+ def namespace_views_by_route_alias(value = nil)
22
+ rw_config(:namespace_views_by_route_alias, value)
23
+ end
24
+
25
+ def namespace_views_by_route_alias?
26
+ !namespace_views_by_route_alias.blank?
27
+ end
28
+ end
29
+
30
+ module Methods
31
+ def self.included(klass)
32
+ klass.helper_method :namespace_views_by_route_alias, :namespace_views_by_route_alias?,
33
+ :namespace_views_by_context, :namespace_views_by_context?, :sub_template_name
34
+ end
35
+
36
+ private
37
+ def namespace_views_by_context?
38
+ self.class.namespace_views_by_context?
39
+ end
40
+
41
+ def namespace_views_by_context
42
+ self.class.namespace_views_by_context
43
+ end
44
+
45
+ def namespace_views_by_route_alias?
46
+ self.class.namespace_views_by_route_alias? && route_name != model_name
47
+ end
48
+
49
+ def namespace_views_by_route_alias
50
+ self.class.namespace_views_by_route_alias
51
+ end
52
+
53
+ def sub_template_name(name)
54
+ path_parts = [controller_name]
55
+
56
+ if namespace_views_by_context?
57
+ context_folder_name = namespace_views_by_context.is_a?(Hash) && namespace_views_by_context.key?(context) ?
58
+ namespace_views_by_context[context] : context
59
+ path_parts << (context_folder_name || "root")
60
+ end
61
+
62
+ if namespace_views_by_route_alias?
63
+ route_alias_folder_name = namespace_views_by_route_alias.is_a?(Hash) && namespace_views_by_route_alias.key?(route_name) ?
64
+ namespace_views_by_route_alias[route_name] : route_name
65
+ path_parts << (route_alias_folder_name).to_s.pluralize
66
+ end
67
+
68
+ path_parts << name
69
+ path_parts.join("/")
70
+ end
71
+
72
+ def default_template_name(action_name = self.action_name)
73
+ if namespace_views_by_context? || namespace_views_by_route_alias?
74
+ sub_template_name(action_name)
75
+ else
76
+ super
77
+ end
78
+ end
79
+ end
80
+
81
+ module Partials
82
+ def _pick_partial_template(partial_path)
83
+ if respond_to?(:namespace_views_by_context?) && respond_to?(:namespace_views_by_route_alias?) &&
84
+ (namespace_views_by_context? || namespace_views_by_route_alias?) && !partial_path.include?("/")
85
+ partial_path = sub_template_name(partial_path)
86
+ end
87
+ super
88
+ end
89
+ end
90
+ end
91
+ end
92
+
93
+
94
+ module ActionView
95
+ class Base
96
+ include Resourcelogic::SubViews::Partials
97
+ end
98
+ end
@@ -0,0 +1,128 @@
1
+ module Resourcelogic
2
+ module Urligence
3
+ def self.included(klass)
4
+ klass.helper_method :smart_url, :smart_path, :hash_for_smart_url, :hash_for_smart_path, :method_missing
5
+ end
6
+
7
+ def smart_url(*url_parts)
8
+ url_params = url_parts.extract_options!
9
+ url_parts.push(:url)
10
+ url_parts.push(url_params)
11
+ urligence(*url_parts)
12
+ end
13
+
14
+ def smart_path(*url_parts)
15
+ url_params = url_parts.extract_options!
16
+ url_parts.push(:path)
17
+ url_parts.push(url_params)
18
+ urligence(*url_parts)
19
+ end
20
+
21
+ def hash_for_smart_url(*url_parts)
22
+ urligence(*url_parts.unshift(:hash_for).push(:url).push({:type => :hash}))
23
+ end
24
+
25
+ def hash_for_smart_path(*url_parts)
26
+ urligence(*url_parts.unshift(:hash_for).push(:path).push({:type => :hash}))
27
+ end
28
+
29
+ private
30
+ def urligence(*url_parts)
31
+ url_parts = cleanup_url_parts(url_parts)
32
+ method_name_fragments = extract_method_name_fragments(url_parts)
33
+ method_arguments = extract_method_arguments(url_parts)
34
+
35
+ if url_parts.first != :hash_for
36
+ send method_name_fragments.join("_"), *method_arguments
37
+ else
38
+ url_params = method_arguments.extract_options!
39
+ params = {}
40
+ method_arguments.each_with_index do |obj, i|
41
+ key = i == (method_arguments.size - 1) ?
42
+ :id :
43
+ (obj.is_a?(Array) ? "#{obj.first}_id".to_sym : "#{obj.class.name.underscore}_id".to_sym)
44
+ params.merge!((obj.is_a?(Array)) ? {key => obj[1].to_param} : {key => obj.to_param})
45
+ end
46
+
47
+ params.merge!(url_params)
48
+ send method_name_fragments.join("_"), params
49
+ end
50
+ end
51
+
52
+ # The point of this method is to replace any object if a url param is passed. For example:
53
+ #
54
+ # [:admin, [:user, user_object], {:user_id => 4}]
55
+ #
56
+ # The "user_object" should be replaced by user with id 4, since we are explicitly saying we want to use User.find(4).
57
+ # The last part is the url_params.
58
+ #
59
+ # This also pluralizes path names if the obj is nil. Example:
60
+ #
61
+ # [:user, nil]
62
+ #
63
+ # No param was passed to replace the nil object as in the example above, so it should be:
64
+ #
65
+ # :users
66
+ #
67
+ # This is needed for contextual development. Take modifying a resource from another, but a
68
+ # parent resource is not needed. For example:
69
+ #
70
+ # payments/credit_cards
71
+ #
72
+ # You can manage and select a credit card from the credit cards resource but a payment object
73
+ # is not needed. In a sense you are just creating a "payments" context.
74
+ def cleanup_url_parts(url_parts)
75
+ url_parts = url_parts.compact
76
+ url_params = url_parts.last.is_a?(Hash) ? url_parts.last : {}
77
+ new_url_parts = []
78
+
79
+ url_parts.each do |object|
80
+ if !object.is_a?(Array)
81
+ # It's not an array, just copy it over
82
+ new_url_parts << object
83
+ else
84
+ # Let's try to
85
+ klass = object.first.to_s.camelize.constantize rescue nil
86
+ #klass_name = klass ? klass.name.underscore : nil
87
+ params_key = "#{object.first}_id".to_sym
88
+ obj = if url_params.key?(params_key)
89
+ (!klass && url_params[params_key]) || (url_params[params_key] && klass.find(url_params.delete(params_key)))
90
+ else
91
+ object[1]
92
+ end
93
+ new_url_parts << [object.first, obj]
94
+ #new_url_parts << (obj.nil? ? object.first.to_s.pluralize.to_sym : [object.first, obj])
95
+ end
96
+ end
97
+ new_url_parts
98
+ end
99
+
100
+ def extract_method_name_fragments(url_parts)
101
+ fragments = url_parts.collect do |obj|
102
+ if obj.is_a?(Symbol)
103
+ obj
104
+ elsif obj.is_a?(Array)
105
+ obj.first
106
+ elsif !obj.is_a?(Hash)
107
+ obj.class.name.underscore.to_sym
108
+ end
109
+ end
110
+ fragments.compact
111
+ end
112
+
113
+ def extract_method_arguments(url_parts)
114
+ url_parts.flatten.select { |obj| !obj.is_a?(Symbol) }
115
+ end
116
+
117
+ def method_missing(method, *args, &block)
118
+ if method.to_s =~ /^((.*)_)?(child_collection|parent_collection|sibling|sibling_collection)_(path|url)$/ || method.to_s =~ /^((.*)_)?(child|collection|object|parent)_(path|url)$/
119
+ action = $2.blank? ? nil : $2.to_sym
120
+ target = $3
121
+ url_type = $4
122
+ send("smart_#{url_type}", *send("#{target}_url_parts", action, *args))
123
+ else
124
+ super
125
+ end
126
+ end
127
+ end
128
+ end