resourcelogic 0.0.12 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,13 +3,11 @@ module Resourcelogic # :nodoc:
3
3
  def self.included(klass)
4
4
  klass.class_eval do
5
5
  extend ClassMethods
6
- include InstanceMethods
7
6
  end
8
7
  end
9
8
 
10
9
  module ClassMethods
11
10
  def acts_as_resource(&block)
12
- resourceful(true)
13
11
  yield self if block_given?
14
12
  acts_as_resource_modules.each { |mod| include mod }
15
13
  init_default_actions
@@ -67,21 +65,13 @@ module Resourcelogic # :nodoc:
67
65
  acts_as_resource_modules
68
66
  end
69
67
 
70
- def resourceful(value = nil)
71
- rw_config(:resourceful, value, false)
72
- end
73
-
74
- def resourceful?
75
- resourceful == true
76
- end
77
-
78
68
  private
79
69
  def acts_as_resource_modules
80
70
  key = :acts_as_resource_modules
81
71
  inheritable_attributes.include?(key) ? read_inheritable_attribute(key) : []
82
72
  end
83
73
 
84
- def rw_config(key, value, default_value = nil, read_value = nil)
74
+ def config(key, value, default_value = nil, read_value = nil)
85
75
  if value == read_value
86
76
  inheritable_attributes.include?(key) ? read_inheritable_attribute(key) : default_value
87
77
  else
@@ -89,21 +79,6 @@ module Resourcelogic # :nodoc:
89
79
  end
90
80
  end
91
81
  end
92
-
93
- module InstanceMethods
94
- def self.included(klass)
95
- klass.helper_method :resourceful?, :section
96
- end
97
-
98
- def resourceful?
99
- self.class.resourceful?
100
- end
101
-
102
- def section
103
- section = request.path.split("/")[1]
104
- section && section.to_sym
105
- end
106
- end
107
82
  end
108
83
  end
109
84
 
@@ -115,16 +90,11 @@ if defined?(::ActionController)
115
90
  include Resourcelogic::Actions
116
91
  include Resourcelogic::Child
117
92
  include Resourcelogic::Context
118
- include Resourcelogic::Scope
93
+ include Resourcelogic::Parent
119
94
  include Resourcelogic::Self
120
95
  include Resourcelogic::Sibling
121
- include Resourcelogic::SubViews
96
+ include Resourcelogic::Singleton
122
97
  include Resourcelogic::Urligence
123
-
124
- # Need to be loaded last to override methods
125
- include Resourcelogic::Parent
126
- include Resourcelogic::Aliases
127
- include Resourcelogic::Singleton
128
98
  end
129
99
  end
130
100
  end
@@ -7,49 +7,89 @@ module Resourcelogic
7
7
  end
8
8
 
9
9
  module Urls
10
+ def self.included(klass)
11
+ klass.helper_method :new_child_url, :new_child_path, :edit_child_url, :edit_child_path,
12
+ :child_url, :child_path, :child_collection_url, :child_collection_path
13
+ end
14
+
10
15
  private
16
+ def new_child_url(child_name, url_params = {})
17
+ smart_url *new_child_url_options(child_name, url_params)
18
+ end
19
+
20
+ def new_child_path(child_name, url_params = {})
21
+ smart_path *new_child_url_options(child_name, url_params)
22
+ end
23
+
24
+ def edit_child_url(child, url_params = {})
25
+ smart_url *child_url_options(child, :edit, url_params)
26
+ end
27
+
28
+ def edit_child_path(child, url_params = {})
29
+ smart_path *child_url_options(child, :edit, url_params)
30
+ end
31
+
32
+ def child_url(child, url_params = {})
33
+ smart_url *child_url_options(child, url_params)
34
+ end
35
+
11
36
  # The following should work
12
37
  #
13
38
  # child_path(obj)
14
39
  # child_path(obj, :id => 2) # where obj is then replaced by the obj with id 2
15
40
  # child_path(:child_name, :id => 2) # where this is a literal build of the url
