Route for printer-formatted ERB view - ruby-on-rails

Working with rails 3.1 here.
I'm wondering if there are any best practices for defining routes for views are meant to be sent to the printer. For instance, I have a report at "/daily" which has a print function that opens up a new nicely formatted printer view.
What URL should this view sit on? Couple ideas are:
/daily/print
/daily?media=print
What have other people used?

Either is fine.
Probably the main consideration is whether your app is public facing and accessible to search engines. Typically you want to prevent them from indexing (duplicate) content, which a printable version would be, and typically it's easier to exclude search engines (using the robots.txt file) from printable content if it's part of the path, as opposed to the query-string.
Otherwise, it's easier to just tack on the query string parameter and use that to set the printable version of your stylesheet and/or views. This approach saves having to create a new route, which may be more flexible.

Related

MVC Routing - Generate the Route URL With Good Coding Standards

I'm learning how to do routing in MVC. It seems to me that the routing API only solves half the problem. I can easily see how to map incoming URLs to controller actions and params. However, it is not obvious to me how to generate these routed URLs in the source code of my pages.
For example, in one of my views, I use this code to get the route URL:
<a class="listingResult" href="#Url.RouteUrl("ListingSEO", new { id = Model.Listing.ID, seoName = ListingController.SeoName(Model.Listing.Title) })">
This seems like poor coding practice to me for several reasons:
If the route changes in the future, I may have many places in my View code that will need updating.
The View now requires knowledge of the ListingController (maybe this is not a big deal?)
I've lost strong typing on my input params, and if I misspell the param names, my code is broken, but this doesn't generate compile warnings.
How do I observe good coding standards when I am generating route URLs? The alternative seems to be putting static functions in the controller to generate routes, which would at least address concerns #1 and #3. If I worked with you and you saw the code above, how unhappy would you be?
My recommendations:
Generate URLs in the ViewModel, not the View: This will keep your views cleaner and logic free. You can pass the UrlHelper instance from the controller to the ViewModel, which will also help for my next point...
Use a strongly-typed URL generation technique: Such as delegate-based, expression-based or code generation.
One of the purposes of using named routes is to abstract the controller/action. Your named routes shouldn't really change. At the most, you'd just change the controller/action they hit, but that happens seamlessly behind the scenes because you're using named routes.
Your view requires knowledge of the controller because you've added a dependency on it. This is bad for a number of reasons. There's many different ways you could handle this that wouldn't require a dependency on the controller, depending on what it is you're actually doing here, but at the very least, you should simply use a utility class, so at least it wouldn't be controller-specific.
The route params are intentionally not strongly-typed, because routes are flexible by design. You can pass anything you want to the action, with or without a parameter to catch it (you can use something like Request to get at it without a param).

Execute arbitrary rails 4 controller action, render to string

