break up the session controller into 3 separate controllers? - ruby-on-rails

I have a sessions_controller with 3 actions:
new
create
destroy
but I am thinking that it would be clearer if I created separate controllers for each action, with each controller only doing one thing (sessions#new is less clear to me than login#new):
signup
login
logout
essentially breaking up the actions at a file level rather than a function level.
are there reasons to do one over the other?

While you certainly could break them into separate controllers, I don't think it is necessary and it would make your life a lot harder.
It sounds like you need to utilize routes.rb to match up requests with the controller. This will keep your session logic grouped while making your paths a little more sensical.

Related

Handling Singular Resource in REST

i have a case where i am actually using some resources that are singular in nature. This is about buildings, so in a city i have a single sawmill and a single town_center.
Now, i am creating everything in a RESTful manner using resources(with :except or :only) where needed. In this case though, i am having a town_center_controller and a sawmill_controller that just have a different show action(they have no other actions).
One can say that a buildings_controller sounds better, but in that case, i would have a single show action to display totally different views(like the one for the sawmill and the town_center). They have many differences and i don't really see how i could stack them in a single controller. However, when i destroy or create a building, i do use the buildings_controller.
I would like to ask you, how would you go about it ? How would you design your controllers ? Would you do what i do and create building based controllers(one controller per each building), or something else ?
I would create a general controller that has the generic functions to support all building cases, like destroy/create/edit, then I would create new controller that inherits from that base controller. This way I will keep my generic functions DRY, and my specific (overridden) functions separate.

God Controllers - How to prevent them?

In a few MVC projects I've been working on, it has become apparent that there are a few problematic controllers that have organically grown into God classes - demi-gods each in their own domain, if you will.
This question might be more of a matter 'what goes where,' but I think it's an important question with regards to SRP (Single Responsibility Principle), DRY (Don't Repeat Yourself), and keeping things concise, "agile" -- and I am not experienced enough (with this pattern and in general design) to be knowledgeable about this.
In one project, we have a NutritionController. Over time it's grown to include these actions (many with their respective, GET, POST, and DELETE methods):
Index (home controller)
ViewFoodItem
AddFoodItem
EditFoodItem
DeleteFoodItem
ViewNutritionSummary
SearchFoodItem
AddToFavorites
RemoveFromFavorites
ViewFavorites
Then we have an ExerciseController, which will include many similar actions, such as the searches, and favorites actions. Should these be refactored into their own controller so that it's something like so?
SearchController {
SearchExercise
SearchNutrition
//... etc
}
FavoritesController {
ViewNutritionFavorites
AddToNutritionFavorites
AddToExerciseFavorites
EditNutritionFavorites
EditExerciseFavorites
//... etc
}
It just seems to me that if you break them out into separate controllers, you're going to grow an unbelievably large dependency at some level to deal with the information that you will need. OR you are going to have a completely generic handling application that will be very difficult to handle since you will have to jump through so many hoops to get your desired effect (either at the M, V, or C level).
I am thinking about this the wrong way? For example, should I have a generic Favorites object and then let the controller decide what view to throw it to?
*Sorry for spelling out the acronyms -- I'm doing so in case anyone else comes across this question and is clueless as to what those things are
EDIT:
All the logic I perform is pretty much handled in the service layers. For example, the controller will send the 'new' FoodItem to the service. If it already exists, or there's an error with it, the service will bubble it back up to the controller.
I would break your first list up based on responsibility:
HomeController
Index
FoodItemController
ViewFoodItem
AddFoodItem
EditFoodItem
DeleteFoodItem
SearchFoodItem
NutritionController
ViewNutritionSummary
FavoritesController
AddToFavorites
RemoveFromFavorites
ViewFavorites
SearchFavorites
Django's approach to MVC is to separate responsibilities into "applications", each with their own models, controllers, and even templates if necessary. You'd have a Food app, a Nutrition app, a Search app, and a Favorites app, most likely.
Edit: The OP mentioned that searching is more specific to each controller, so I've made those actions. However, searching may also be just a general global thing, so in those cases, a SearchController would be fine.
Do as Soviut says. You want to keep the controllers simple. It sounds like your ending up with too much coordination logic in your controllers. Remember they are responsible for hooking up a view and a model. This coordination logic should probably be split out into services.
I get this feeling because you mention the possibility of your controller growing huge dependencies. Well If FavoritesController needs to know about nutrition AND exercise favorites (to display in the same view) don't make your controller dependent on 2 repository like classes. Instead, encapsulate that coordination behavior. Maybe create a FavoritesService that knows how to return both nutrition and exercise favorites. That service might delegate to NutritionFavoritesService and ExerciseFavoritesService. This way you're controller only ends up with 1 dependency, you're keeping things DRY, enforcing the SRP, and concentrating your business logic in some place other than the controller.
I'm not too familiar with that framework, but I can offer a bit of general advice. A controller should probably only know how to complete a single action, or to invoke other, single action controllers to complete a sequence of related actions. Any information that must be passed around from action to action should probably be somehow passed through the model layer, since that information is most likely relevant to the underlying model.
I have also experienced these sorts of maintenance headaches and find sticking to a "Rails" like method to be very helpful in keeping my controllers focused and unbloated.
If I find myself adding actions with unusual names Eg. To use a blogging example, AddPostToBlog, that would be a flag to create a new Post controller with a Create action.
In other words, if the action is not either one of the Index, New, Create, Show, Edit, Update and Destroy actions, then I add a new controller specific to the action I require.
For your example.
SearchController {
SearchExercise
SearchNutrition
//... etc
}
I would refactor this to...
SearchExerciseController {
Index
}
SearchNutritionController {
Index
}
This may mean having more controllers, but in my opinion thats easier to manage than ever expanding "god" controllers. It also means that the controllers are more self documenting.
Eg. Does the SearchExercise action, return the View to search the exercise or does it actually perform the search? You could probably ascertain this by looking at parameters and body, but its not as easy as for example a New and Create, or Edit and Update action pair.
SearchController {
SearchExercise
}