16
- def child_url_parts(action = nil, child = nil, url_params = {})
17
- child_base_parts(action, url_params) + [[child.is_a?(Symbol) ? child : child.class.name.underscore.to_sym, child], url_params]
41
+ def child_path(child, url_params = {})
42
+ smart_path *child_url_options(child, url_params)
18
43
  end
19
44
 
20
- def child_collection_url_parts(action = nil, child_name = nil, url_params = {})
21
- child_base_parts(action, url_params) + [child_name, url_params]
45
+ def child_collection_url(child_name, url_params = {})
46
+ smart_url *child_collection_url_options(child_name, url_params)
22
47
  end
23
48
 
24
- # This determines if the child if off of an object or the collection. Most of the time,
25
- # as assumed, it will be off of an object. But let's say you are at this url:
26
- #
27
- # /payments
28
- #
29
- # And you call this path:
30
- #
31
- # child_collection(:credit_cards)
32
- #
33
- # There is no object to be a child off, we are in the collection / index action. But
34
- # we still want to call the following url:
35
- #
36
- # /payments/credit_cards
37
- #
38
- # That's what this method does, it makes the above possible. So you can still link
39
- # to the "child" credit cards resource relatively, keeping the idea of contextual
40
- # development intact. Maybe you only want to use payments as a context for the
41
- # credit cards resource.
42
- def child_base_parts(action, url_params)
43
- object_to_use = (url_params.key?("#{model_name}_id".to_sym) && url_params["#{model_name}_id".to_sym]) || (id? && object)
44
- base_parts = object_to_use || singleton? ? object_url_parts(action, object_to_use) : collection_url_parts(action)
45
- base_parts.pop if base_parts.last.is_a?(Hash)
46
- base_parts
47
- end
48
-
49
- #def current_object_to_use(url_params)
50
- # result = (url_params.key?("#{model_name}_id".to_sym) && url_params["#{model_name}_id".to_sym]) || (id? && object)
51
- # result ? result : nil
52
- #end
49
+ def child_collection_path(child_name, url_params = {})
50
+ smart_path *child_collection_url_options(child_name, url_params)
51
+ end
52
+
53
+ def new_child_url_options(child_name, url_params = {})
54
+ object_url_options(:new) + [child_name, url_params]
55
+ end
56
+
57
+ def child_url_options(child, *action_prefix_or_params)
58
+ action_prefix, url_params = identify_action_prefix_or_params(action_prefix_or_params)
59
+ object_url_options(action_prefix) + [[child.is_a?(Symbol) ? child : child.class.name.underscore.to_sym, child], url_params]
60
+ end
61
+
62
+ def child_collection_url_options(child_name, url_params = {})
63
+ object_url_options + [child_name, url_params]
64
+ end
65
+
66
+ def find_object_for_child(url_params = {})
67
+ key = "#{model_name}_id".to_sym
68
+ url_params.key?(key) ? end_of_association_chain.find(url_params[key]) : object
69
+ end
70
+
71
+ def find_child_name(child)
72
+ name = args.first.class.name.underscore.to_sym
73
+ return name if model.reflect_on_association(name)
74
+
75
+ name = name.to_s.pluralize
76
+ end
77
+
78
+ def identify_action_prefix_or_params(action_prefix_or_params)
79
+ action_prefix_or_params = action_prefix_or_params.first if action_prefix_or_params.is_a?(Array) && action_prefix_or_params.size <= 1
80
+ action_prefix = nil
81
+ url_params = {}
82
+ case action_prefix_or_params
83
+ when Array
84
+ url_params = action_prefix_or_params.last if action_prefix_or_params.last.is_a?(Hash)
85
+ action_prefix = action_prefix_or_params.first
86
+ when Symbol
87
+ action_prefix = action_prefix_or_params
88
+ when Hash
89
+ url_params = action_prefix_or_params
90
+ end
91
+ [action_prefix, url_params]
92
+ end
53
93
  end
54
94
  end
55
95
  end
@@ -4,48 +4,85 @@ module Resourcelogic
4
4
  module Context
5
5
  def self.included(klass)
