Is there a convention for the location of a base controller class? - asp.net-mvc

I have a GridDataController class that handles all of my data requests from my jqGrids.
I think my application would be easier to maintain if I busted that class apart, put the relevent actions in their respective controllers, keep the grid specific functions in a base controller class and then inherit from that class when I need to retrieve grid data in my controllers.
It doesn't seem right for the Base Controller class to reside in the Controllers folder as I do not want any of it's actions to be called.
Is there a convention for this?

No conventions. It would be easier for everybody though if you put it under Controllers, since its a controller, want it or not :). However, you can put it anywhere and refer to it inside your controllers by using and by inheriting from it (if that's what you want to do).
If you don't want its actions to be called, declare it appropriately as abstract class ...
So, no right answer to your question, but before putting it anywhere, thing twice and change your mind and put it back into Controllers :)

Related

Why controller action should call one model method other than an initial find or new?

I have almost all of the "shared" statements in functions in my model. The problem is that I am getting the following error, when I need to use more then one of these functions in my controller:
Controller action should call one model method other than an initial
find or new
and the IDE goes deeper explaining that:
This inspection warns if a controller action contains more than one
model method call, after the initial .find or .new. It’s recommended
that you implement all business logic inside the model class, and use
a single method to access it.
Is this mean that all of the logic should be put in more complex model functions? I have thought that the work of the controller is to call model functions and passes the results to the view.
If I put back the model functions code back to the controller, everything will work, but I will get a code duplication in all my controller actions.
So, what is the right approach here?
The warning message indeed means that the logic should be put in a single model function, but not necessarily more complex ones. To avoid model duplication and/or the "fat model" problem, you may need to introduce additional classes that the model relies on.
Yes, the work of the control is to call model functions, but only as a thin veneer, per this inspection guideline of one model function per controller action aside from an initial create/find.
I'm not sure I understand your comment about getting code duplication in your controller if you move functions back up, since you can always introduce shared functions at the controller level. But again, that's not the recommended approach of "thin controller" and "reasonably thin model" with supporting classes as required.

When to add method to application_controller.rb

My shopping site has a header that's common across all pages.
I have added a shopping cart icon in the header, with a number that updates based on the contents in the current cart.
Because this icon requires a definition for current_cart, I now need to add this to every controller action. Is this unwise/unsafe? I'm new to rails, and don't quite understand the security repercussions of adding methods to applications.rb
Also, is the best way to do this to add this once to application_controller.rb, or to add it separately to each relevant controller action?
Thanks in advance for the feedback!
Having DRY in mind it's definitely better to add this method once, one level up in yours controller inheritance tree. If all controllers need that method then application_controller.rb is a good place. If just some of them then you may consider to create controller which inherits from ApplicationController, store that method in it, and all controllers that requiers that method should inherits form it.
All of your controllers inherit from the application controller. This means that any method you define in the application controller is available in all of your other controllers.

Where should I put functions that are accessed by models? -- Rails 3.1

I've been told that the helpers are just for functions that are needed by the views.
Where should I put in functions that are used commonly by models? What about controllers?
What's the convention to place commonly used functions that will be used in:
1) models
2) views
3) controllers
Problem: Creating a module in lib to hold the functions and including the module in a class would create a boat-load of instance methods for the class.
Problem: What about functions that are common and needed in all three?
Problem: Creating a module in lib to hold the functions and including the module in a class would create a boat-load of instance methods for the class.
First organize, then optimize
Problem: What about functions that are common and needed in all three?
Do you really have methods that are needed in all the three and not exist yet ?
If yes, may be you can give an exemple
I think the question should be where to put logic in general.
You should first think what your method does before to think about where to put it.
But whatever you create, when it's getting big and or valuable, you should really think about exporting it as a gem/plugin.
Inner navigation logic (what to display and where to go after an action) : Controllers
App navigation logic; application_controller
Sub set of app logic; create a namespace with master controller, class API_controller < application_controller
Data logic (How to manipulate, process data) : Models
Data; Model class method (search, sorting, counting, macro process ...)
Datum; Model instance method (modification, micro process ...)
Data presentation logic (How to display data) : Helper, Partial and Decorators
Helper are not designed for that in my opinion.
Partial handle layouting of specific data.
application decorator; handle generic data presentation help
scope_decoration; you can use inheritance
Layout language logic (layout language help) : Helper
Specific to your app; application_helper
Specific to a model ...; model_helper, but you should consider decorator
Generic; export it in a gem (super form helper, templating system ...)
Layout logic (should i display this menu ?) : ?
Helper/decorator/model can should answer the question : #user.can_edit?(#article)
Layout handle the display <%= render :partial => allowed ? "something" : "somthing else" %>
I think if you are not in this configuration you are creating kind of backend system.
So it should go in lib, then in a gem later.
This organization is just an exemple. The most important thing is to organize your code and split different logic layers and don't hesitate to refactor/export code to make it generic after adding new features...
for Controllers - put common methods in application_controller.rb
for Views - put common methods in application_helper.rb
for Models - monkeypatch ActiveRecord::Base to include common methods OR write a module with common model methods and include it in the models that need it OR do it in OOP way by subclassing ActiveRecord::Base with your abstract class, then inheriting all your models from this class.
To use common methods in both Model and Controller, do one of the following:
Write a plain ruby class, put it in /lib or elsewhere, just make sure it's loaded, then require it when you need to use its methods.
Extract common functionality to a gem, install it, require it when you need it. Publish it to rubygems if it's something valuable.
... Usually, I put those kind of functions into common superclasses: For models, that could be (for example) Animal for subclasses Dog, Cat, etc. Within the Animal model, you would have to
self.abstract_class = true
so it doesn't expect a table for that class. For controllers, you could either use ApplicationController or you could make your controllers be derived by another common subclass.
In the Model you should store all the methods that have a relation to the model itself like manipulating attributes, scopes, associating,...
In the View you dont store any logic! The logic belongs to the model. In the view you only put code that helps you to display stuff.
The Controller is the "bridge" between both. You select data in the controller, call methods that are stored in the model,... A common failure is to store the logic in the controller which should be stored in the model.
When you store a method in your Modelyou can access it from the model, the view and the controller! If you have a method that doesn't have a relation to a specific model or its needed in several models you can use the Helper. An example for such a case might be a method that rewrites your url using a pattern. This might be needed in 20 models to prepare a string for to_param. That method would be stored in an Helper that could be included in the Models its needed.

