I am building a very basic twitter-like application.
I would like to have mydomain.com/trending however I am aware that the convention would be to have "trendings" for the controller name and thus the url also - which doesn't make much sense to me, what is the best way around this, do we just mask the url some how? Or are their certain exceptions to the pluralising of controllers/views?
in your routes file do something like this
get 'trending', to: 'tweets#trending', as: :trending
Related
Given a path such as
/foos/123
and a route
get '/foos/:id', as: 'foos'
How to get the ID using Rails routes (reverse) look up?
In this example, path.split('/').last would work, and a regex would be better. But how to use the Rails routes to do it?
This functionality was provided by Rails.application.routes.recognize_path but has been deprecated.
Note: This not part of a controller. Please do not answer about how to use routes within a controller.
Rails 6.
You can't. Routing is actually a lot more complicated than that.
The routes are not just a simple static set of regexes that match a string to a controller and action. You need an entire request object. You have to remember that constraints put things like headers, cookies and even middleware like Warden in the picture.
Rails.application.routes.recognize_path was depreciated since it completely failed at handling this complexity. It just gave a false sense of simplicity which is probably the worst thing software can do.
That's probably not the clearest title ..
Essentially, what I want to do is run the path (e.g. '/sexypage') through a function, which will do some AR lookups. If a match is found, that function will handle a redirect, which is no problem, but if not I want the routes file to carry on looking for a match as normal.
Is this possible?
It is usually done in before_action of a controller
As #Ix00st says this is normally done via a controller. You can't have complicated logic or DB lookups in your routes. Any data-dependent requests should go to standard urls like /sexypage/:some_param
I'm trying to route a particular object's show method to the root path of my app, but I'm having trouble routing it anywhere at all for that matter. So I guess this break down into two questions:
If I wanted /pages/2 for example to go to the root path, how would I do this?
Also, if I wanted to make the url take a name or some attribute (eg. /username would find_by_username and show the correct page) how would I do this?
I've looked at a couple railscasts and the rails guide on routing, but I seem to be missing something...
Any help would be much appreciated.
First of all, I should warn you. Because you want to break down REST pattern. REST was well designed by clever folks and if you want to redefine some of it's functionality - so you have some incorrect logic in your App design.
Now to answer your question:
1. You can try something like this:
match "pages/:id", redirect {|params| "your_root_url" if params[:id] == 2}
2. Look at to_param documentation for more detail.
I hope i helped you alittle
I'd like to have a URL like this:
/payroll/region/1
and I'd like it to map to the Tasks Controller's payroll_list function. I'd also like to use REST. What's the best way to do this?
Many thanks!
Well I'd suggest you better go with the convention how Rails handles this. If you still insist on using such "strange" URLs and want to ignore the problems/headaches this can create during further development, then try to use Refraction.
I don't want to be rude but currently it seems to me that you did not understand why restful URLs are the way they are. Please do understand the design behind this first, then rethink your application/controller and routing design. I bet you will be enlighted.
In this example, your URL should probably be /regions/1/payrolls with map.resources :regions, :has_many => :payrolls. Then your payroll list would be rendered by the PayrollsController having a params[:region_id] - and that actually makes sense (and probably what you tried to achieve with your URL layout). Code snippet:
def index
if params[:region_id]
#region = Region.find(params[:region_id])
#payrolls = #region.payrolls
else
#payrolls = Payroll.all
end
end
If you still want to have a resource under a different named URL, use the following:
map.resources :regions do |regions|
regions.resources :tasks, :as => :payrolls
end
This will map the nested resources to the tasks controller using the named URL part "payrolls." But this probably does not work as you might expect because restful logic means you should handle the payroll model in the PayrollsController. Otherwise you might run into strange looking code. Maybe your design of the TasksController is just wrong? Rails will probably expect tasks to be handled over to your tasks controller although you name it payrolls. This can be confusing at least (however, it does not actually expect these being task models, so it will probably work).
BTW - Keep in mind: "restful" also means your application should answer to standard verbs on a resource, not just using "resourceful" routes. It's also about the GET, PUT, DELETE and POST http verbs, and of course the "edit", "new" etc default actions. Do not try to make your controllers big and complicated. Follow the motto "skinny controllers - fat models".
OK, so a better question, then might be this:
How can I get it so that I use your suggestion:
/regions/1/payroll
and have that map RESTfully to:
Tasks controller with index, new, etc that are prefixed by "payroll_"?
Like this: TasksController#payroll_index or TasksController#payroll_new
This might seem like a n00b question, but I am trying to break some of my bad practice that I may have adopted using MVC, so I hope you can help me out
So, imagine I want to do something like "Upload CSV And Parse It", it doesn't seem obvious to me to fit it into the CRUD pattern... I am not interacting with the DB, so i don't need add or update or delete, but I still want to be able to use the action in a meaningful way from different views. Thus, it is "ok" to just an action called "UploadCSV" and have it be accessible via a URL such as "/data/uploadcsv"
Your thoughts are much appreciated!
Tom
It sounds like you are talking about RESTful ideas (having actions called index, create, new, edit, update, destroy, show).
In MVC you can call an action largely whatever you want (so yes, you can call it uploadcsv if you want). If you want it fit RESTful principles you might want to think about what the action is doing (for example is a data upload essentially a create or an update function) and name it using one of the RESTful action names.
I believe I have the same point of view as you.
In my projects I try to be as restful as possible whenever I can. However as you said sometimes a special case just does not 'fit'
After all it is also a question of 'feeling'
If you provide a csv import function, I see it as perfectly correct to not create a full REST implementation for CSV.
Let's imagine in your application you have clients. And you wnat to give the option for clients to import data using csv. You can add a route for this action using:
map.resources :clients, :member => { :uploadcsv => :get }
The route is properly declared, Your 'clients' resource is completely restful and you have an additional action properly declared to manage data importation.
The only warning I have is: don't use a route like this one "/data/uploadcsv". From my point of view It lacks clarity. I like to be able to understand what my application is going to do just be looking at the url. And '/data' is too vague for me :)
The persistence of the resource is not crucial here. I suppose that what you are doing here is this - creating some kind of resource (although not persistent) out of the csv provided. The thing here is to think about what this csv file represents. What's inside? Is it something that will become a collection of resources in your system, or is it a representation of only one object in your system? If you think about it it has to be something concrete. Can you be more specific about your problem domain?