6
6
  klass.class_eval do
7
+ extend Config
7
8
  add_acts_as_resource_module(Methods)
8
9
  end
9
10
  end
10
11
 
12
+ module Config
13
+ def contextual_views(value = nil)
14
+ config(:contextual_views, value)
15
+ end
16
+
17
+ def contextual_views?
18
+ !contextual_views.blank?
19
+ end
20
+ end
21
+
11
22
  module Methods
12
23
  def self.included(klass)
13
- klass.helper_method :context, :contexts, :contexts_url_parts
14
- klass.hide_action :context, :contexts
24
+ klass.helper_method :context, :contexts, :contextual_views, :contextual_views?, :context_template_name
15
25
  end
16
26
 
17
- def context
18
- @context ||= contexts.last
19
- end
20
-
21
- def contexts
22
- return @contexts if defined?(@contexts)
23
- path_parts = request.path.split("/")
24
- path_parts.shift
25
- @contexts = []
26
- path_parts.each_with_index do |part, index|
27
- break if model_name_from_path_part(part.split(".").first) == model_name
28
- @contexts << (part.to_i > 0 ? @contexts.pop.to_s.singularize.to_sym : part.underscore.to_sym)
27
+ private
28
+ def context
29
+ @context ||= (parent? && (parent_alias || parent_model_name)) || (contexts.last && (contexts.last.is_a?(Array) ? contexts.last.first : contexts.last))
29
30
  end
30
- @contexts
31
- end
32
31
 
33
- private
34
- def contexts_url_parts
35
- return @contexts_url_parts if @contexts_url_parts
32
+ # Returns all of the current namespaces of the current controller, symbolized, in array form.
33
+ def contexts
34
+ return @contexts if @contexts
36
35
  path_parts = request.path.split("/")
37
36
  path_parts.shift
38
- @contexts_url_parts = []
37
+ @contexts = []
39
38
  path_parts.each_with_index do |part, index|
40
- break if model_name_from_path_part(part.split(".").first) == model_name
39
+ part = part.split(".").first if (index + 1) == path_parts.size # for formats: blah.html or blah.js
40
+ break if [(parent_alias || parent_model_name).to_s.pluralize, (parent_alias || parent_model_name).to_s, route_name.to_s.pluralize].include?(part.underscore)
41
41
  if part.to_i > 0
42
- @contexts_url_parts << [route_name_from_path_part(@contexts_url_parts.pop), part.to_i]
42
+ @contexts << [@contexts.pop.to_s.singularize.to_sym, part]
43
43
  else
44
- @contexts_url_parts << part.underscore.to_sym
44
+ @contexts << part.underscore.to_sym
45
45
  end
46
46
  end
47
- @contexts_url_parts
47
+ @contexts
48
+ end
49
+ alias_method :namespaces, :contexts
50
+
51
+ def contextual_views?
52
+ self.class.contextual_views?
53
+ end
54
+
55
+ def contextual_views
56
+ self.class.contextual_views
57
+ end
58
+
59
+ def context_template_name(name)
60
+ sub_folder = contextual_views.is_a?(Hash) && contextual_views.key?(context) ? contextual_views[context] : context
61
+ sub_folder ||= "root"
62
+ "#{controller_name}/#{sub_folder}/#{name}"
63
+ end
64
+
65
+ def default_template_name(action_name = self.action_name)
66
+ if contextual_views?
67
+ context_template_name(action_name)
68
+ else
69
+ super
70
+ end
48
71
  end
49
72
  end
73
+
74
+ module Partials
75
+ def _pick_partial_template(partial_path)
76
+ partial_path = context_template_name(partial_path) if respond_to?(:contextual_views?) && contextual_views? && !partial_path.include?("/")
77
+ super
78
+ end
79
+ end
80
+ end
81
+ end
82
+
83
+
84
+ module ActionView
85
+ class Base
86
+ include Resourcelogic::Context::Partials
50
87
  end
51
88
  end
@@ -17,125 +17,157 @@ module Resourcelogic
17
17
  @belongs_to[name.to_sym] = options
