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.
Related
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.
I am making an app where several users work towards a common goal grouped under an account.
What would be a better structure for my urls?
Subdomains: some-team-name.app.com
Directories: app.com/some-team-name
For example, Basecamp uses subdomains.
Do clients think better of your web-app if it uses subdomains?
In my humble opinion it's mostly a programming hassle and offers no real value.
I think it really depends on how you approach your app.
For example, Basecamp uses domains because each space is on its own, without sharing nor communicating with others. Thus, conceptually, you could approach subdomains as different, parallel versions of a simple concept (a business account, a work project, etc).
On the other hand, folders, all nested on the same root domain, seems more a part of something
than something on its own.
Since they are teams who, on some way or another, share info, comments and stuff like that, I'd say the second approach feels better. And it's technically more easies to accomplish.
At the end of the day, both could be use to be the same, but some patterns (like I've commented before) tend to be use on one or other situation. It really depends on your take :)
**update: horray! so it is a journey of practice and understanding. ;) now i no longer feel so dumb.*
I have read up many articles on REST, and coded up several rails apps that makes use of RESTful resources. However, I never really felt like I fully understood what it is, and what is the difference between RESTful and not-restful. I also have a hard time explaining to people why/when they should use it.
If there is someone who have found a very clear explanation for REST and circumstances on when/why/where to use it, (and when not to) it would benefit the world if you could put it up, thanks! =)
REST is usually learned like this:
You hear about REST being using HTTP the way it was meant to be used, and from that you shun SOAP Web Services' envelopes, since most of what's needed by many SOAP standards are handled by HTTP in a simple, no-nonsense way. You also quickly learn that you need to use the right method for the right operation.
Later, perhaps years later, you hear that REST is more than that. REST is in fact also the concept of linking between resources. This often takes a while to grasp the full meaning of, but when you learn this, you start introducing hyperlinks into your responses so that clients can navigate your system without being coupled to how the server wants to name its resources (i.e. the URIs).
Even later, you learn that you still haven't understood REST! And this is because you find out that media types are important. You start making media types called application/vnd.example.foo+json and put hyperlinks in them, since that's already your understanding of REST.
Years pass, and you re-read Fielding's thesis for the umpteenth time, to see if there's anything you missed, and it suddenly dawns upon you what really the HATEOAS constraint is: It's about the client not having any notion of how the server's resources are structured, but that it discoveres these relationships at runtime. It also means that the screen in front of the user is driven completely by what is passed over the wire, so in fact, if a server passes an image/jpeg then that's what you're supposed to show to the user, not an error message saying "AtomProcessor can't handle image/jpeg".
I'm just coming to terms with #4 and I'm hoping the ladder isn't much longer! It's taken me seven years.
This article does a good job classifying the differences in several http application styles from WS-* to RESTian purity. What I like about this post is it reminds you that most of what we call REST really is something only partly in line with Roy Fielding's original definition.
InfoQ has a whole section addressing more of the "what is REST" angle as well.
In terms of REST vs. SOAP, this question seems to have a number of good responses, particularly the selected answer.
I would imagine YMMV, but I found it very easy to start understanding the details of REST after I realised how REST essentially was a continuation of the static WWW concepts into the web application design space. I had written (a rather longish) post on the same : Why REST?
Scalability is an obvious benefit of REST (stateless, caching).
But also - and this is probably the main benefit of hypertext - REST is ideal for when you have lots of clients to your service. Following REST and the hypertext constraint drastically reduces the coupling between all those clients and your server, which means you have more freedom when evolving/developing your service over time - you are not tied down by the risk of breaking would-be-coupled clients.
On a practical note, if you're working with rails - then restfulie is a great little framework for tackling hypertext on the client and server. Server side is a rails extension, and client is a DSL for handling state changes. Interesting stuff, check it out here: http://restfulie.caelum.com.br/ - I highly recommend the tutorial/demo vids they have up on vimeo :)
Content-Type: text/x-flamebait
I've been asking the same question lately, and my supposition is that
half the problem with explaining why full-on REST is a good thing when
defining an interface for machine-consumed data is that much of the
time it isn't. OK, you'd need a really good reason to ignore the
commonsense bits (URLs define resources, HTTP verbs define actions,
etc etc) - I'm in no way suggesting we go back to the abomination that
was SOAP. But doing HATEOAS in a way that is both Fielding-approved
(no non-standard media types) and machine-friendly seems to offer
diminishing returns: it's all very well using a standard media type to
describe the valid transitions (if such a media type exists) but where
the application is at all complicated your consumer's agent still
needs to know which are the right transitions to make to achieve the
desired goal (a ticket purchase, or whatever), and it can't do that
unless your consumer (a human) tells it. And if he's required to
build into his program the out-of-band knowledge that the path with
linkrels create_order => add_line => add_payment_info => confirm is
the correct one, and reset_order is not the right path, then I don't
see that it's so much more grievous a sin to make him teach his XML
parser what to do with application/x-vnd.yourname.order.
I mean, obviously yes it's less work all round if there's a suitable
standard format with libraries and whatnot that can be reused, but in
the (probably more common) case that there isn't, your options
according to Fielding-REST are (a) create a standard, or (b) to
augment the client by downloading code to it. If you're merely
looking to get the job done and not to change the world, option (c)
"just make something up" probably looks quite tempting and I for one wouldn't
blame you for taking it.
We have a requirement to have comments on an application auto-moderated for obscenities etc. There will still be a real world moderating looking at comments, but they want to filter out the really bad stuff automatically.
What would be the best way to do this?
You'll want to use something like Akismet. Last I checked, it's the thing WordPress uses to prevent comment spam. It's pretty straightforward, too.
Here are a couple links:
Ryan Bates over at Railscasts
(always excellent, but a little old
so may not current with Rails 3
though)
Another tutorial on
using Akismet in Rails
Here's a gem/plugin: Rakismet
As for profanity instead of general spam, you might want something like WebPurify (first one I found). You can hack your own together by blacklisting profane words and using Ruby's elegant string handling to replace/filter them, but that would probably be a never ending battle against 1337 speak and stuff like that. Plus it's probably better practice to outsource something like that, if possible.
Auto-moderation for obcenities is always going to give problems, as shown by Jeff Atwoods Post about it: Obscenity Filters: Bad Idea, or Incredibly Intercoursing Bad Idea?.
Now, on the other hand, actively filtering Spam using an automatic (third party) text analysis tools is certainly an viable option ( Mollom for example, which also have a ruby plugin )
You can try fu-fu, not perfect but will filter out a lot.
http://github.com/adambair/fu-fu
When you start working on an existing Rails project what are the steps that you take to understand the code? Where do you start? What do you use to get a high level view before drilling down into the controllers, models, helpers and views? Do you have any specific techniques, tricks or tools that help speed up the process?
Please don't respond with "Learn Rails & Ruby" (like one of the responses the last guy who asked this got - he also didn't get much response to his question so I thought I would ask again and prompt a bit more). I'm pretty comfortable with my own code. It's sorting other people's that does my head in and takes me a long time to grok.
Look at the models. If the app was written well, this should give you a picture of its domain model, which is where the interesting logic should live. I also look at the tests for the models.
The way that the controllers/views were implemented should be apparent just by using the Rails app and observing the URLs.
Unfortunately, there are many occasions where too much logic lives in controllers and even views. That means you'll have to take a look into those directories too. Doubley-unfortunate, tests for these layers tend to be much less clear.
First I use the app, noting the interesting controller and action names.
Then I start reading the code for these controllers, and for the relevant models when necessary. Views are usually less important.
Unlike a lot of the people so far, I actually don't think tests are the place to start. I think they're too narrow, too focused. It'd be like trying to understand basic physics/mechanics by first zooming into intra-molecular forces and quantum mechanics. I also think you're relying too much on well-written tests, and in my experience, a lot of people don't write sufficient tests or write poor tests (which don't give an accurate sense of what the code should actually do).
1) I think the first thing to do is to understand what the hell the app actually does. Use it, at least long enough to build an idea of what its main purpose is and what the different types of data might be and which actions you can perform, and most importantly, why.
2) You need to step back and see the big picture. I think the best way to do that is by starting with schema.rb. This tells you a few really important things:
What is the vocabulary/concepts of this project. What does "User" actually mean in this app? Why does the app have both "User" and "Account" models and how are they different/related?
You could learn what models there are by looking in app/models but this will actually tell you what data each model holds.
Thanks to *_id fields, you'll learn the associations between the models, which helps you understand how it all fits together.
I'd follow this up by looking at each model's *.rb file for (hopefully) comments, validations, associations, and any additional logic relevant to each. Keep an eye out for regular ol' Ruby classes that might live in lib/.
3) I, personally, would then take a brief glance at routes.rb as it will tell you two key things: a brief survey of all of the actions in the app, and, if the routes and controllers/actions are well named and thought out, a quick sense of where different functionality might live.
At this point you're probably ready to dig into a specific thing you need to learn. Find the controller for the feature you're most interested in and crack it open. Start reading through the relevant actions, see which models are involved, and now maybe start cracking open tests if you want to.
Don't forget to use the rest of your tools: Ruby/Rails debuggers, browser dev tools, logs, etc.
I would say take a look at the tests (or specs if the project uses RSpec) to get an idea at the high-level of what the application is supposed to do. Once you understand from the top level how the models/views/controllers are expected to behave, you can drill into the implementations.
If the Rails project is in a somewhat stable state than I have always been a big fan of using the debugger to help navigate the code base. I'll fire up the browser and begin interacting with the app then target some piece of functionality and set a breakpoint at the beginning of the associated function. With that in place I just study the parameters going into the function and the value being returned to get a better understanding of what's going on. Once you get comfortable you can modify the functionality a little bit to ensure you understand what's going on. Just performing some static analysis on the code can be cumbersome! Good luck!
I can think of two reasons to be looking at an existing app with which I have no previous involvement: I need to make a change or I want to understand one or more aspects because I'm considering using them as input to changes I'm considering making to another app. I include reading-for-education/enlightenment in that second case.
A real benefit of the MVC pattern in particular, and many web apps in general is that they are fairly easily split into request/response pairs, which can to some extent be comprehended in isolation. So you can start with a single interaction and grow your understanding out from that.
When needing to modify or extend existing code, I should have a good idea of what the first change will be - if not then I probably shouldn't be fooling with the code yet! In a Rails app, the change is most likely to involve view, model or a combination of both and I should be able to identify the relevant items fairly quickly. If there are tests, I check that they run, then attempt to write a test that exposes the missing functionality and away we go. If there are no tests then it's a bit trickier - I'm going to worry that I might inadvertently break something: I'd consider adding tests to give myself a more confidence, which will in turn start to build some understanding of the area under study. I should fairly quickly be able to get into a red-green-refactor loop, picking up speed as I learn my way around.
Run the tests. :-)
If you're lucky it'll have been built on RSpec, and that'll describe the behavior regardless of the implementation.
I run rake test in a terminal
If the environment does not load, I take a look at the stack trace to figure out what's going on, and then I fix it so that the environment loads and run the tests again
I boot the server and open the app in a browser. Clicking around.
Start working with the tasks at hand.
If the code rocks, I'm happy. If the code sucks, I hurt it for fun and profit.
Aside from the already posted tips of running specs, and decomposing the MVC, I also like:
rake routes
as another way to get a high-level view of all the routes into the app
./script/console
The rails irb console is still my favorite way to inspect models and model methods. Grab a few records and work with them in irb. I know it helps me during development and test.
Look at the documentation, there is pretty good documentation on some projects.
It's a little bit hard to understand other's code, but try it...Read the code ;-)