I'm new to Rails and I have a question. Everyone says the preferred way of iterating through a table is to capture the data in an instance variable via a Controller, then iterate in the corresponding View.
What if I just did
<% Course.all.each do |course| %>
<!-- displays list of courses -->
<% end %>
I know using instance variables is the preferred way, but is there any reason?
Could I not use instance variables?
Yes. The code, as you've written it, works.
Using instance variables is the preferred way, but is there any reason?
It's really just an agreed design pattern to do avoid making database queries directly in the view.
A principle of MVC frameworks is to have the controller prepare all data for the view, rather than the view directly fetching data at arbitrary points. In the long term, you'll find the latter approach can become messy, un-performant and difficult to maintain.
For example, you might start making the same query multiple times, or run into N+1 problems, or struggle to test the implementation at all (because if logic is all inside the view, the only way to test might be via very complex+expensive feature tests, instead of quick and easy unit tests!) - which can make the implementation fragile and error prone.
But rules are made to be broken, and you can write code like this in rails; just take a word of warning from the past experience of developers who invented MVC frameworks in the first place: This is generally a design pattern to be avoided.
You certainly CAN do this, but it does not mean it is a good idea.
Rails operates as an MVC framework which separates models, views & controllers, which in turn is really an application of the "Separation of Concerns" design principle.
By adding controller responsibilities (fetching data) into view responsibilities (displaying data & interacting with the users), you're making it more difficult for the view code to be reused.
What if you only want to display a subset of courses but not all of them, but using the same format?
What if you want to display a different set of courses depending on who the user is at the moment?
What if you want to paginate the course list because you've got 1,000 courses already?
And so on.
This is really hard to appreciate when you are just starting out but getting into the habit as early as possible will save yourself from unlearning it later down the line.
At the end of the day, these are just conventions, and there is a time and place wherein you can break conventions but just be aware that all these "rule-breaking" might eventually come back and haunt you. That's what we call "technical debt" and as with any kind of debt, the longer you keep it, the harder it is to pay it off.
Related
I'm building a MVC4 app, I've used EF5 model first, and kept it pretty simple. This isn't going to a huge application, there will only ever be 4 or 5 people on it at once and all users will be authenticated before being able to access any part of the application, it's very simply a place order - dispatcher sees order - dispatcher compeletes order sort of application.
Basically my question is do I need to be worrying about repositories and ViewModels if the size and scope of my application is so small. Any view that is strongly typed to a domain entity is using all of the properties within that entity. I'm using TryOrUpdateModel in my controllers and have read some things saying this can cause a lot of problems, but not a lot of information on exactly what those problems can be. I don't want to use an incredibly complicated pattern for a very simple app.
Hopefully I've given enough detail, if anyone wants to see my code just ask, I'm really at a roadblock here though, and could really use some advice from the community. Thanks so much!
ViewModels: Yes
I only see bad points when passing an EF Entities directly to a view:
You need to do manual whitelisting or blacklisting to prevent over-posting and mass assignment
It becomes very easy to accidentally lazy load extra data from your view, resulting in select N+1 problems
In my personal opinion, a model should closely resembly the information displayed on the view and in most cases (except for basic CRUD stuff), a view contains information from more than one Entity
Repositories: No
The Entity Framework DbContext already is an implementation of the Repository and Unit of Work patterns. If you want everything to be testable, just test against a separate database. If you want to make things loosely coupled, there are ways to do that with EF without using repositories too. To be honest, I really don't understand the popularity of custom repositories.
In my experience, the requirements on a software solution tend to evolve over time well beyond the initial requirement set.
By following architectural best practices now, you will be much better able to accommodate changes to the solution over its entire lifetime.
The Respository pattern and ViewModels are both powerful, and not very difficult or time consuming to implement. I would suggest using them even for small projects.
Yes, you still want to use a repository and view models. Both of these tools allow you to place code in one place instead of all over the place and will save you time. More than likely, it will save you copy paste errors too.
Moreover, having these tools in place will allow you to make expansions to the system easier in the future, instead of having to pour through all of the code which will have poor readability.
Separating your concerns will lead to less code overall, a more efficient system, and smaller controllers / code sections. View models and a repository are not heavily intrusive to implement. It is not like you are going to implement a controller factory or dependency injection.
In learning about Core Data, I've noticed how (in Xcode's templates) Apple directly used the query classes inside the view controller. This seems like it is bad MVC (having database access logic directly inside the view controller). Would it make sense to abstract out these kinds of actions to a separate suite of classes that obtain the data from the database and pass it back to the view controller calling it?
EDIT–
So, just to be clear, when I say "kinds of actions", I specifically mean CRUD Operations. Though if you have ideas about other things that a so-called "Model-Controller" would do, I'd be interested in hearing about them.
It's a matter of opinion, and often yes the templates are the most simple form of working example. It's hard to have a template spin out multiple files, for example.
Yes, personally, I generally spin out a separate NSManagedObject subclass. I like to have a _MySubclass object that has all the auto-generated stuff, then have the model actually reference MySubclass which has model-based business logic (you can use mogenerator or other methods to do this too if so inclined). Perhaps thinking of it as "Model-Controllers" and "View-Controllers" is another way of putting it.
This is a very good question and the answer likely depends on your situation. Perhaps architecture purists would insist on separate Model controllers and there are a lot of benefits to this approach. However, sometimes I find myself using Key Values when I'm doing a simple view. When things are more complex, for example, when coding the same Model for the Mac and iOS, having separate Model Controllers will allow you to reuse a lot of code. When you must diverge, Obj C Categories are a very clean way to extend functionality without adding a lot of overhead. I personally favor categories over extensive subclassing.
Since NSFetchedResultsController was released, my model classes are leaner. There are a lot of nuances to this and experience will help you come up with the best solution for your App. I've also found that writing unit tests up front will help you force through issues and validate your design, or send you back to the drawing board :)
Just curious why ManagedObjectContexts should be passed to UIViewControllers when they are created, rather than just grabbing them from a UIApplicationDelegate?
The docs say that this makes your applications more rigid, but I am failing to see the nuances of when to use which pattern.
Thanks!
Imagine that I ask you to do some task, like painting a room. If I just tell you "go paint a room," you'll need to ask me a lot of questions, like:
Which room?
Where's the paint?
Where are the brushes?
Should I use a dropcloth?
In short, you won't be able to complete the task without help from me. If you have to depend on me every time, you won't be a very flexible painter. One way to deal with that problem is for me to give you all the stuff you need at the outset. Instead of "go paint a room," I'll say "please paint room number 348 using this bucket of paint and this brush, and don't bother with a dropcloth." Now, you've got everything you need, and you can get right to work with no further help from me. You're a much more flexible worker because you no longer depend on me.
The same thing applies to view controllers (and objects generally); it's better to give them everything they need than to have them depend on a particular object like the app delegate. It's true not just for managed object contexts, but for any information they need to do their job.
This is mainly because you want to use dependency injection with your UIViewControllers instead of just grabbing everything from UIApplication, this keeps your delegate clean instead of full of reference hacks.
This is also to keep with the MVC pattern:
Model
View Controller (Only for view logic)
Controller (For coordinating between the view and the model)
I tend not to agree with this pattern.
First of all I try to treat Core Data as an implementation detail, and as any implementation detail it should be hidden behind a good facade. The facade is the interfaces I expose for my model objects. For example if I have two model objects; Cource and Student, any cource can have a number of students. I do not want to let the controller take upon the duty to setup predicates and sort descriptors, and jump through all Core Data hoops just to get a list of students for a particular class. There is a perfectly valid way to expose this in the model:
#interface Cource (StudentAccess)
-(NSArray*)studentsStortedByName;
#end
Then implement the ugly stuff once and for all in the Model class. Hiding all the complex details of Core Data, and no need to pass around managed object contexts. But how would I find the sources, it has to start somewhere right? Yes, it does but you need not expose it to the controller. Adding methods such as these are perfectly reasonable as well:
#interface Cource (CourceAccess)
+(Cource*)caurceByID:(NSString*)courceID;
+(NSArray*)allCources;
+(NSArray*)courcesHeldByTeacher:(Teacher*)teacher;
#end
This also helps in minimizing dependencies between controllers. And reducing he dependencies between the model and controller. Assuming I have a CourceViewController and a StudenViewController is I did not hide the Core Data details behind a facade and wanted to pass around the managed object context as well, then I would end up with a designated initializer like this:
-(id)initWithManagedObjectContext:(NSManagedObjectContext*)moc
student:(Student*)student;
Whereas with good a good facade I end up with this:
-(id)initWithStudent:(Student*)student;
Minimizing dependencies behind facades, in favor of dependency injection also makes it much easier to change the internal implementations. Passing around the managed object context encourages each controller to implement their own logic for basic stuff. Take for example studentsSortedByName method. At first it might be sorter by last/first name, if later changed to last/first name sort you would have to go to each and every controller that has sorted students and make the change. Where a good facade method requires you to change in one method, and all controller automagically get the update for free.
The Apple Docs try to foster the most widely applicable and sustainable design patterns.
Dependency injection is preferred because it allows for the most flexible, expandable, reusable and maintainable design.
As apps grow in complexity, using a quasi-singleton like parking the context in the app delegate breaks down. In more complex apps, you may have multiple context tied to multiple stores. You might want the same view-controller/view pair to display data from different context at different times or you may end up with multiple context on different threads/operations. You can't pile all those context up in the app delegate.
If you have a simple app with a single context then using the quasi-singleton with the app delegate can work well. I've used it on several smaller apps in the past without immediate issue but I did hit scalability problems on a couple of apps when the apps grew overtime.
Which pattern to use depends on your shipping constraints and you best guesses about of the evolution app over its entire lifecycle. If its a small one shot app, then the app delegate quasi-singleton will work fine. If the app is more complex, might grow more complex or might spawn other related apps that will reuse existing components, then dependency injection is the way to go.
Does anyone here use DTO's to transfer data from the controller to the view? If so, where would you recommend storing those files? /apps/dtos, and then let them mirror the views dir structure? Any recommendations on testing these animals with rspec?
Please don't listen to the other answers. They are terrible. Rails helpers are terrible. Using rails models everywhere is terrible. I am begging you, design your application properly and decide if you need DTOs or not. Decide if you actually want to have rails models to handle things other than communication with the database. Decide if you actually want to not have a layer between your app and rails and so on and so forth. Rails design is suitable for only small apps or apps that have to be developed super quickly. But if it's not something trivial and you expect to develop it for some time, please invest your time into proper design. Don't be afraid to break Rails conveniences. And may the force with you.
The Rails convention is not to use distributed tiers for controller and view layers. The separation is there, but it is logical and relatively thin/lightweight compared to the types of frameworks you see in Java land.
The basic architecture is that the controller sets instance variables that are available in the corresponding view. In the general case, the instance variables will be model instances or collections of model instances (coming from the database). Models should be the core of your business logic. Controllers coordinate flows of data. Views display it. Helpers are used to format display values in the view ... anything that takes a model value and does something just for display purposes (you may find that a helper method used repeatedly may actually be better off on the model itself).
However, if you find that a view needs knowledge of many different models, you might find it easier to wrap models into another object at a higher-level of abstraction. Nothing prevents you from creating non-active-record objects that collect and coordinate your actual AR models. You can then instantiate these objects in the controller, and have them available to the view. You generally have to be at a pretty dense level of complexity in the controller to need this type of thing.
I would tend to throw such objects into apps/models - Rails already loads everything in this directory, keeps things easy from a config/expectation point of view.
If you're coming from a .NET or J2EE background you may be thinking about patterns like DTO. You may or may not be surprised (and possibly happy) to learn that Rails doesn't do things that way by convention.
In particular there is no need at all to formally transfer (or store) serialized objects between the controllers and views. Instance variables (typically model attribute values) created in the controller are available within the view for free as provided by the framework without any additional programming effort needed.
What I've been told is that generally, this is work that is handled by 'helpers'. They basically help you format your model objects for view consumption from within the view. So it's definitely not a 1-1 mapping of concepts, but that's the thinking in the rails world
In keeping with the DRY-principle I try to use partials as soon as I am repeating a particular pattern more than once or twice. As a result, some of my views consist of ten or more different partials. I am worried that this might have a negative effect on the overall performance. Some programming books compare the use of partials with the use of methods. So should I use the same rationale to determine when to use them?
What is the best practice regarding size and quantity of partials in a Rails project?
I like your practice already: Once you've repeated view code twice, refactor it out to a partial. Tim's right that you can speed it up as necessary after it's been profiled and after it's been proven necessary.
Here is my one caveat: If you work with professional designers who handle the views, it may be easier over the long term to have rather repetitive view code. Some people have a hard time searching through partials and "seeing" how they all fit together. I've found it easier with those people to let them manage the whole shebang and update more than one file if they need to. Optimal? Not to us as programmers, but designers are more often used to seeing most of the HTML in one or three files rather than 20. :)
Remember the rules of optimization!
If, once your application is complete, your views are too slow, use something like New Relic to find out where the slowdown is occurring. There are a lot of places that might be, but it's unlikely to be in your partials.