| Module | Resourceful::Default::Accessors |
| In: |
lib/resourceful/default/accessors.rb
|
This module contains all sorts of useful methods that allow access to the resources being worked with, metadata about the controller and action, and so forth.
Many of these accessors call other accessors and are called by the default make_resourceful actions. This means that overriding one method can affect everything else.
This can be dangerous, but it can also be very powerful. make_resourceful is designed to take advantage of overriding, so as long as the new methods accomplish the same purpose as the old ones, everything will just work. Even if you make a small mistake, it’s hard to break the controller in any unexpected ways.
For example, suppose your controller is called TagsController, but your model is called PhotoTag. All you have to do is override current_model_name:
def current_model_name
"PhotoTag"
end
Then current_model will return the PhotoTag model, current_object will call PhotoTag.find, and so forth.
Overriding current_objects and current_object is particularly useful for providing customized model lookup logic.
Creates a new object of the type of the current model with the current object’s parameters. current_object then returns this object for this action instead of looking up a new object.
Note that if this is a nested controller, the newly created object will automatically be a child of the current parent object.
# File lib/resourceful/default/accessors.rb, line 133
133: def build_object
134: @current_object = if current_model.respond_to? :build
135: current_model.build(object_parameters)
136: else
137: current_model.new(object_parameters)
138: end
139: end
The class of the current model. Note that if this is a nested controller, this instead returns the association object. For examle, in HatsController where Person has_many :hats,
current_model #=> Person.find(params[:person_id]).hats
This is useful because the association object uses duck typing to act like a model class. It supplies a find method that’s automatically scoped to ensure that the object returned is actually a child of the parent, and so forth.
# File lib/resourceful/default/accessors.rb, line 173
173: def current_model
174: if parent_objects.empty? || singular?
175: current_model_name.constantize
176: else
177: parent_objects[-1].send(instance_variable_name)
178: end
179: end
The string name of the current model. By default, this is derived from the name of the controller.
# File lib/resourceful/default/accessors.rb, line 143
143: def current_model_name
144: controller_name.singularize.camelize
145: end
Returns the object referenced by the id parameter (or the newly-created object for the new and create actions). For UsersController, it essentially runs User.find(params[:id]).
However, there are a few important differences. First, this method caches is results in the @current_objects instance variable. That way, multiple calls won’t run multiple queries.
Second, this method uses the current_model accessor, which provides a lot of flexibility (see the documentation for current_model for details).
Note that this is different for a singleton controller, where there’s only one resource per parent resource. Then this just returns that resource. For example, if Person has_one Hat, then in HatsController current_object essentially runs Person.find(params[:person_id]).hat.
# File lib/resourceful/default/accessors.rb, line 96
96: def current_object
97: @current_object ||= if plural?
98: if defined?(current_param)
99: STDERR.puts "DEPRECATION WARNING: \nThe make_resourceful #current_param accessor\nis deprecated and will be removed in 0.3.0.\nOverride #current_object instead.\n".gsub("\n", ' ')
100: return current_model.find(current_param)
101: end
102:
103: current_model.find(params[:id])
104: else
105: parent_objects[-1].send(instance_variable_name)
106: end
107: end
Returns an array of all the objects of the model corresponding to the controller. For UsersController, it essentially runs User.find(:all).
However, there are a few important differences. First, this method caches is results in the @current_objects instance variable. That way, multiple calls won’t run multiple queries.
Second, this method uses the current_model accessor, which provides a lot of flexibility (see the documentation for current_model for details).
# File lib/resourceful/default/accessors.rb, line 53
53: def current_objects
54: if defined?(model_includes)
55: STDERR.puts "DEPRECATION WARNING: \nThe make_resourceful #model_includes accessor\nis deprecated and will be removed in 0.3.0.\nOverride #current_objects instead.\n".gsub("\n", ' ')
56: @current_objects ||= current_model.find(:all, :includes => model_includes)
57: return @current_objects
58: end
59:
60: @current_objects ||= current_model.find(:all)
61: end
The name of the instance variable that load_object and load_objects should assign to.
# File lib/resourceful/default/accessors.rb, line 157
157: def instance_variable_name
158: controller_name
159: end
Calls current_object and stores the result in an instance variable named after the controller.
For example, in UsersController, calling load_object sets @user = current_object.
# File lib/resourceful/default/accessors.rb, line 122
122: def load_object
123: instance_variable_set("@#{instance_variable_name.singularize}", current_object)
124: end
Calls current_objects and stores the result in an instance variable named after the controller.
For example, in UsersController, calling load_objects sets @users = current_objects.
# File lib/resourceful/default/accessors.rb, line 75
75: def load_objects
76: instance_variable_set("@#{instance_variable_name}", current_objects)
77: end
Assigns each parent object, as given by parent_objects, to its proper instance variable, as given by parents.
# File lib/resourceful/default/accessors.rb, line 253
253: def load_parent_objects
254: parents.zip(parent_objects).map { |name, obj| instance_variable_set("@#{name}", obj) }
255: end
An array of namespaces under which the current controller is. For example, in Admin::Content::PagesController:
namespaces #=> [:admin, :content]
# File lib/resourceful/default/accessors.rb, line 152
152: def namespaces
153: @namespaces ||= self.class.name.split('::').slice(0...-1).map(&:underscore).map(&:to_sym)
154: end
Returns the hash passed as HTTP parameters that defines the new (or updated) attributes of the current object. This is only meaningful for create or update.
# File lib/resourceful/default/accessors.rb, line 185
185: def object_parameters
186: params[current_model_name.underscore]
187: end
Returns the names of the model classes of the parents of the current model. For example, in HatsController where Group has_many :people and Person has_many :hats,
parent_model_names #=> ["Group", "Person"]
Note that nesting must be declared via Builder#belongs_to.
# File lib/resourceful/default/accessors.rb, line 206
206: def parent_model_names
207: parents.map { |p| p.camelize }
208: end
Returns the model classes of the parents of the current model. For example, in HatsController where Group has_many :people and Person has_many :hats,
parent_models #=> [Group, Person]
Note that nesting must be declared via Builder#belongs_to.
# File lib/resourceful/default/accessors.rb, line 226
226: def parent_models
227: parent_model_names.map { |p| p.constantize }
228: end
Returns the parent objects for the current object. Note that nesting must be declared via Builder#belongs_to.
Note also that the results of this method are cached so that multiple calls don’t result in multiple SQL queries. In addition, each object except the first is scoped so that it’s guaranteed to be a child of its parent object.
# File lib/resourceful/default/accessors.rb, line 237
237: def parent_objects
238: return [] if parents.empty?
239: return @parent_objects if @parent_objects
240:
241: first = parent_models[0].find(parent_params[0])
242: @parent_objects = [first]
243: parent_params.zip(parents)[1..-1].inject(first) do |object, arr|
244: id, name = arr
245: @parent_objects << object.send(name.pluralize).find(id)
246: @parent_objects[-1]
247: end
248: @parent_objects
249: end
Returns the HTTP parameters designating the ids for the parent objects of the current model. For example, in HatsController where Group has_many :people and Person has_many :hats,
parent_params #=> [params[:group_id], params[:person_id]]
Note that nesting must be declared via Builder#belongs_to.
# File lib/resourceful/default/accessors.rb, line 216
216: def parent_params
217: parents.map { |p| params["#{p}_id"] }
218: end
Returns a list of the names of the parents of the current model. For a non-nested controller, this is []. For example, in HatsController where Group has_many :people and Person has_many :hats,
parents #=> ["group", "person"]
Note that nesting must be declared via Builder#belongs_to.
# File lib/resourceful/default/accessors.rb, line 196
196: def parents
197: self.class.read_inheritable_attribute :parents
198: end
Returns whether the controller is a normal plural controller, implying that there are multiple resources for each parent resource.
Note that the way this is determined is based on the singularity of the controller name, so it may yield false negatives for oddly-named controllers. If this is the case, the singular? method should be overridden.
# File lib/resourceful/default/accessors.rb, line 308
308: def plural?
309: !singular?
310: end
Returns whether or not the current action acts upon multiple objects. By default, the only such action is index.
# File lib/resourceful/default/accessors.rb, line 283
283: def plural_action?
284: PLURAL_ACTIONS.include?(params[:action].to_sym)
285: end
Declares that the current databse update was not completed successfully. Causes subsequent calls to save_succeeded? to return false.
This is mostly meant to be used by the default actions, but it can be used by user-defined actions as well.
# File lib/resourceful/default/accessors.rb, line 277
277: def save_failed!
278: @save_succeeded = false
279: end
Declares that the current databse update was completed successfully. Causes subsequent calls to save_succeeded? to return true.
This is mostly meant to be used by the default actions, but it can be used by user-defined actions as well.
# File lib/resourceful/default/accessors.rb, line 268
268: def save_succeeded!
269: @save_succeeded = true
270: end
Returns whether or not the database update in the create, update, and destroy was completed successfully.
# File lib/resourceful/default/accessors.rb, line 259
259: def save_succeeded?
260: @save_succeeded
261: end
Returns whether the controller is a singleton, implying that there is only one such resource for each parent resource.
Note that the way this is determined is based on the singularity of the controller name, so it may yield false positives for oddly-named controllers and need to be overridden.
# File lib/resourceful/default/accessors.rb, line 298
298: def singular?
299: instance_variable_name.singularize == instance_variable_name
300: end