If I have a function that I use both in the controller and in the views, where should I put it?

I try to be very good about keeping my view code and my controller code separate, but occasionally I run into situations where I need to use the same function in the controller and in the views. Where should I put this function so that I can access it from both the controller and the view?
You can put it in a controller and make it available as a helper. If you need it to be available between multiple controllers and their views put in the application controller or other inherited controller:
helper_method :shared_function
According to your situation, for example if the function return a standard Variable value that don't require any controls, you can call it directly from the view, on the contrary, if you have a function that return for example an array that requires controls it's judicious to call it from the the model before you show what you want on the view.
I actually think a module is the best way to share code amongst controllers. Helpers are good if you want to share code amongst views. Helpers are basically glorified modules, so if you don't need view level access, I suggest placing a module in your lib folder.
If the code is really a set of utilities that doesn't need access to object state, I would consider putting it in a module to be called separately.
If the code needs state and is used in a subset of all controllers that are not very closely related, put it in a module and include it in necessary controllers.

Best Practices for reusing code between controllers in Ruby on Rails

I have some controller methods I'd like to share. What is the best practice for doing this in ruby on rails? Should I create an abstract class that my controllers extend, or should I create module and add it in to each controller? Below are the controller methods I want to share:
def driving_directions
#address_to = params[:address_to]
#address_from = params[:address_from]
#map_center = params[:map_center_start]
# if we were not given a center point to start our map on
# let's create one.
if !#map_center && #address_to
#map_center = GeoKit::Geocoders::MultiGeocoder.geocode(#address_to).ll
elsif !#map_center && #address_from
#map_center = GeoKit::Geocoders::MultiGeocoder.geocode(#address_from).ll
end
end
def printer_friendly
starting_point = params[:starting_point].split(',').collect{|e|e.to_f}
ne = params[:ne].split(',').collect{|e|e.to_f}
sw = params[:sw].split(',').collect{|e|e.to_f}
size = params[:size].split(',').collect{|e|e.to_f}
address = params[:address]
#markers = retrieve_points(ne,sw,size,false)
#map = initialize_map([[sw[0],sw[1]],[ne[0],ne[1]]],[starting_point[0],starting_point[1]],false,#markers,true)
#address_string = address
end
In my opinion, normal OO design principles apply:
If the code is really a set of utilities that doesn't need access to object state, I would consider putting it in a module to be called separately. For instance, if the code is all mapping utilities, create a module Maps, and access the methods like: Maps::driving_directions.
If the code needs state and is used or could be used in every controller, put the code in ApplicationController.
If the code needs state and is used in a subset of all controllers that are closely and logically related (i.e. all about maps) then create a base class (class MapController < ApplicationController) and put the shared code there.
If the code needs state and is used in a subset of all controllers that are not very closely related, put it in a module and include it in necessary controllers.
In your case, the methods need state (params), so the choice depends on the logical relationship between the controllers that need it.
In addition:
Also:
Use partials when possible for repeated code and either place in a common 'partials' directory or include via a specific path.
Stick to a RESTful approach when possible (for methods) and if you find yourself creating a lot of non-RESTful methods consider extracting them to their own controller.
I know this question was asked 6 years ago. Just want to point out that in Rails 4, there're now Controller Concerns that're a more out of the box solution.
I actually think a module is the best way to share code amongst controllers. Helpers are good if you want to share code amongst views. Helpers are basically glorified modules, so if you don't need view level access, I suggest placing a module in your lib folder.
Once you create the module, you'll have to use the include statement to include it in the desired controllers.
http://www.rubyist.net/~slagell/ruby/modules.html
I agree with the module approach. Create a separate Ruby file in your lib directory and put the module in the new file.
The most obvious way would be to add the methods to your ApplicationController, but I am sure you know that already.
if you want to share codes between controller and helpers, then you should try creating a module in library. You can use #template and #controller for accessing method in controller and helper as well.
Check this for more details http://www.shanison.com/?p=305
Another possibility:
If your common code needs state and you want to share the behavior amongst controllers, you could put it in a plain old ruby class in either your model or lib directory. Remember that model classes don't have to be persistent even though all ActiveRecord classes are persistent. In other words, it's acceptable to have transient model classes.
I found that one effective way to share identical code across controllers is to have one controller inherit from the other (where the code lives). I used this approach to share identical methods defined in my controllers with another set of namespaced controllers.

Resources