What's the best Rails convention for this? - ruby-on-rails

Let's say that you have a resource that is created and displayed entirely within the view of another resource (eg. comments or tags). Should you still make it it's own resource, or would it be a better idea to make it a nested resource? Also, should you make use of virtual attributes?
I know this question is general, but I'm not looking for a specific answer, just a general explanation of when each technique is preferred.

Some general thoughts:
Nesting and independent resources are not necessarily mutually exclusive.
"created and displayed entirely within the view of another resource" is a strong statement that can end up not being true. For example, tags: do you ever want a list of all articles with a certain tag. that would not make sense nested.
Nesting below the second or third level will begin to be more trouble then its worth. Some will say that even the first nesting is more trouble then its worth.
For an app that has a single dominate resource the cost of adding other independent resources is proportionally higher. Small apps can get away with complexities that large apps cannot.
If you don't have a good feel yet write a few resources each way. Answers will at best be justifies opinions it is probably best to develop you own through experience.

Generally speaking, it would be more useful to make it a nested resource. This is the more "RESTful" way. It will also give you access to the parent resource without having to specify it as a parameter. However, you do not want to nest a resource more than one level deep, as noted in the Rails routing guide.

Related

Could I not use instance variables?

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.

When should you nest model declarations in Rails?

What are the guidelines about when it is better to nest Model name spaces and when it is better to leave them all top-level?
For instance, when I have a few classes that all have something to do with one core class (and the majority of the system only deals with that core class) then my instinct tells me to declare them as such:
CoreModel
CoreModel::DependentOne
CoreModel::AnotherDependent
Almost always this corresponding to has_many/belongs_to relationships (i'd almost consider this the next candidate for convention over configuration.)
And again, my routes often reflect this nesting:
/CoreModels/:core_model_id/DependentOne/:id
The reason I feel like I should do this is because often two component areas of the same large application may need a supporting component with similar if not identical names as other areas of the software. I feel like name spacing these dependent models (which only exist to support that core model) is the best way to go.
I'm confused because while some times doing things this way can make stuff easier (such as link_to which needs only to take the DependentOne model and will automatically route correctly) yet other items such as form_for refuse to work properly (because it doesn't route properly and if I add the CoreModel to the form_for it complains about no such route core_model_core_model_dependent_one etc....
Perhaps I haven't been clear enough and so I'll ensure I update this as requests for clarifications come in.
...the majority of the system only deals with that core class...
In that case, I wouldn't bother namespacing them.
The reason I feel like I should do this is because often two component areas of the same large application may need a supporting component with similar if not identical names as other areas of the software. I feel like name spacing these dependent models (which only exist to support that core model) is the best way to go.
Bingo - if you have name conflicts, namespacing is a good way to fix it. But, do you have that problem yet?
Namespacing prevents name conflicts, but in Rails it also introduces some gotchas and headaches and (throughout the app) quite a bit more typing. So, to me, it isn't worth it unless you actually have a name conflict.
Consider a structure like this, with your core model and many that just help it.
#Core Models
Model
Supporter
Assister
Helper
Benefactor
For most of the life of your app you may never run into a problem. If you do finally hit one, you could just do this:
AltModel
AltModel::Supporter
OtherModel
OtherModel::Benefactor
Or if it's really simple just prefixing the class name would work:
AltModelSupporter
OtherModelBenefactor
For that matter, it's probably simpler to name your core models in this way than it would be to "properly" namespace them:
CoreModel
CoreSupporter
CoreAssister
So, there are many ways to accomplish what you need, none of which suggest you should bother namespacing the core functionality of your app when you don't actually have a namespace conflict. Given the headaches you've already run into I think you'll be happier leaving the core models of your app in the top-level namespace and only nesting alternate models that actually have a conflict down the road.

Nested Routes and Parameters for Rails URLs (Best Practice)

I have a decent understanding of RESTful urls and all the theory behind not nesting urls, but I'm still not quite sure how this looks in an enterprise application, like something like Amazon, StackOverflow, or Google...
Google has urls like this:
http://code.google.com/apis/ajax/
http://code.google.com/apis/maps/documentation/staticmaps/
https://www.google.com/calendar/render?tab=mc
Amazon like this:
http://www.amazon.com/books-used-books-textbooks/b/ref=sa_menu_bo0?ie=UTF8&node=283155&pf_rd_p=328655101&pf_rd_s=left-nav-1&pf_rd_t=101&pf_rd_i=507846&pf_rd_m=ATVPDKIKX0DER&pf_rd_r=1PK4ZKN4YWJJ9B86ANC9
http://www.amazon.com/Ruby-Programming-Language-David-Flanagan/dp/0596516177/ref=sr_1_1?ie=UTF8&s=books&qid=1258755625&sr=1-1
And StackOverflow like this:
https://stackoverflow.com/users/169992/viatropos
https://stackoverflow.com/questions/tagged/html
https://stackoverflow.com/questions/tagged?tagnames=html&sort=newest&pagesize=15
So my question is, what is best practice in terms of creating urls for systems like these? When do you start storing parameters in the url, when don't you? These big companies don't seem to be following the rules so hotly debated in the ruby community (that you should almost never nest URLs for example), so I'm wondering how you go about implementing your own urls in larger scale projects because it seems like the idea of not nesting urls breaks down at anything larger than a blog.
Any tips?
Don't get too bogged down by the "rules" in the Ruby community. The idea is that you shouldn't go overboard when nesting URLs, but when they're appropriate they're built into the Rails framework for a reason: use them.
If a resource always falls within another resource, nest it. Nothing wrong with that. Going deeper than one can sometimes be a bit of a pain because your route paths will be very long and can get a bit confusing.
Also, don't confuse nesting with namespacing. Just because you see example.com/admin/products/1234/edit does not mean that there's any nesting happening. Routing can make things look nested when they're actually not at the code level.
I'm personally a big fan of nesting and use it often (just one level -- occasionally two) in my applications. Also, adding permalink style URLs that use words rather than just IDs are more visually appealing and they can help with SEO, whether or not they're nested.
I believe the argument for or against REST and/or nesting in your routes has much to do with how you want to expose your API. If you do not care to ever expose an API for your app publicly, there is an argument to be made that strict adherence to RESTful design is a waste of time, particularly if you disagree with the reasoning behind REST. Your choice.
I find that thinking about how a client (other than a browser) might access information from you app helps in the design process. One of the greatest advantages of thinking about your app's design from an API perspective is that you tend to eliminate unnecessary complexity. To me this is the root of the cautions you hear in the Rails community surrounding nested routes. I would take it as an indication that things are getting a bit complicated and it might be time to step back and rethink the approach. Systems "larger than a blog" do not have to be inherently complex. Some parts might be but you also may be surprised when you approach the design from a different perspective.
In short, consider some of the dogma you might hear from certain parts of the community as guides and signals that you may want to think more deeply about your design. Strict REST is simply another way to think about how you are structuring your application.

Best Practices for using partials in Rails

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.

Which multi-language web architecture works best (multiple views/single view)?

I want to support just 2 languages. There will be no requirement for any additional language. What will be the best approach after considering both ease of use and maintenability:
(a) Each view has a separate page for each language and they will share controllers and model dlls
(b) Both languages pump resources into the same view template
Please don't bother about the url structure right now. I will appreciate real experiences over the theoretical discourses of pros and cons. Thanks for your help.
Mutliple views are more flexiable clearly and if you only have 2 then that is a possibility but its still a pain.
However having just 2 instead of N to worry about means you can probably take both into consideration when creating the views in the first place. Hence instead creating multiple views create a single view that uses resources and works in both languages.
Depends on how different you expect the localized versions to get. If you are pretty confident they will always be almost identical, simply different words in each placeholder, then a single view model would probably be the way to go.
However, what I have found to work when there is a blend between the two (i.e. some views are the same, just translated; others end up being somewhat different) is to build a provider model into each view and sub-view, so when the view engine goes to load a view, there is isolated logic in the provider factory to determine, for that particular view, whether to use the same for both languages or switch.

Resources