Why does params include details regarding controller and action? - ruby-on-rails

Just curious, params are supposed to be hashes containing details regarding browser requests. But debug(params) returns
controller: controllername
action:actionname
.
.
.
Is there any specific reason it contains these key-value pairs?

params comes from three sources
The URL
The query string(GET)
The post data often by form submit(POST)
The controller name and action name comes from URL. Say the url is "article/123", Rails will know:
The controller is ArticlesController - Because "article" is the first part of url
The action is #show, because the request is GET and there is an ID
Any controller and action can be recognized once you have defined them in routes.rb. Remember you need to assign controller name and action for custom route?

I'm just speculating, but this might be from the days before Rails was built on Rack. Nowadays, you would just put these things into the Rack environment (and they are probably in there now). They are probably still there for backwards compatibility.

So you can query those in before/after/around filters, views (not the best practice), and methods shared between multiple controllers

Related

How to redirect old url to new url in rails using just routes?

The old sitemap of my application has already been indexed to Google now. For some one visiting my rails app with old url shouldn't go to 404.
The old url looked like this
/search?sub_category=210
Now after making them friendly, it looks like this:
/search?sub_category=milling-and-drilling.
I tried redirecting it from controller but it causes too much issues on other things. Such as filters which are using the same params. Is there a way I can do it from routes file?
Instead of using redirect_to route_path(id) you would do redirect_to route_path(object.find_by_id(id).name)
How to redirect old url to new url in rails using just routes?
AFAIK (As far as I know), no. (if through params)
The main job of routes.rb is to determine what "code" will handle the request, particularly that which matches request.url and the request.method. It does not concern yet of the request parameters nor its values: these would be handled in the controllers itself. Although, you can route based on parameters (or any information about the "request") through a routes constraint
Alternative Solution:
Instead of finding by ID, now find by "Slug name or ID".
In your models, particularly in this specific example of yours, add something like:
class SubCategory < ApplicationRecord
# if you're using a gem for the "friendly" urls, you don't need this method, and just use theirs.
def self.friendly_find!(friendly_id)
# this may not necessarily be `name`, maybe `slug`? or depending on your case
find_by(name: friendly_id) || find(friendly_id)
end
end
And in your controllers, just replace wherever you're finding a record (maybe also to other models not just SubCategory as needed be), particularly in your search action:
def search
sub_category = SubCategory.friendly_find!(params[:sub_category])
end
NOTE: friendly_find! will raise an Error if no record is found.

How param works in rails views

I have an old app running in rails 2.3.5
In customizing, I stuck when i find a param keyword being used in views
i.e in views I can see stuffs like
unless params[:fee_collection].nil?
can someone explain to me in what context is param keyword used in rail views rather than controllers
params is a hash that contains parameters sent with the HTTP request.
You can access to this object as well from your controller or from a view. Although, the convention is to access to an instance variable (defined in your controller, e.g : #fee_collection = params[:fee_collection]) from your view.
The params variable stores a hash which contains the http parameters received in the request to this route (controller#action)
If you have a UserController with the show method, you should receive the param[:id] to identify the resource you're looking for.
If you want to send parameters, it would be either via url in a GET or a data payload on a POST request, on the most common cases.

How do I forward an action to another controller in Rails?

Rails 4 - I have an action that handles routes like www.site.com/catalog/shoes/sport/ABC123 for product and www.site.com/catalog/shoes/sport for category
The problem is I have to display some seo-paid links (not my choise, I just have to) in format www.site.com/href, and that link must me handled as some product category. That's not the only case - in future, there might be some other "short"-links, that are pointing to other parts of my site
When I used Symfony, I could just write $this->forward('controller', 'action') and get another controller's output while saving short route, but in Rails I see only redirect_to, and it does not preserve short url?
Assuming I have a route get ':href' => 'index#simple', as: :simple, how do I forward execution to another controller (or just call controller's method?), preserving original route? - In "rails way", of course
Thank you
You can just use 'redirect_to controller_action_path' / redirect_to '/controller/action' from your controller action.

what are the sequence of events that happen when you get a page

Im trying to get my head around the sequence of events that happen between when rails receives a get/post command and the page is served. I was just trying to map out the sequence myself and i realised i dont fully understand myself which scripts is even ran first so I'd like to clear it up in my head.
many thanks
jon
The request goes into the route matcher which parses the URL, parses the config/routes.rb and if the URL matches a route, it looks for a controller file whose name matches the controller part of the URL, (e.g. http://localhost/categories will look for a CategoriesController)
Then, one of two things happen:
If you're using a Rails restful route, the route matcher applies heuristics to figure out which of the 7 actions to call: a GET on a plural last part is mapped to index; a GET mapped to an ID-looking part after the plural is mapped to show (e.g. categories/1 or categories/something or categories/1-something); a POST to a plural last part is mapped to create; a PUT to an ID-looking part after the plural is mapped to update; a DELETE to the same URL is mapped to destroy; new and edit are mapped to GETs for categories/new & categories/edit.
If you have a custom action, you must have a method in your controller object of the same name.
The chosen action is executed and then Rails either renders the template/file/action specified in the render call within the action or it looks for a view file of the same name as the action and that ends with .html.erb (by default) in the app/views/ directory.
Simple.
Rails does quite a lot of things, a good way to get a decent overview is to read the "Action Controller Overview" document at rails guides: http://guides.rubyonrails.org/action_controller_overview.html
The basic structure is:
rack middleware
routing
filters
controller code
rendering
filters
But rails also does many things by itself to the request. It automatically determines what kind of response you want based on your accept headers, and/or if you manually specify which type of response you want with a file ending like /blog/1.xml. Rails also magically creates a nicely formatted params hash, parsing params like user[name]=foo to {:user => {:name => "foo"}}. Rails also has built-in exception handling and some nice stuff to prevent cross site request forgery and much more, so check out the Controller Overview for the lowdown on that.

Create a routes to a controller without model with a /id

I have product with a foreign collection_id key
I want to pass an id to a controller.
To do so i have the following routes for my controller :
controller :magasin do
get "magasin" => "magasin#index"
end
The only view in my controller is magasin/index.html.erb
The link to magasin is link_to collection.nom, magasin_path(collection)
This kind of syntax usually works in controllers with models. Here my link is : http://localhost:3000/magasin.2 instead of http://localhost:3000/magasin/2
Later on i will need to call the same view with product_kind_id instead of collection_id and i will add sort by name/price ....
How can i have the ID as a normal argument (/:id)instead of a type(.id)?
A popular URL schema to follow is RESTful routing. Rails has this built-in and will set it up for you if you initialize your resource via rails generate scaffold Magasin nom:string.
If you put resources :magasins in your routing file, it will route /magasins to MagasinsController#index and /magasins/1 to MagasinsController#show with params[:id] set to "1". It will also set up a few other routes that will be useful in the future but for now will just raise an action not found exception.
You don't want to use the dot as an argument delimiter, since Rails places what comes after the dot in the request.format method or just in params[:format] (ordinarily accessed through the respond_to method that comes with the generated scaffolds). Save that dot for later when you are working on delivering alternative display formats like XML and JSON.
I realize I've said a lot in a small space, so feel free to ask any follow up questions once you've consulted the Rails Guide on the issue, and I'll be very glad to help!

Resources