Naming for Conventions for Actions and Views (Revisited)

I'm brand new to MVC and, as a learning exercise, I'm trying to re-write an old application as an ASP.NET MVC application. I'm a little unclear about some conventions which the question Action Naming Conventions only partially covers.
Lets say I have two controllers: JobController and ClientController. Both of the controllers are going to have identical actions: List, Details, New, Update, and Delete.
Should the views for these actions be named identically to the action? In this case the List action for JobController should have a view named "List.aspx" as opposed to something like "JobList.aspx".
The reason this question came to my mind was that I was unsure if its appropriate to have multiple views with the same name (such as "List.aspx"). This will get more and more relavent as I continue adding controllers as pretty much every business object in my system will require a "List.aspx" of some sort.
They won't really have the same name. If it were important to give all our files different names why would we want folders? You actually have a Job/List.aspx and a Client/List.aspx.

When should I create a new controller class in ASP.NET MVC?

I'm learning MVC and am having trouble deciding when I should create a new controller versus just adding an action and view associated with an existing controller. On the one hand, Single Responsibility would seem to say a controller should be limited to a few actions. When I try this, though, the number of classes grows exponentially (model, views and controller for each)- to the point I wonder if I'm going overboard.
For example, the default AccountController has Login, ChangePassword, and Register actions. I would tend to instead create a LoginController, PasswordController, and ProfileController, and related model classes. So where there was 1 class, there would be 3-6.
Is there any good rule of thumb on this?
You should dedicate a controller for each model type you're manipulating. The controller acts as a collection of actions that act upon those models. This is generally the rule of thumb, but sometimes a controller's scope transcends a single model.
The AccountController deals with all things authentication related. This is an example of going beyond a single model's scope to encompass authentication in general. What are the key parts of authentication? Retrieving users, changing passwords, etc.
I think you need to be pragmatic about it. I'm working on a project that consists of a StatsController. The number of actions is continuously growing (RandomStat, MostPopular, MostViewed, MostVoted, etc...) the list goes on and on. These actions are simple to satisfy since the StatsController's dependencies don't change. I'm using an IoC to satisfy what my Controllers need and when I start to see my Controllers needing references to new objects, this is a signal that they need to be broken apart.
If your LoginController, PasswordController, and ProfileController all rely on the same objects, why break them apart?
My current AccountController has 12 methods which to me is completely manageable.
I have another controller which currently has 34 methods but those are all tied to a single view and they each have around 8-10 lines of code max (check required parameters, update the model, and redirect as necessary).
They key is to encapsulate your business logic in an entirely separate module. That will allow your action handlers to remain extremely light weight and can make testing your business logic easier.

Rails Model, View, Controller, and Helper: what goes where?