In Rails 4, how does one execute an arbitrary controller action and render the response to a string?
This is obviously a bad practice, but there are circumstances when it becomes very difficult to avoid:
You are making an offline copy or e-mail attachment of a dynamically rendered pdf (or any self-contained response).
Aforementioned response involves views and controllers not under your control, or in external gems.
Aforementioned views involve layouts and dozens of partials using relative paths and custom template rendering engines.
In some circumstances (when calling from another controller), it is possible to eliminate the dependency on the controller by replacing any data needed by the view. However, this typically still breaks the view rendering, as relative paths can no longer be passed to the render function within partials (among other issues).
So I haven't actually done this. Or anything like it.
But I remembered you can get a Rack app object for any arbitrary rails action. So it seemed like you could use that rack-compat interface to all an arbitrary action and get a response internally, without actually having to make an http request.
Googled around things I vaguely remembered to put the pieces together, and got this, which I have tried out in a very simple dummy app I made, and it seems to work:
rack_env = Rack::MockRequest.env_for("/some/url?foo=bar")
rack_app = SomeController.action(:index)
(status, headers, rack_body) = rack_app.call(rack_env)
str = rack_body.body
I was surprised to need to call #body on the thing I already thought was the body, not sure exactly what's going on I guess I don't entirely understand the rack api. Not sure if MockRequest is the right way to build a request. Not sure if there's a better way (but heck 3-4 lines ain't bad). But it does seem to work.
(There's probably a way to get the 'right' way to work too, with enough work -- there are for instance ways to change or add to the view template lookup paths, to put the original controller's views on the view lookup path, even when you're rendering the template from a new view. But I believe you that it gets painful, and am honestly not sure in this case what the 'right' way to do it is, I think the Rack method seems reasonable)

Change the generated EDIT routes in Rails 3.2 to put id _after_ `edit`

As well explained in the Rails Guide on Routing, a resourceful route declaration like
resources :photos
generates a suite of routes and helpers. One of the routes is
/photos/:id/edit
and along with it comes the helper edit_photo_path(photo) which takes a photo object and returns the path to use to edit it. I use the helpers everywhere and want them to keep working as-is.
Well, for various reasons, this one application is generating custom IDs and it is possible for an ID to look like 64/edit or look like 64. This of course causes problems, because regardless of constraints or tweaks
/photos/64/edit
either gets interpreted as #edit 64 or #show 64/edit and neither one is always right.
The solution I would like to implement is to keep all the benefits of resourceful routers, in including being able to pass objects into the path helpers, and just change the Rails default edit path to be
/photos/edit/:id
Then all the paths would be unambiguous. Is there a (reasonably simple and clean) way to do this?
Note
I have a workaround in place so please do not provide workarounds.
Any solution must update the helpers so that edit_photo_path(photo) produces /photos/edit/:id and also works with nested resources. For example, edit_magazine_photo_path(#magazine, #photo) would produce /magazines/:magazine_id/photos/edit/:id.
I have multiple resources, so I'd prefer not to explode the size of my routes.rb with special overrides.
I know I can change the path name of the edit portion using the path_names option. (This is, in fact what I did, putting a Unicode character that will never appear in the ID in the renamed edit path, but now I have the users seeing Unicode URLs, which I don't like, and this will fail once IDs get expanded to Unicode strings.)
I know I can write custom match rules, but that gets very tedious and difficult with nested resources, particularly when it comes to generating path helpers that take objects.
I read the answer to the question "Remove the edit suffix to url" but that answer does not, in fact, remove the edit suffix, it changes a different part of the URL.
I really want insight into the inner workings of the resourceful route generation, especially the URL helpers, so that I can just switch the order of edit and id in the path.

ColdFusion - What's the best URL naming convention to use?

I am using ColdFusion 9.
I am creating a brand new site that uses three templates. The first template is the home page, where users are prompted to select a brand or a specific model. The second template is where the user can view all of the models of the selected brand. The third template shows all of the specific information on a specific model.
A long time ago... I would make the URLs like this:
.com/Index.cfm // home page
.com/Brands.cfm?BrandID=123 // specific brand page
.com/Models.cfm?ModelID=123 // specific model page
Now, for SEO purposes and for easy reading, I might want my URLs to look like this:
.com/? // home page
.com/?Brand=Worthington
.com/?Model=Worthington&Model=TX193A
Or, I might want my URLs to look like this:
.com/? // home
.com/?Worthington // specific brand
.com/?Worthington/TX193A // specific model
My question is, are there really any SEO benefits or easy reading or security benefits to either naming convention?
Is there a best URL naming convention to use?
Is there a real benefit to having a URL like this?
http://stackoverflow.com/questions/7113295/sql-should-i-use-a-junction-table-or-not
Use URLs that make sense for your users. If you use sensible URLs which humans understand, it'll work with search engines too.
i.e. Don't do SEO, do HO. Human Optimisation. Optimise your pages for the users of your page and in doing so you'll make Google (and others) happy.
Do NOT stuff keywords into URLs unless it helps the people your site is for.
To decide what your URL should look like, you need to understand what the parts of a URL are for.
So, given this URL: http://domain.com/whatever/you/like/here?q=search_terms#page-frament.
It breaks down like this:
http
what protocol is used to deliver the page
:
divides protocol from rest of url
//domain.com
indicates what server to load
/whatever/you/like/here
Between the domain and the ? should indicate which page to load.
?
divides query string from rest of url
q=search_terms
Between the ? and the # can be used for a dynamic search query or setting.
#
divides page fragment from rest of the url
page-frament
Between the # and the end of line indicates which part of the page to focus on.
If your system setup lets you, a system like this is probably the most human friendly:
domain.com
domain.com/Worthington
domain.com/Worthington/TX193A
However, sometimes a unique ID is needed to ensure there is no ambiguity (with SO, there might be multiple questions with the same title, thus why ID is included, whilst the question is included because it's easier for humans that way).
Since all models must belong to a brand, you don't need both ID numbers though, so you can use something like this:
domain.com
domain.com/123/Worthington
domain.com/456/Worthington/TX193A
(where 123 is the brand number, and 456 is the model number)
You only need extra things (like /questions/ or /index.cfm or /brand.cfm or whatever) if you are unable to disambiguate different pages without them.
Remember: this part of the URL identifies the page - it needs to be possible to identify a single page with a single URL - to put it another way, every page should have a unique URL, and every unique URL should be a different page. (Excluding the query string and page fragment parts.)
Again, using the SO example - there are more than just questions here, there are users and tags and so on too. so they couldn't just do stackoverflow.com/7275745/question-title because it's not clearly distinct from stackoverflow.com/651924/evik-james - which they solve by inserting /questions and /users into each of those to make it obvious what each one is.
Ultimately, the best URL system to use depends on what pages your site has and who the people using your site are - you need to consider these and come up with a suitable solution. Simpler URLs are better, but too much simplicity may cause confusion.
Hopefully this all makes sense?
Here is an answer based on what I know about SEO and what we have implemented:
The first thing that get searched and considered is your domain name, and thus picking something related to your domain name is very important
URL with query string has lower priority than the one that doesn't. The reason is that query string is associated with dynamic content that could change over time. The search engine might also deprioritize those with query string fearing that it might be used for SPAM and diluting the result of SEO itself
As for using the URL such as
http://stackoverflow.com/questions/7113295/sql-should-i-use-a-junction-table-or-not
As the search engine looks at both the domain and the path, having the question in the path will help the Search Engine and elevate the question as a more relevant page when someone typing part of the question in the search engine.
I am not an SEO expert, but the company I work for has a dedicated dept to managing the SEO of our site. They much prefer the params to be in the URI, rather than in the query string, and I'm sure they prefer this for a reason (not simply to make the web team's job slightly trickier... all though there could be an element of that ;-)
That said, the bulk of what they concern themselves with is the content within and composition of the page. The domain name and URL are insignificant compared to having good, relevant content in a well defined structure.

How does rendering different formats/layouts in Rails affect SEO?

I have been reading a lot about cloaking and redirects, and am wondering how this fits into rendering and layouts in Rails...
Two parts:
1) If I have different data formats to render in (json, xml, html, and iphone), and they all use the same url, differing by the ".format" at the end, is this considered "content duplication"? It seems like you could make the search engines unhappy with this. Is there a workaround/best-practice here?
2) If I render just the model template for rails, projects/index.html in one case, and render both the model template and the layout template in another, projects/index.html and layouts/application.html, and they are at different urls, is that considered content duplication? What's best practice in this case?
layout :main # or
layout :projects # or
layout :some_condition
I have read a little about canonicalization but I'm not quite sure how that fits into these cases.
What do you normally do in this situation to prevent being banned by the search engines?
Thanks for the tips.
No, this is not content duplication because you are serving the content in different formats. It would be content duplication if you would serve the same content in the same format at more than one URL.
Yes, it could. But you need to provide more details in order to provide a more specific answer.
There are multiple solutions you can adopt:
Use a Canonical Link Tag (here's an how to with Rails)
Disable duplicate content in your robots.txt or use the no-index header/tag
Don't duplicate your content

Resources