Clarification of When to use Controllers - ruby-on-rails-3

Im new to rails and want to understand controllers better (especially when linked with models)
My example is I have Recipe controller and model and then a favourite controller and model. Within the recipe controller I have New, create, update, destroy etc, so that obviously I can perform those actions on a recipe.
Now i want to flag recipes as favourites, so again I can create a new favourite and delete a favourite. So is it best practice to put my requests for the favourite model in the favourite controller. Not in the same controller as recipe. the reason I ask this is because i have favourite and recipe associated with belongs_to.
Also within my app I want to view favourite recipes within the my_recipes page (this is in the recipe controller), does it matter that my create/delete methods are in another controller for favourites?
I hope this makes some sense to someone, looking for some clarification really

This is two resources, so i think it would be better to have two controller for them. In your case, you can put your request in recipe controller, because you want flag favourite recipes. As you can see questions on stackoverflow has a start flag to make question is favourite or not. So you can put an action in recipe controller to make a normal recipe become favorite recipe. It means you can put create/delete methods not in favourite recipe controller.

Related

When does a method warrant being defined in the Model instead of Controller? (from Chap 10 of Rails Tutorial)

I am currently going through Hartl's Rails Tutorial, and through the first 10 chapters or so have gotten used to the convention of putting most of the actions/methods in the controller. Currently, as the book is going through and defining a feed method for the Microposts, the method is placed with the User.rb model instead. As I am relatively new to the world of rails (and programming in general), I was wondering what the rationale or convention followed for putting this method (copied below) in the Model?
The method placed in the User.rb model:
def feed
# This is preliminary. See "Following users" for the full implementation.
Micropost.where("user_id = ?", id)
end
There is actually quite some contention on what code to put where, but in general, there are some easy guidelines to follow.
Does the method have to know some detail about the underlying data structure? Put it in the model.
An easy way to determine this is when it uses ActiveRecord methods like find, where, or specific columns in the database. By keeping this logic in the model, that means if you need to change the underlying datastore, you only have to change the model.
Does the method have some say in how a page is going to be rendered? Put it in the controller.
Generally, controllers should be pretty thin, pushing data to views and saving form data back to models.
While (if I remember correctly) Hartl does not take about non-rails classes, don't be afraid to put 'business logic' outside of the rails structure. You can create a app/lib or app/services or app/x directory and put plain old ruby objects in there, which can then be called from your controllers and models to handle those things they are good at.
Aim to 'push' things 'up' into the model as much as possible, then they will be repeated less and available to more. Don't just use models for Active Record database tables.
You can often unit test models easier.
Another 'next' place to put stuff that is shared is in /lib

Inserting controller logic between model and view when using Interface Builder, NSObjectController sub-classes, and bindings

