I have the following call:
http://localhost:3000/arc/v1/api/menus/51/only_items_with_notes
and I'm curious what is the preferred structure of the url - This reads fine and is totally clear what it means. But I am not sure if this is the canonical way to do this. One issue is that it does proliferate the routes.rb file. I have:
get '/menus/:menu_id/only_items_with_notes' => 'api_menus#only_items_with_notes'
One think I don't like is that it reads a bit like a pseudo nested attribute. What is the proper, canonical way to do this?
That’s pretty deep nesting. What other routes do you have?
In the absence of more information, I’d suggest that only_items_with_notes is really a filter on the functionality of the index action. You can use a query parameter to restrict the items to those with notes.
Related
Simple question, in terms of best practice is it better to format my URL like this:
http://www.example.com/search?query=hello&page=1
or like this:
http://www.example.com/search/hello/page/1
Can you provide a valid reason for your choice please.
First one fits the situation where you want to "filter" your result if it gets a little too complicated, like this example:
cars.com/audi/sedan/a/4/black/manual.....
this is gonna take so long and complicated and result will be nightmare, but this would work better:
cars.com/mercedes/amg?color=white&transmission=manual
2nd way is just like thinking it of a 'folder'ed structure:
socialmedia.com/shares/1/comments/1/page/2
I am pretty sure you get the idea.
p.s. if you will provide your API to a brand new clients, who don't know anything about it, then first one is also more understandable but, i suggest you also have a API documentation which describes the parameters and the relevant poasible other calls as well. in this way your url formatting will be clearer and clients will not struggle to solve parameters in the url.
The first way is not only functional, but lets a human understand what the name/value pairs are. Sure you could go into configuration and string manipulation and make your URL look like the second example and still function, but from a readability pov and ease of function, the first one is best.
I'm continuing my experiments with falcor and enjoying most of it, but I'm noticing something concerning.
I'm assembling my JSONGraph from multiple disparate APIs, exactly what falcor-router is intended to do. However I can't seem to find a way to cleanly provide a catch-all for fields that don't need special handling w/o blowing up any routes that do need to do special handling.
My routes look something like the following:
items[{integers:ids}].name
items[{integers:ids}][{keys:fields}]
No matter the order I declare the routes in the generic one always wins. Is there a better way to avoid this than the full-nuclear option of structuring my routes like this?
items[{integers:ids}].name
items[{integers:ids}]['fooga', 'wooga', 'booga', 'tooga', ... ]
That seems very brittle, if the data coming from the backing server changes I have to update not only my application code but my router as well. It also becomes a real mess if you have deeply nested objects as the number of permutations climb in a hurry.
I believe this is a bug. The router should match the most specific path first. I would appreciate if you could log it as an issue. We will fix it for you.
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.
I have a rails 3 app and now i implementing filter for my catalog. Filters form pass data to controller through GET request. As a result i have link like this in my browser after i submit
my form (apply search):
http://localhost:3001/shoes?filter%5BShoeBottomType%5D%5B%5D=2&filter%5BShoeClassification%5D%5B%5D=1&filter%5BShoeClassification%5D%5B%5D=2&filter%5BShoeElation%5D%5B%5D=3&filter%5BShoeElation%5D%5B%5D=4&filter%5BShoeElation%5D%5B%5D=5&filter%5BShoeLiningColor%5D%5B%5D=2&filter%5BShoeLiningColor%5D%5B%5D=3&filter%5BShoeLiningColor%5D%5B%5D=4&filter%5BShoeTopColor%5D%5B%5D=1&filter%5BShoeTopColor%5D%5B%5D=2&filter%5Bonly_action%5D%5B%5D=1&page=2
Is there a way to do URL more beautiful?
PS i dont want use POST request, because I read that it is bad for SEO
TLDR: just leave it.
HTML forms serialize in a straightforward manner; the parameters are named after the HTML elements. The actual issue here is how the form elements are named. It looks like they have names like filter[ShoeBottomType][]; look into your HTML to see the name attributes. Since you're in Rails, I'm guessing you having a filter hash passed to your Rails controller method as a single argument, and since Rails expects hashes to use a certain URL format for hashes and arrays (it has to know how to deserialize it from the request), the form helper writes the form that way. And yours is especially complicated because the hash values are arrays, hence the extra set of brackets. Then it's URL encoded and you end up with an ugly mess.
You could avoid some of this problem by passing the inputs individually back to the controller instead of as a big hash. Something like:
def index
shoe_bottom_types = params[:bottom_types]
shoe_classifications = params[:classifications]
shoe_elations = params[:elations]
...
which will get you to: /shoes?bottomTypes[]=1&bottomTypes[]=2.... That doesn't seem much better, and now your controller is all gross. And I don't see how you're going to get rid of the brackets entirely if you want to have more than one of the same filter. I guess you could get crazy and do your own parsing in your controller, like breaking apart shoeBottomTypes=1|2, but then you'll have to do your own form serialization too. Again, just not worth it.
Backing up for a sec, the SEO stuff doesn't make much sense. Search engines won't fill out your form; they just follow links. The real reason you should use GET is that (presumably), submitting your form doesn't have side effects, since it's just a search. See here; it's important to use the right HTTP methods. If you use POST, you'll get weird warnings on reloads and you won't be able to bookmark the search.
Backing up even further, why do you care, especially now that SEO is out of the picture? Just as a quick demo, I did a google search for the word "thing" and this was the URL:
https://www.google.com/#hl=en&output=search&sclient=psy-ab&q=thing&pbx=1&oq=thing&aq=f&aqi=g2g-s1g1&aql=1&gs_sm=3&gs_upl=764l1877l0l1980l6l6l0l0l0l0l89l432l5l5l0&bav=on.2,or.r_gc.r_pw.r_cp.r_qf.,cf.osb&fp=220ef4545fdef788&biw=1920&bih=1086
So URLs for form submissions can be long. The user won't even look at it.
The only possibility I can think of for why you'd care about the length/ugliness of your URL here is that you want, separately from the form, to create links to certain searches. There are several ways to handle that, but since I don't know whether that's relevant to you, I'll let that be a follow-up.
So bottom line, it looks like I'd expect, and trying to fix it sounds ugly and pointless.
If you do not want to use a POST request, then there is no other way then to put the form values in the URL -- they have to get to the server one way or another.
On the other hand however, I do not see why doing a POST would be bad for SEO and I would love to see the article that stated so.
My suggestion is that you could add some custom routes to beautify your urls.
For example :
http://localhost:3001/shoes/Type/2/Classification/1,2/Elation/3,4,5/LiningColor/2,3,4/TopColor/1,2/only_action/1/page/2
This is far much shorter than your initial URL ;)
The counterpart is that, as far as I know, you have to use always the same order for params in your url.
The routing rule is the following :
match "shoes/Type/:type/Classification/:classification/Elation/:elation/LiningColor/:liningcolor/TopColor/:topcolor/only_action/:only_action/page/:page" => "shoes#show"
You can retrieve the passed values in params array. You have to split the string containing , in order to retrieve the multiple values.
I am trying to write a route that matches the following URL format:
/category1/category2/S/
where the number of categories is unknown, so there could be 1 category or there could be 10 (1..N).
I cannot use a catch all becuase the categories are not at the end of the URL.
I am actually routing to a web form here (using Phil Haack's example http://haacked.com/archive/2008/03/11/using-routing-with-webforms.aspx), but that is beside the point really.
Any ideas?
To be honest, I found the answer here to be more useful: Using the greedy route parameter in the middle of a route definition
The blog post linked to in the question was extremely useful: http://www.thecodejunkie.com/2008/11/supporting-complex-route-patterns-with.html
I think it's impossible but you could try work around it using this route:
{categories}/S
Then split the categories using the '/' character yourself.
I made a site where I just fixed it to 1-3 categories by registering 3 routes, but I had to work around a lot of things and wasn't really happy with it afterwards.
EDIT: Using S/{*categories} will catch the categories. You can only use it at the end of the URL.
Exactly what you need(ed)
This is a long time lost shot, but I seem to have exactly what you need. I've written a GreedyRoute class that allows greedy segment anywhere in the URL (at the beginning, in the middle or at the end - which is already supported).
You can read all details on my blog as well as getting the code of this particular class.
The main thing is it supports any of these patterns:
{segment}/{segment}/{*segment}
{segment}/{*segment}/{segment}
{*segment}/{segment}/{segment}
It doesn't support multiple greedy segments though (which is of course possible as well but has some restrictions that should be obeyed in that scenario), but I guess that's a rare example where that could be used.