josevalim-inherited_resources 0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +4 -0
- data/MIT-LICENSE +21 -0
- data/README +362 -0
- data/Rakefile +19 -0
- data/init.rb +1 -0
- data/lib/inherited_resources.rb +4 -0
- data/lib/inherited_resources/base.rb +272 -0
- data/lib/inherited_resources/base_helpers.rb +199 -0
- data/lib/inherited_resources/belongs_to.rb +227 -0
- data/lib/inherited_resources/belongs_to_helpers.rb +89 -0
- data/lib/inherited_resources/class_methods.rb +155 -0
- data/lib/inherited_resources/polymorphic_helpers.rb +19 -0
- data/lib/inherited_resources/respond_to.rb +324 -0
- data/lib/inherited_resources/singleton_helpers.rb +53 -0
- data/lib/inherited_resources/url_helpers.rb +147 -0
- data/test/aliases_test.rb +71 -0
- data/test/base_helpers_test.rb +130 -0
- data/test/base_test.rb +219 -0
- data/test/belongs_to_base_test.rb +268 -0
- data/test/belongs_to_test.rb +109 -0
- data/test/class_methods_test.rb +73 -0
- data/test/fixtures/en.yml +9 -0
- data/test/nested_belongs_to_test.rb +138 -0
- data/test/polymorphic_base_test.rb +282 -0
- data/test/respond_to_test.rb +282 -0
- data/test/singleton_base_test.rb +226 -0
- data/test/test_helper.rb +37 -0
- data/test/url_helpers_test.rb +284 -0
- data/test/views/cities/edit.html.erb +1 -0
- data/test/views/cities/index.html.erb +1 -0
- data/test/views/cities/new.html.erb +1 -0
- data/test/views/cities/show.html.erb +1 -0
- data/test/views/comments/edit.html.erb +1 -0
- data/test/views/comments/index.html.erb +1 -0
- data/test/views/comments/new.html.erb +1 -0
- data/test/views/comments/show.html.erb +1 -0
- data/test/views/employees/edit.html.erb +1 -0
- data/test/views/employees/index.html.erb +1 -0
- data/test/views/employees/new.html.erb +1 -0
- data/test/views/employees/show.html.erb +1 -0
- data/test/views/managers/edit.html.erb +1 -0
- data/test/views/managers/new.html.erb +1 -0
- data/test/views/managers/show.html.erb +1 -0
- data/test/views/pets/edit.html.erb +1 -0
- data/test/views/professors/edit.html.erb +1 -0
- data/test/views/professors/index.html.erb +1 -0
- data/test/views/professors/new.html.erb +1 -0
- data/test/views/professors/show.html.erb +1 -0
- data/test/views/projects/index.html.erb +1 -0
- data/test/views/projects/respond_to_with_resource.html.erb +1 -0
- data/test/views/students/edit.html.erb +1 -0
- data/test/views/students/new.html.erb +1 -0
- data/test/views/users/edit.html.erb +1 -0
- data/test/views/users/index.html.erb +1 -0
- data/test/views/users/new.html.erb +1 -0
- data/test/views/users/show.html.erb +1 -0
- metadata +108 -0
@@ -0,0 +1,199 @@
|
|
1
|
+
module InheritedResources #:nodoc:
|
2
|
+
module BaseHelpers #:nodoc:
|
3
|
+
|
4
|
+
# Protected helpers. You might want to overwrite some of them.
|
5
|
+
protected
|
6
|
+
# This is how the collection is loaded.
|
7
|
+
#
|
8
|
+
# You might want to overwrite this method if you want to add pagination
|
9
|
+
# for example. When you do that, don't forget to cache the result in an
|
10
|
+
# instance_variable:
|
11
|
+
#
|
12
|
+
# def collection
|
13
|
+
# @projects ||= end_of_association_chain.paginate(params[:page]).all
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
def collection
|
17
|
+
get_collection_ivar || set_collection_ivar(end_of_association_chain.find(:all))
|
18
|
+
end
|
19
|
+
|
20
|
+
# This is how the resource is loaded.
|
21
|
+
#
|
22
|
+
# You might want to overwrite this method when you are using permalink.
|
23
|
+
# When you do that, don't forget to cache the result in an
|
24
|
+
# instance_variable:
|
25
|
+
#
|
26
|
+
# def resource
|
27
|
+
# @project ||= end_of_association_chain.find_by_permalink!(params[:id])
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# You also might want to add the exclamation mark at the end of the method
|
31
|
+
# because it will raise a 404 if nothing can be found. Otherwise it will
|
32
|
+
# probably render a 500 error message.
|
33
|
+
#
|
34
|
+
def resource
|
35
|
+
get_resource_ivar || set_resource_ivar(end_of_association_chain.find(params[:id]))
|
36
|
+
end
|
37
|
+
|
38
|
+
# This method is responsable for building the object on :new and :create
|
39
|
+
# methods. You probably won't need to change it. Again, if you overwrite
|
40
|
+
# don't forget to cache the result in an instance_variable.
|
41
|
+
#
|
42
|
+
def build_resource(attributes = {})
|
43
|
+
get_resource_ivar || set_resource_ivar(end_of_association_chain.send(method_for_build, attributes))
|
44
|
+
end
|
45
|
+
|
46
|
+
# This class allows you to set a instance variable to begin your
|
47
|
+
# association chain. For example, usually your projects belongs to users
|
48
|
+
# and that means that they belong to the current logged in user. So you
|
49
|
+
# could do this:
|
50
|
+
#
|
51
|
+
# def begin_of_association_chain
|
52
|
+
# @current_user
|
53
|
+
# end
|
54
|
+
#
|
55
|
+
# So every time we instantiate a project, we will do:
|
56
|
+
#
|
57
|
+
# @current_user.projects.build(params[:project])
|
58
|
+
# @current_user.projects.find(params[:id])
|
59
|
+
#
|
60
|
+
# The variable set in begin_of_association_chain is not sent when building
|
61
|
+
# urls, so this is never going to happen:
|
62
|
+
#
|
63
|
+
# project_url(@current_user, @project)
|
64
|
+
#
|
65
|
+
# If the user actually scopes the url, you should user belongs_to method
|
66
|
+
# and declare that projects belong to user.
|
67
|
+
#
|
68
|
+
def begin_of_association_chain
|
69
|
+
nil
|
70
|
+
end
|
71
|
+
|
72
|
+
# Private helpers, you probably don't have to worry with them.
|
73
|
+
private
|
74
|
+
|
75
|
+
# Fast accessor to resource_collection_name
|
76
|
+
#
|
77
|
+
def resource_collection_name
|
78
|
+
resources_configuration[:self][:collection_name]
|
79
|
+
end
|
80
|
+
|
81
|
+
# Fast accessor to resource_instance_name
|
82
|
+
#
|
83
|
+
def resource_instance_name
|
84
|
+
resources_configuration[:self][:instance_name]
|
85
|
+
end
|
86
|
+
|
87
|
+
# Returns if the object has a parent. This means, if it has an object
|
88
|
+
# set at begin_of_association_chain is not nil.
|
89
|
+
#
|
90
|
+
def parent?
|
91
|
+
!begin_of_association_chain.nil?
|
92
|
+
end
|
93
|
+
|
94
|
+
# This methods gets your begin_of_association_chain and returns the
|
95
|
+
# scoped association.
|
96
|
+
#
|
97
|
+
def end_of_association_chain
|
98
|
+
if parent?
|
99
|
+
begin_of_association_chain.send(resource_collection_name)
|
100
|
+
else
|
101
|
+
resource_class
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# Returns the appropriated method to build the resource.
|
106
|
+
#
|
107
|
+
def method_for_build
|
108
|
+
parent? ? :build : :new
|
109
|
+
end
|
110
|
+
|
111
|
+
# Get resource ivar based on the current resource controller.
|
112
|
+
#
|
113
|
+
def get_resource_ivar
|
114
|
+
instance_variable_get("@#{resource_instance_name}")
|
115
|
+
end
|
116
|
+
|
117
|
+
# Set resource ivar based on the current resource controller.
|
118
|
+
#
|
119
|
+
def set_resource_ivar(resource)
|
120
|
+
instance_variable_set("@#{resource_instance_name}", resource)
|
121
|
+
end
|
122
|
+
|
123
|
+
# Get collection ivar based on the current resource controller.
|
124
|
+
#
|
125
|
+
def get_collection_ivar
|
126
|
+
instance_variable_get("@#{resource_collection_name}")
|
127
|
+
end
|
128
|
+
|
129
|
+
# Set collection ivar based on the current resource controller.
|
130
|
+
#
|
131
|
+
def set_collection_ivar(collection)
|
132
|
+
instance_variable_set("@#{resource_collection_name}", collection)
|
133
|
+
end
|
134
|
+
|
135
|
+
# Helper to set flash messages. It's powered by I18n API.
|
136
|
+
# It checks for messages in the following order:
|
137
|
+
#
|
138
|
+
# flash.controller_name.action_name.status
|
139
|
+
# flash.actions.action_name.status
|
140
|
+
#
|
141
|
+
# If none is available, a default message is set. So, if you have
|
142
|
+
# a CarsController, create action, it will check for:
|
143
|
+
#
|
144
|
+
# flash.cars.create.status
|
145
|
+
# flash.actions.create.status
|
146
|
+
#
|
147
|
+
# The statuses can be :notice (when the object can be created, updated
|
148
|
+
# or destroyed with success) or :error (when the objecy cannot be created
|
149
|
+
# or updated).
|
150
|
+
#
|
151
|
+
# Those messages are interpolated by using the resource class human name.
|
152
|
+
# This means you can set:
|
153
|
+
#
|
154
|
+
# flash:
|
155
|
+
# actions:
|
156
|
+
# create:
|
157
|
+
# notice: "Hooray! {{resource}} was successfully created!"
|
158
|
+
#
|
159
|
+
# But sometimes, flash messages are not that simple. Going back
|
160
|
+
# to cars example, you might want to say the brand of the car when it's
|
161
|
+
# updated. Well, that's easy also:
|
162
|
+
#
|
163
|
+
# flash:
|
164
|
+
# cars:
|
165
|
+
# update:
|
166
|
+
# notice: "Hooray! You just tuned your {{car_brand}}!"
|
167
|
+
#
|
168
|
+
# Since :car_name is not available for interpolation by default, you have
|
169
|
+
# to overwrite interpolation_options.
|
170
|
+
#
|
171
|
+
# def interpolation_options
|
172
|
+
# { :car_brand => @car.brand }
|
173
|
+
# end
|
174
|
+
#
|
175
|
+
# Then you will finally have:
|
176
|
+
#
|
177
|
+
# 'Hooray! You just tuned your Aston Martin!'
|
178
|
+
#
|
179
|
+
def set_flash_message!(status, default_message = '')
|
180
|
+
options = {
|
181
|
+
:default => [ :"flash.actions.#{action_name}.#{status}", default_message ],
|
182
|
+
:resource => resource_class.human_name
|
183
|
+
}.merge(interpolation_options)
|
184
|
+
|
185
|
+
message = I18n.t "flash.#{controller_name}.#{action_name}.#{status}", options
|
186
|
+
|
187
|
+
flash[status] = message unless message.blank?
|
188
|
+
end
|
189
|
+
|
190
|
+
# Overwrite this method to provide other interpolation options when
|
191
|
+
# the flash message is going to be set. Check set_flash_message! for
|
192
|
+
# more information.
|
193
|
+
#
|
194
|
+
def interpolation_options
|
195
|
+
{ }
|
196
|
+
end
|
197
|
+
|
198
|
+
end
|
199
|
+
end
|
@@ -0,0 +1,227 @@
|
|
1
|
+
# = belongs_to
|
2
|
+
#
|
3
|
+
# This allows you to specify to belongs_to in your controller. You might use
|
4
|
+
# this when you are having nested resources in your routes:
|
5
|
+
#
|
6
|
+
# class TasksController < InheritedResources::Base
|
7
|
+
# belongs_to :project
|
8
|
+
# end
|
9
|
+
#
|
10
|
+
# This will do all magic assuming some defaults. It assumes that your URL to
|
11
|
+
# access those tasks are:
|
12
|
+
#
|
13
|
+
# /projects/:project_id/tasks
|
14
|
+
#
|
15
|
+
# But all defaults are configurable. The options are:
|
16
|
+
#
|
17
|
+
# * :parent_class => Allows you to specify what is the parent class.
|
18
|
+
#
|
19
|
+
# belongs_to :project, :parent_class => AdminProject
|
20
|
+
#
|
21
|
+
# * :class_name => Also allows you to specify the parent class, but you should
|
22
|
+
# give a string. Added for ActiveRecord belongs to compatibility.
|
23
|
+
#
|
24
|
+
# * :instance_name => How this object will appear in your views. In this case
|
25
|
+
# the default is @project. Overwrite it with a symbol.
|
26
|
+
#
|
27
|
+
# belongs_to :project, :instance_name => :my_project
|
28
|
+
#
|
29
|
+
# * :finder => Specifies which method should be called to instantiate the
|
30
|
+
# parent. Let's suppose you are using slugs ("this-is-project-title") in URLs
|
31
|
+
# so your tasks url would be: "projects/this-is-project-title/tasks". Then you
|
32
|
+
# should do this in your TasksController:
|
33
|
+
#
|
34
|
+
# belongs_to :project, :finder => :find_by_title!
|
35
|
+
#
|
36
|
+
# This will make your projects be instantiated as:
|
37
|
+
#
|
38
|
+
# Project.find_by_title!(params[:project_id])
|
39
|
+
#
|
40
|
+
# Instead of:
|
41
|
+
#
|
42
|
+
# Project.find(params[:project_id])
|
43
|
+
#
|
44
|
+
# * param => Allows you to specify params key used to instantiate the parent.
|
45
|
+
# Default is :parent_id, which in this case is :project_id.
|
46
|
+
#
|
47
|
+
# * route_name => Allows you to specify what is the route name in your url
|
48
|
+
# helper. By default is 'project'. But if your url helper should be
|
49
|
+
# "admin_project_task_url" instead of "project_task_url", just do:
|
50
|
+
#
|
51
|
+
# belongs_to :project, :route_name => "admin_project"
|
52
|
+
#
|
53
|
+
# = nested_belongs_to
|
54
|
+
#
|
55
|
+
# If for some reason you need to nested more than two resources, you can do:
|
56
|
+
#
|
57
|
+
# class TasksController
|
58
|
+
# belongs_to :company, :project
|
59
|
+
# end
|
60
|
+
#
|
61
|
+
# ATTENTION! This DOES NOT mean polymorphic associations as in resource_controller.
|
62
|
+
# Polymorphic associations are not supported yet.
|
63
|
+
#
|
64
|
+
# It means that companies have many projects which have many tasks. You URL
|
65
|
+
# should be:
|
66
|
+
#
|
67
|
+
# /companies/:company_id/projects/:project_id/tasks/:id
|
68
|
+
#
|
69
|
+
# Everything will be handled for you again. And all defaults will describe above
|
70
|
+
# will be assumed. But if you have to change the defaults. You will have to
|
71
|
+
# specify one association by one:
|
72
|
+
#
|
73
|
+
# class TasksController
|
74
|
+
# belongs_to :company, :finder => :find_by_name!, :param => :company_name
|
75
|
+
# belongs_to :project
|
76
|
+
# end
|
77
|
+
#
|
78
|
+
# belongs_to is aliased as nested_belongs_to, so this provides a nicer syntax:
|
79
|
+
#
|
80
|
+
# class TasksController
|
81
|
+
# nested_belongs_to :company, :finder => :find_by_name!, :param => :company_name
|
82
|
+
# nested_belongs_to :project
|
83
|
+
# end
|
84
|
+
#
|
85
|
+
# In this case the association chain would be:
|
86
|
+
#
|
87
|
+
# Company.find_by_name!(params[:company_name]).projects.find(params[:project_id]).tasks.find(:all)
|
88
|
+
#
|
89
|
+
# When you are using nested resources, you have one more option to config.
|
90
|
+
# Let's suppose that to get all projects from a company, you have to do:
|
91
|
+
#
|
92
|
+
# Company.admin_projects
|
93
|
+
#
|
94
|
+
# Instead of:
|
95
|
+
#
|
96
|
+
# Company.projects
|
97
|
+
#
|
98
|
+
# In this case, you can set the collection_name in belongs_to:
|
99
|
+
#
|
100
|
+
# nested_belongs_to :project, :collection_name => 'admin_projects'
|
101
|
+
#
|
102
|
+
# = polymorphic associations
|
103
|
+
#
|
104
|
+
# In some cases you have a resource that belongs to two different resources
|
105
|
+
# but not at the same time. For example, let's suppose you have File, Message
|
106
|
+
# and Task as resources and they are all commentable.
|
107
|
+
#
|
108
|
+
# Polymorphic associations allows you to create just one controller that will
|
109
|
+
# deal with each case.
|
110
|
+
#
|
111
|
+
# class Comment < InheritedResources::Base
|
112
|
+
# belongs_to :file, :message, :task, :polymorphic => true
|
113
|
+
# end
|
114
|
+
#
|
115
|
+
# Your routes should be something like:
|
116
|
+
#
|
117
|
+
# m.resources :files, :has_many => :comments #=> /files/13/comments
|
118
|
+
# m.resources :tasks, :has_many => :comments #=> /tasks/17/comments
|
119
|
+
# m.resources :messages, :has_many => :comments #=> /messages/11/comments
|
120
|
+
#
|
121
|
+
# When using polymorphic associations, you get some free helpers:
|
122
|
+
#
|
123
|
+
# parent? #=> true
|
124
|
+
# parent_type #=> :task
|
125
|
+
# parent_class #=> Task
|
126
|
+
# parent_instance #=> @task
|
127
|
+
#
|
128
|
+
# This polymorphic controllers thing is a great idea by James Golick and he
|
129
|
+
# built it in resource_controller. Here is just a re-implementation.
|
130
|
+
#
|
131
|
+
# = nested polymorphic associations
|
132
|
+
#
|
133
|
+
# You can have polymorphic associations with nested resources. Let's suppose
|
134
|
+
# that our File, Task and Message resources in the previous example belongs to
|
135
|
+
# a project.
|
136
|
+
#
|
137
|
+
# This way we can have:
|
138
|
+
#
|
139
|
+
# class Comment < InheritedResources::Base
|
140
|
+
# belongs_to :project {
|
141
|
+
# belongs_to :file, :message, :task, :polymorphic => true
|
142
|
+
# }
|
143
|
+
# end
|
144
|
+
#
|
145
|
+
# Or:
|
146
|
+
#
|
147
|
+
# class Comment < InheritedResources::Base
|
148
|
+
# nested_belongs_to :project
|
149
|
+
# nested_belongs_to :file, :message, :task, :polymorphic => true
|
150
|
+
# end
|
151
|
+
#
|
152
|
+
# Choose the syntax that makes more sense to you. :)
|
153
|
+
#
|
154
|
+
# Finally your routes should be something like:
|
155
|
+
#
|
156
|
+
# map.resources :projects do |m|
|
157
|
+
# m.resources :files, :has_many => :comments #=> /projects/1/files/13/comments
|
158
|
+
# m.resources :tasks, :has_many => :comments #=> /projects/1/tasks/17/comments
|
159
|
+
# m.resources :messages, :has_many => :comments #=> /projects/1/messages/11/comments
|
160
|
+
# end
|
161
|
+
#
|
162
|
+
# The helpers work in the same way as above.
|
163
|
+
#
|
164
|
+
# = singleton
|
165
|
+
#
|
166
|
+
# If you have singleton resources, in other words, if your controller resource
|
167
|
+
# associates to another through a has_one association, you can pass the option
|
168
|
+
# :singleton to it. It will deal with all the details and automacally remove
|
169
|
+
# the :index action.
|
170
|
+
#
|
171
|
+
# class ManagersController < InheritedResources::Base
|
172
|
+
# belongs_to :project, :singleton => true # a project has one manager
|
173
|
+
# end
|
174
|
+
#
|
175
|
+
module InheritedResources #:nodoc:
|
176
|
+
module BelongsTo #:nodoc:
|
177
|
+
|
178
|
+
protected
|
179
|
+
def belongs_to(*symbols, &block)
|
180
|
+
options = symbols.extract_options!
|
181
|
+
|
182
|
+
options.symbolize_keys!
|
183
|
+
options.assert_valid_keys(:class_name, :parent_class, :instance_name, :param, :finder, :route_name, :collection_name, :singleton, :polymorphic)
|
184
|
+
|
185
|
+
acts_as_singleton! if singleton = options.delete(:singleton)
|
186
|
+
acts_as_polymorphic! if polymorphic = options.delete(:polymorphic)
|
187
|
+
|
188
|
+
raise ArgumentError, 'You have to give me at least one association name.' if symbols.empty?
|
189
|
+
raise ArgumentError, 'You cannot define multiple associations with the options: #{options.keys.inspect}.' unless symbols.size == 1 || options.empty?
|
190
|
+
|
191
|
+
# Add BelongsToHelpers if we haven't yet.
|
192
|
+
include BelongsToHelpers if self.parents_symbols.empty?
|
193
|
+
|
194
|
+
# Set configuration default values
|
195
|
+
symbols.each do |symbol|
|
196
|
+
symbol = symbol.to_sym
|
197
|
+
|
198
|
+
if polymorphic
|
199
|
+
self.parents_symbols << :polymorphic unless self.parents_symbols.include? :polymorphic
|
200
|
+
self.polymorphic_symbols << symbol
|
201
|
+
else
|
202
|
+
self.parents_symbols << symbol
|
203
|
+
end
|
204
|
+
|
205
|
+
config = self.resources_configuration[symbol] = {}
|
206
|
+
config[:parent_class] = options.delete(:parent_class)
|
207
|
+
config[:parent_class] ||= (options.delete(:class_name) || symbol).to_s.classify.constantize rescue nil
|
208
|
+
config[:collection_name] = (options.delete(:collection_name) || symbol.to_s.pluralize).to_sym
|
209
|
+
config[:instance_name] = (options.delete(:instance_name) || symbol).to_sym
|
210
|
+
config[:param] = (options.delete(:param) || "#{symbol}_id").to_sym
|
211
|
+
config[:finder] = (options.delete(:finder) || :find).to_sym
|
212
|
+
config[:route_name] = (options.delete(:route_name) || symbol).to_s
|
213
|
+
config[:polymorphic] = polymorphic
|
214
|
+
end
|
215
|
+
|
216
|
+
# Regenerate url helpers unless block is given
|
217
|
+
if block_given?
|
218
|
+
class_eval(&block)
|
219
|
+
else
|
220
|
+
InheritedResources::UrlHelpers.create_resources_url_helpers!(self)
|
221
|
+
end
|
222
|
+
end
|
223
|
+
alias :nested_belongs_to :belongs_to
|
224
|
+
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module InheritedResources #:nodoc:
|
2
|
+
module BelongsToHelpers #:nodoc:
|
3
|
+
|
4
|
+
# Private helpers, you probably don't have to worry with them.
|
5
|
+
private
|
6
|
+
|
7
|
+
# Overwrites the parent? method defined in base_helpers.rb.
|
8
|
+
# This one always returns true since it's added when associations
|
9
|
+
# are defined.
|
10
|
+
#
|
11
|
+
def parent?
|
12
|
+
true
|
13
|
+
end
|
14
|
+
|
15
|
+
# Evaluate the parent given. This is used to nest parents in the
|
16
|
+
# association chain.
|
17
|
+
#
|
18
|
+
def evaluate_parent(parent_config, chain = nil)
|
19
|
+
scoped_parent = if chain
|
20
|
+
chain.send(parent_config[:collection_name])
|
21
|
+
else
|
22
|
+
parent_config[:parent_class]
|
23
|
+
end
|
24
|
+
|
25
|
+
scoped_parent = scoped_parent.send(parent_config[:finder], params[parent_config[:param]])
|
26
|
+
|
27
|
+
instance_variable_set("@#{parent_config[:instance_name]}", scoped_parent)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Overwrites the end_of_association_chain method.
|
31
|
+
#
|
32
|
+
# This methods gets your begin_of_association_chain, join it with your
|
33
|
+
# parents chain and returns the scoped association.
|
34
|
+
#
|
35
|
+
def end_of_association_chain
|
36
|
+
return resource_class unless parent?
|
37
|
+
|
38
|
+
chain = symbols_for_chain.inject(begin_of_association_chain) do |chain, symbol|
|
39
|
+
evaluate_parent(resources_configuration[symbol], chain)
|
40
|
+
end
|
41
|
+
|
42
|
+
chain = chain.send(method_for_association_chain) if method_for_association_chain
|
43
|
+
|
44
|
+
return chain
|
45
|
+
end
|
46
|
+
|
47
|
+
# If current controller is singleton, returns instance name to
|
48
|
+
# end_of_association_chain. This means that we will have the following
|
49
|
+
# chain:
|
50
|
+
#
|
51
|
+
# Project.find(params[:project_id]).manager
|
52
|
+
#
|
53
|
+
# Instead of:
|
54
|
+
#
|
55
|
+
# Project.find(params[:project_id]).managers
|
56
|
+
#
|
57
|
+
def method_for_association_chain
|
58
|
+
singleton ? nil : resource_collection_name
|
59
|
+
end
|
60
|
+
|
61
|
+
# Maps parents_symbols to build association chain.
|
62
|
+
#
|
63
|
+
# If the parents_symbols find :polymorphic, it goes through the
|
64
|
+
# params keys to see which polymorphic parent matches the given params.
|
65
|
+
#
|
66
|
+
def symbols_for_chain
|
67
|
+
parents_symbols.map do |symbol|
|
68
|
+
if symbol == :polymorphic
|
69
|
+
params_keys = params.keys
|
70
|
+
|
71
|
+
key = polymorphic_symbols.find do |poly|
|
72
|
+
params_keys.include? resources_configuration[poly][:param].to_s
|
73
|
+
end
|
74
|
+
|
75
|
+
raise ScriptError, "Could not find param for polymorphic association.
|
76
|
+
The request params keys are #{params.keys.inspect}
|
77
|
+
and the polymorphic associations are
|
78
|
+
#{polymorphic_symbols.inspect}." if key.nil?
|
79
|
+
|
80
|
+
instance_variable_set('@parent_type', key.to_sym)
|
81
|
+
else
|
82
|
+
symbol
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|