I've been struggling to understand the best way to insert controller logic when using IB, NSObjectController sub-classes and bindings.
I need to insert controller logic between the model and the view, and I'm struggling to find an elegant way to do so. Yes, you can send actions to the file owner and handle controller logic in there, but when some core data models can extend across fifty entities or more with deep relationship structures, this starts to mount up to an incredible amount of boiler-plate code.
A very simplified example would be this; imagine you have an entity with four string attributes myTextWinter, myTextSpring, myTextSummer, myTextAutumn. You have a view which connects to this in IB via an NSObjectController. Now, say the user can select which 'Season' they wish to view by choosing Spring, Summer, Autumn, Winter from a Menu somewhere - when that season is selected, I would like to display the appropriate season's text.
In this simplified example I could probably fetch the object in the NSDocument sub-class, create a property called mySeasonText which I bind to in my view, and then check my NSUserDefaults for the appropriate season and route the requests to the appropriate attribute in the model.
The problem comes when I have fifty entities, some with relationships some two, three or more deep, each with their own set of season specific text attributes that I wish to switch between when selecting from the Season menu. Or if I have a bunch of nsarraycontrollers chained together to access objects at a deeper, and deeper level.
To date, I've been doing the following; adding a property in each of my model objects called 'mySeasonText', then grabbing the setting from my controller setting, and routing to the appropriate season. I refresh these objects whenever a new item in the menu is selected.
Whilst this works and eliminates an absolute ton of boiler-plate code, my controller logic is now in my model.
There must be a better way! Could someone please point me in the correct direction?
This is a tricky topic. Apple even mentions these challenges in its own documentation:
By using the bindings technology, you can easily create a Cocoa MVC application whose views directly observe model objects to receive notifications of state changes. However, there is a theoretical problem with this design. View objects and model objects should be the most reusable objects in an application. […] Design-wise, it's best to keep model and view objects separate from each other, because that enhances their reusability.
The design pattern you are looking for is a Mediating Controller - a way to use the cocoa-bindings classes to insert controller logic:
Mediating controllers are typically ready-made objects that you drag from the Interface Builder library. You can configure [Mediating controllers] to establish the bindings between properties of view objects and properties of the controller object, and then between those controller properties and specific properties of a model object. As a result, when users change a value displayed in a view object, the new value is automatically communicated to a model object for storage—via the mediating controller; and when a property of a model changes its value, that change is communicated to a view for display.
Here is how I like to think of them: Have you ever seen a movie or TV show where two characters need to talk, but they don't speak any of the same languages? They find someone else (or in a comedy 5 other people) who each have one language in common, and they communicate by playing a giant game of translation telephone.
Mediating controllers are kind of like that.
As your application grows they learn all the super specific rules about where to look for this one thing on this one view. This is the kind of code that an app needs to run, but you rightly feel that it is nasty when put in your model.
For several specific and detailed examples, Apple provides this amazingly detailed document: Bindings Message Flow.
For some really good discussions about this and related MVC + Bindings please see:
MVC and cocoa bindings best practices question
Why use NSObjectController?
Replacing model objects using an NSArrayController

iOS architecture and components

For quite a while I've been looking at objective c examples, watching the Stanford lectures, and playing around with some code to get a hang of creating an iOS app.
However there are a few things that I can't find a good answer on:
How do I properly separate my layers? I understand the MVC structure, and I saw some examples of creating Categories for models to implement business logic. Is that the proper way, by enriching models or should I create dedicated classes (e.g. to authenticate users, extract models from json, group orders)?
How smart should views be? Can I make a view that displays a Contact (by assigning the contact property) or should I create separate properties for all of the Contact fields or should the view request it's information via a delegate call?
I'm using a Storyboard in my application. On my screen I want to
have a navigation bar, and let's say a view that displays orders. On
other screens I want to reuse the order-view.
How can I re-use the order-view's ViewController and View in other ViewControllers?
If I have 4 screens with the same look-and-feel, do I have to simply copy them in the Storyboard? This seems like a pain to main, what if I want to change my background? Or add a button to all of the views? When I create a setup-wizard I don't want to define the look-and-feel for every screen separately.
Coming from a C# background I probably have to get into the objective-c mindset :)
Any help on this would be great.
1) ObjC-Categories will easily distort your understanding of the main problem you're facing. ObjC-Categories are completely unnecessary. You could always approach these extensions by subclassing, object composition, additional methods in the actual model, or some customization in the controller or view. So if you need to format data (e.g. which is present in the model) for display in a view -- that task would often land in the controller. As far as the examples you provide: You may opt for models in simple cases -- as well, any of the examples could merit dedicated class, if complex enough or if it would keep you from redundant implementation. Note that these may be accessory classes, which simply produce a model, or they may be composites of multiple concrete of abstract classes. Not everything needs to land squarely in the definition of M-or-V-or-C. You're free to use many design patterns with ObjC. Think of MVC as the patterns Cocoa typically uses -- you will need to know them, and you will need to know how to subclass and extend these types, but these patterns lose dominance as implementations move away from Cocoa's libraries (e.g. as complexity increases).
2) They can be smart. However, under MVC, you want to focus its implementation on the view/presentation aspect. A view which represents a collection of information could in fact perform some tasks which are typically reserved for the controller -- however, you would generally cede that the implementation were a dedicated MONContactView in doing so. If you go that route, you would generally do so for easy reusability or to achieve a simple interface. Displaying information about a Contact could be very complex - In simple scenarios, these tasks are often handled by the controller. Specifically, a MONAwesomeContactView is likely less complex (e.g. in SLOC) than MONAwesomeContactViewController (unless you have some very special drawing or layout to perform). It would be more common to set the controller's contact, and let the controller push the contact data to the views' fields. Again, in the case of a very specialized subclass -- a view could very well hold its own controllers in some cases.
3a) There's nothing wrong with creating multiple instances of a class.
3b) No need to copy. When duplication is smelled, I push the implementation to actual code -- the programs can apply the look and feel you desire, or add or manipulate the subviews as you desire. Of course, they will not be present in Xcode's NIB editor. There are of course alternate approaches, but this replication often makes me move the implementation to compiled code. Achieving a good balance of both is not so difficult (personally, I do most of my views programmatically, rather than using NIBs).
This is a pretty abstract question and it's not clear what oh mean by 'layers'. Yes, you should create your own classes where appropriate, but categories also give you the option of adding functionality to existing classes. If you can be more specific with the question it'll be easier to provide a better answer.
It's a judgement call. If you want to create a view class that knows how to display an instance of your Contact type, that's fine in my book. If that view knows where Contacts are stored in the app, though, that's not so good.
Remember that the things in a storyboard are objects, not classes. You don't want to try to re-use a view from one scene in another scene -- that'd mean sharing a view between scenes, which really won't work. If you want to use the same order-view in several places, that'd be a good candidate for creating a class. On the other hand, you can set up your storyboard so that several different scenes all transition to the same scene. If you want different parts of your app to modally display a scene that displays an order, for example, you can do that.