18
18
  end
19
19
  end
20
-
21
- def require_parent(value = nil)
22
- rw_config(:require_parent, value, false)
23
- end
24
20
  end
25
21
 
26
22
  module Urls
23
+ def self.included(klass)
24
+ klass.helper_method :new_parent_url, :new_parent_path, :edit_parent_url, :edit_parent_path, :parent_url, :parent_path,
25
+ :parent_collection_url, :parent_collection_path
26
+ end
27
+
27
28
  private
28
- def parent_url_parts(action = nil, url_params = {})
29
- [action] + contexts_url_parts + [url_params]
29
+ def new_parent_url(url_params = {})
30
+ smart_url *([:new] + namespaces + [parent_url_options, url_params])
31
+ end
32
+
33
+ def new_parent_path(url_params = {})
34
+ smart_path *([:new] + namespaces + [parent_url_options, url_params])
35
+ end
36
+
37
+ def edit_parent_url(url_params = {})
38
+ smart_url *([:edit] + namespaces + [parent_url_options, url_params])
39
+ end
40
+
41
+ def edit_parent_path(url_params = {})
42
+ smart_path *([:edit] + namespaces + [parent_url_options, url_params])
43
+ end
44
+
45
+ def parent_url(url_params = {})
46
+ smart_url *(namespaces + [parent_url_options, url_params])
30
47
  end
31
48
 
32
- def parent_collection_url_parts(*args)
33
- parent_url_parts(*args)
49
+ def parent_path(url_params = {})
50
+ smart_path *(namespaces + [parent_url_options, url_params])
51
+ end
52
+
53
+ def parent_collection_url(url_params = {})
54
+ smart_url *(namespaces + [parent_model_name.to_s.pluralize.to_sym, url_params])
55
+ end
56
+
57
+ def parent_collection_path(url_params = {})
58
+ smart_path *(namespaces + [parent_model_name.to_s.pluralize.to_sym, url_params])
59
+ end
60
+
61
+ def parent_url_options
62
+ if parent?
63
+ parent_name = (parent_alias || parent_model_name).to_sym
64
+ parent_singleton? ? parent_name : [parent_name, parent_object]
65
+ else
66
+ nil
67
+ end
34
68
  end
35
69
  end
36
70
 
37
71
  module Reflection
38
72
  def self.included(klass)
39
- klass.class_eval do
40
- helper_method :parent?, :parent_model_name, :parent_object
41
- before_filter :require_parent
42
- end
73
+ klass.helper_method :parent?, :parent_model_name, :parent_object
43
74
  end
44
75
 
45
76
  private
46
77
  def belongs_to
47
78
  self.class.belongs_to
48
79
  end
49
-
50
- def parent_path_name
51
- return @parent_path_name if defined?(@parent_path_name)
52
- path_parts = request.path.split("/")
53
- path_parts.reverse.each do |path_part|
54
- next if path_part.blank?
55
- if model_name_from_path_part(path_part) == parent_model_name
56
- return @parent_path_name = path_part.to_sym
57
- end
58
- end
59
- @parent_path_name = nil
80
+
81
+ # Returns the relevant association proxy of the parent. (i.e. /posts/1/comments # => @post.comments)
82
+ #
83
+ def parent_association
84
+ @parent_association ||= parent_object.send(model_name.to_s.pluralize.to_sym)
60
85
  end
61
-
62
- def parent_route_name
63
- return @parent_route_name if defined?(@parent_route_name)
64
- path_parts = request.path.split("/")
65
- path_parts.reverse.each do |path_part|
66
- next if path_part.blank?
67
- if model_name_from_path_part(path_part) == parent_model_name
68
- return @parent_route_name = route_name_from_path_part(path_part)
69
- end
70
- end
71
- @parent_route_name = parent_model_name
86
+
87
+ def parent_alias
88
+ return @parent_alias if @parent_alias
89
+ parent_from_params? || parent_from_request?
90
+ @parent_alias
72
91
  end
73
-
92
+
74
93
  # Returns the type of the current parent
75
94
  #