In Ruby on Rails Development (or MVC in general), what quick rule should I follow as to where to put logic.
Please answer in the affirmative - With Do put this here, rather than Don't put that there.
MVC
Controller: Put code here that has to do with working out what a user wants, and deciding what to give them, working out whether they are logged in, whether they should see certain data, etc. In the end, the controller looks at requests and works out what data (Models) to show and what Views to render. If you are in doubt about whether code should go in the controller, then it probably shouldn't. Keep your controllers skinny.
View: The view should only contain the minimum code to display your data (Model), it shouldn't do lots of processing or calculating, it should be displaying data calculated (or summarized) by the Model, or generated from the Controller. If your View really needs to do processing that can't be done by the Model or Controller, put the code in a Helper. Lots of Ruby code in a View makes the pages markup hard to read.
Model: Your model should be where all your code that relates to your data (the entities that make up your site e.g. Users, Post, Accounts, Friends etc.) lives. If code needs to save, update or summarise data related to your entities, put it here. It will be re-usable across your Views and Controllers.
To add to pauliephonic's answer:
Helper: functions to make creating the view easier. For example, if you're always iterating over a list of widgets to display their price, put it into a helper (along with a partial for the actual display). Or if you have a piece of RJS that you don't want cluttering up the view, put it into a helper.
The MVC pattern is really only concerned with UI and nothing else. You shouldn't put any complex business logic in the controller as it controls the view but not the logic. The Controller should concern itself with selecting the proper view and delegate more complex stuff to the domain model (Model) or the business layer.
Domain Driven Design has a concept of Services which is a place you stick logic which needs to orchestrate a number of various types of objects which generally means logic which doesn't naturally belong on a Model class.
I generally think of the Service layer as the API of my applications. My Services layers usually map pretty closely to the requirements of the application I'm creating thus the Service layer acts as a simplification of the more complex interactions found in the lower levels of my app, i.e. you could accomplish the same goal bypassing the Service layers but you'd have to pull a lot more levers to make it work.
Note that I'm not talking about Rails here I'm talking about a general architectural style which addresses your particular problem.
Perfect explanations here already, one very simple sentence as conclusion and easy to remember:
We need SMART Models, THIN Controllers, and DUMB Views.
http://c2.com/cgi/wiki?ModelViewController
The Rails way is to have skinny controllers and fat models.
Do put stuff related to authorization/access control in the controller.
Models are all about your data. Validation, Relationships, CRUD, Business Logic
Views are about showing your data. Display and getting input only.
Controllers are about controlling what data goes from your model to your view (and which view) and from your view to your model. Controllers can also exist without models.
I like to think of the controller as a security guard/receptionist who directs you the customer(request) to the appropriate counter where you ask a teller (view) a question. The teller (view) then goes and gets the answer from a manager (model), who you never see. You the request then go back to the security guard/receptionist (controller) and wait until you are directed to go another teller (view) who tells you the answer the manager (model) told them in response to the other teller's (view) question.
Likewise if you want to tell the teller (view) something then largely the same thing happens except the second teller will tell you whether the manager accepted your information. It is also possible that the security guard/receptionist (controller) may have told you to take a hike since you were not authorized to tell the manager that information.
So to extend the metaphor, in my stereotyped and unrealistic world, tellers (views) are pretty but empty-headed and often believe anything you tell them, security guard/receptionists are minimally polite but are not very knowledgeable but they know where people should and shouldn't go and managers are really ugly and mean but know everything and can tell what is true and what isn't.
One thing that helps separate properly is avoiding the "pass local variables from controller to view" anti-pattern. Instead of this:
# app/controllers/foos_controller.rb:
class FoosController < ApplicationController
def show
#foo = Foo.find(...)
end
end
#app/views/foos/show.html.erb:
...
<%= #foo.bar %>
...
Try moving it to a getter that is available as a helper method:
# app/controllers/foos_controller.rb:
class FoosController < ApplicationController
helper_method :foo
def show
end
protected
def foo
#foo ||= Foo.find(...)
end
end
#app/views/foos/show.html.erb:
...
<%= foo.bar %>
...
This makes it easier to modify what gets put in "#foo" and how it is used. It increases separation between controller and view without making them any more complicated.
Well, it sort of depends upon what the logic has to deal with...
Often, it makes sense to push more things into your models, leaving controllers small. This ensures that this logic can easily be used from anywhere you need to access the data that your model represents. Views should contain almost no logic. So really, in general, you should strive to make it so that you Don't Repeat Yourself.
Also, a quick bit of google reveals a few more concrete examples of what goes where.
Model: validation requirements, data relationships, create methods, update methods, destroy methods, find methods (note that you should have not only the generic versions of these methods, but if there is something you are doing a lot, like finding people with red hair by last name, then you should extract that logic so that all you have to do is call the find_redH_by_name("smith") or something like that)
View: This should be all about formatting of data, not the processing of data.
Controller: This is where data processing goes. From the internet: "The controller’s purpose is to respond to the action requested by the user, take any parameters the user has set, process the data, interact with the model, and then pass the requested data, in final form, off to the view."
Hope that helps.
In simple terms, generally,
Models will have all the codes related to table(s), their simple or complex relationships (think them as sql queries involving multiple tables), manipulation of the data/variables to arrive at a result using the business logic.
Controllers will have code/pointers towards the relevant models for the job requested.
Views will accept the user input/interaction and display the resultant response.
Any major deviation from these will put unwanted strain on that part and the overall application performance may get impacted.
Testing, Testing ...
Put as much logic as possible in the model and then you will be able to test it properly. Unit tests test the data and the way it is formed by testing the model, and functional tests test the way it is routed or controlled by testing the controllers, so it follows that you can't test the integrity of the data unless it is in the model.
j

Resources