Ruby on Rails, Split Model into Two Controllers/Forms, but update action calling parent

I have a model that for edit/update actions only is logically split into two forms. The model is Venue. I created app/controllers/venues_controller.rb. The two sub-forms are Details and Policies, so I created app/controllers/venues/details_controller.rb and app/controllers/venues/policies_controller.rb, as well as their corresponding views. The child controllers do inherit from VenuesController. I added the venues namespace to my routes, so it now looks like:
resources :venues
namespace :venues do
:details, :policies
end
The routes work correctly, the correct views load, the "edit" action on the sub-controllers is called correctly. However, in the sub-views, I'm using the RESTful form_for(#venue), so when the form is POSTed (PUT) it is going to venue_path, not venue_details_path.
I looked at the docs for form_for and can't figure out a way to keep my sub-forms restful. You can add a token for a namespace a la form_for([:namespace, #model]), but in my case, the model name is the namespace, so it's inverted.
I really don't want to split the model itself, since that has other implications that would be harder to address.
So far, I see two solutions, both of which I don't like:
1. Let both views POST to VenuesController#update and deal with any differences there (more lame controller code)
2. Use form_tag and _tag helpers (more lame view code)
Am I missing something obvious? Is there something different I can do in the routes, or is there another way to call form_for?
I've scanned some posts about Presenter and Conductor patterns but they don't seem to fit this problem. I've read a few stackoverflow threads about whether creating two controllers for one model koscher (it is), but nothing about this specific issue.
Ah, found it. form_for(#venue, :url => venues_detail_path(#venue)). Gotta love Rails.

cakephp how to refer to the model with a variable in the controller

I want to refer to $this->Model-> ... in the controller. But I want to make the functions generic, so how can I use do that dynamically? I tried $this->$modelname but of course that didn't work.
The CRUD functions will be generic to all models and thus all controllers, with overriding in a couple of cases.
EXAMPLE: Two controllers, one for each model -- Letter and Email. There is letter controller and email controller. Each has CRUD functions. The views are essentially identical, except the models track different information for each (e.g., Letter with send_method). The only thing that varies between them is the fields. I have automated that part, but the controllers are essentially the same thing as one another except for a few minor variations. I want to have a parent class and have it use the model name of the particular model, so I don't have to keep making changes to every controller every time I make a change. But in some instances I need to refer to $this->Model-> ... and I don't know how to do that.
Commplete rewrite based on clarification of OP
At the top of letters_controller.php add:
$this->defaultModel = 'Letter';
And in emails_controller.php add:
$this->defaultModel = 'Email';
In either controller, to reference the model, call
$this->{$this->defaultModel}->function();
Sounds like you're trying to re-invent the wheel: have you checked out the CakePHP Scaffolding section?