76
95
  def parent_model_name
77
- return @parent_model_name if defined?(@parent_model_name)
78
- parent_from_path?
96
+ return @parent_model_name if @parent_model_name
97
+ parent_from_params? || parent_from_request?
79
98
  @parent_model_name
80
99
  end
81
-
82
- def parent_model
83
- @parent_model ||= parent_model_name.to_s.camelize.constantize
100
+
101
+ # Returns the type of the current parent extracted from params
102
+ #
103
+ def parent_from_params?
104
+ return @parent_from_params if defined?(@parent_from_params)
105
+ belongs_to.each do |model_name, options|
106
+ if !params["#{model_name}_id".to_sym].nil?
107
+ @parent_model_name = model_name
108
+ @parent_alias = options[:as]
109
+ return @parent_from_params = true
110
+ end
111
+ end
112
+ @parent_from_params = false
84
113
  end
85
-
114
+
86
115
  # Returns the type of the current parent extracted form a request path
87
- #
88
- def parent_from_path?
89
- return @parent_from_path if defined?(@parent_from_path)
116
+ #
117
+ def parent_from_request?
118
+ return @parent_from_request if defined?(@parent_from_request)
90
119
  belongs_to.each do |model_name, options|
91
- request.path.split('/').reverse.each do |path_part|
92
- possible_model_names(model_name).each_with_index do |possible_name, index|
93
- if [possible_name.to_s, possible_name.to_s.pluralize].include?(path_part)
94
- @parent_model_name = model_name
95
- return @parent_from_path = true
96
- end
97
- end
120
+ if request.path.split('/').include?((options[:as] && options[:as].to_s) || model_name.to_s)
121
+ @parent_model_name = model_name
122
+ @parent_alias = options[:as]
123
+ return @parent_from_request = true
98
124
  end
99
125
  end
100
- @parent_from_path = false
126
+ @parent_from_request = false
101
127
  end
102
-
128
+
103
129
  # Returns true/false based on whether or not a parent is present.
104
130
  #
105
131
  def parent?
106
132
  !parent_model_name.nil?
107
133
  end
108
-
134
+
109
135
  # Returns true/false based on whether or not a parent is a singleton.
110
- #
136
+ #
111
137
  def parent_singleton?
112
- parent? && parent_id.nil?
138
+ !parent_from_params?
113
139
  end
114
-
140
+
115
141
  # Returns the current parent param, if there is a parent. (i.e. params[:post_id])
116
- def parent_id
117
- params["#{parent_route_name}_id".to_sym]
142
+ def parent_param
143
+ params["#{parent_model_name}_id".to_sym]
118
144
  end
119
-
145
+
146
+ # Like the model method, but for a parent relationship.
147
+ #
148
+ def parent_model
149
+ @parent_model ||= parent_model_name.to_s.camelize.constantize
150
+ end
151
+
120
152
  # Returns the current parent object if a parent object is present.
121
153
  #
122
- def parent_object(reload = false)
123
- return @parent_object if !reload && defined?(@parent_object)
154
+ def parent_object
155
+ return @parent_object if defined?(@parent_object)
124
156
  if parent?
125
157
  if parent_singleton? && respond_to?("current_#{parent_model_name}", true)
126
158
  @parent_object = send("current_#{parent_model_name}")
127
- elsif parent_singleton? && parent_scope.respond_to?(parent_model_name)
128
- @parent_object = parent_scope.send(parent_model_name, reload)
129
159
  else
130
- @parent_object = parent_scope.find(parent_id)
160
+ @parent_object = parent_model.find(parent_param)
131
161
  end
132
162
  else
133
163
  @parent_object = nil
134
164
  end
135
165
  end
136
-
137
- def require_parent
138
- raise StandardError.new("A parent is required to access this resource and no parent was found") if !parent? && self.class.require_parent == true
166
+
167
+ # If there is a parent, returns the relevant association proxy. Otherwise returns model.
168
+ #
169
+ def end_of_association_chain
170
+ parent? ? parent_association : model
139
171
  end
140
172
  end
141
173
  end