I have an application where the user modifies an object at a time, and this object have multiple child objects. What I need is to place the id, or any other identifier, as a global param in the URL, for exemple:
mysite.com/:budget_id/accounts
mysite.com/:budget_id/payess
And starting from this point I can get this budget_idin the application controller or any other place I need.
Any suggestion on how doing this on the routes.rb file, or any other approach?
Use a scope.
In routes.rb:
Rails.application.routes.draw do
scope "/(:budget_id)", defaults: {budget_id: "1"} do
...
end
end
Related
I have to modify the routes file in order to have SEO improvement.
This is my context, a rails backend generate a JSON feed with the route's name in, I have to read it and change the default name.
For example, I have this:
get '/people' => 'people#show', as: :people
and I'd like to change /people in some value read from my JSON feed.
I created a class to get the JSON object in my app
class JSONDatabase
def initialize(kind_of_site)
#kind_of_site = kind_of_site
end
def fetch_database_remote(url)
JSON.parse(open(url).read)
end
end
but how can i access it in routes file?
Thank you
You don't necessarily need to modify your application's routes. What you can do is define a wild card route that leads to a unique controller where you read the updated route. This approach is kind of hackish but gives you the unlimited routes you need without modifying the routes.
Your config/routes.rb file would look something like this:
resources :defined_models
root to: 'controller#action'
# At last we define the wildcard route
get '/:route' => 'routing_controller#routing_action'
Then, at this routing action we can do the job of seeing if this route (now defined in the params[:route] variable) corresponds to the modified one. Just remember to redirect to a 404 if the route given is not defined, since with this approach you loose the Rails default way of dealing with undefined routes.
I have a controller, clients_controller, with corresponding index, show, edit, delete, new & form views. Is there a way to create a new view like clients/prospects.html.erb that acts the same way as clients/index.html.erb, except is routed at clients/prospects/?
I've tried this:
match '/clients/prospects' => 'clients#prospects'
And some other things in routes.rb, but of course get the error "Couldn't find Client with id=prospects".
The goal here is basically to have a prospects view and a clients view, and by simply switching the hidden field to a 1, it (in the user's mind) turns a prospect into a client (it's a CRM-like app).
There's a couple of things you need to do. First you need to put the your custom route before any generic route. Otherwise Rails assumes the word "prospects" is an id for the show action. Example:
get '/clients/prospects' => 'clients#prospects' # or match for older Rails versions
resources :clients
Also you need to copy / paste the index method in your ClientsController and name it prospects. Example:
class ClientsController < ApplicationController
def index
#clients = Client.where(prospect: false)
end
def prospects
#prospects = Client.where(prospect: true)
end
end
Lastly, you need to copy the index.html.erb view and name the copy prospects.html.erb. In the example above you would have to work with the #prospects instance variable.
Create a new action in clients controller named prospects. And then define a collection route in routes.rb for it as either resource full way. Or u directly use match as you were doing.
What you're doing is not wrong (although I'd change match to get, otherwise POST and DELETE requests to that url will also render your prospects view). Presumably you have
resources :clients
in your routes file? If so, what you have will probably work if you just move the line you quoted above the resources declaration -- the problem is that /clients/prospects matches the show route for the clients resource, so if it's defined first then that's the route that gets matched.
However, there's a more idiomatic way to define this route
resources :clients do
collection do
get :prospects
end
end
See Rails Routing documentation for more
Also see migu's answer for what else needs to be done once the url is being routed correctly (though there are other things you can do -- if you the two views are similar enough, you can reuse the view template, for example).
i have a task to create mapping of different urls at run time .
In the application i have a GUI interface which displays list of routes from routes.rb file.
User has the ability to change that url to some different name from the interface
eg. (abc/mno) --user can change them to --(hello)
so if user type /hello in the browser request is redirected to /abc/mno
i have to store those mapped routes in a database.
how to add a dynamic mapped route to already defined routes(routes.rb) while creating a new record in database
how to add routes from the database while loading routes.rb file.
i am not able to figure out how to extend the default router so that it can include routes from the database ..
I don't have a complete solution for you, but you can start with two approaches:
Use custom URL constraint: Dynamic URL -> Controller mapping for routes in Rails
Use Rack middleware: Dynamic Rails routing based on database
If you don't want to use rack middleware, you can use constraints. Hopefully, your dynamic routes are scoped to something, like "/abc/anything-after-here-can-be-dynamic", as opposed to straight off the root...
So, lets say you wanted dynamic routes based upon User's first name, then you would do the following:
#config/routes.rb
match '/abc/:route' => "abc#dynamicroute", :contraints => DynamicRouteConstraint.new
#lib/dynamic_route_constraint.rb
class DynamicRouteConstraint < Struct.new
def matches?(request)
User.find_by_first_name(request.params[:route]).present?
end
end
#app/controllers/abc_controller.rb
class AbcController < ApplicationController
def dynamicroute
#user = User.find_by_first_name(params[:route])
#render or redirect, however you wish
end
end
I'm trying to access a resource in my rails app that I want to populate with information based on the variable in the URL. Given the URL:
someapp.com/resources/variable/resource
I would like to pass the variable to Rails to add elements to resource. Is there any quick re-routing way of achieving this? Or is it insanely complicated?
Cheers!
No part of this should be "insanely complicated", but it's not very clear what you're trying to accomplish.
You could try adding a route with a variable segment:
get "/resources/:variable/resource" => "controller#action"
Then, in your controller, access params[:variable].
If your already have a resource defined, you can add an additional "member" route via the following:
resource :resources do
get :resource, on: member
# or
member do
get :resource
end
end
Either of the previous will allow your controller to route /resources/:resource_id/resource to the resources controller's resource action.
I need to get url info in my plugin's module.
request.request_uri is unavailable.
Has ruby/rails an analog of $_SERVER['REQUEST_URI'] as php?
For example:
module MyPlugin
module Routing
def self.getOpts
# HIRE I NEED TO ANALYZE URL and return hash with resulting param
return {controller: :divisions, action: :show, id: 11, as: :current}
end
end
end
# extend routing
module ActionDispatch::Routing
class Mapper
def my_rout
match 'articles', MyPlugin::Routing.getOpts
end
end
end
# In config/routes.rb
Rails::application.routes.draw do
my_rout
end
That's what I need for example:
We get an url http://mysite.ru/slug_division_1/slug_division_2
division with id 2 have in DB table a field 'handler' with value 'any_controller#any_action'
In MyPlugin::Routing i'm doing analyze the url path and get from DB the value 'any_controller#any_action'
MyPlugin::Routing.getOpts return params {controller: :any_controller, action: :any_action, id: 2, as: :current}
From ActionDispatch::Routing.Mapper.my_rout we set new rout like this
match 'slug_division_1/slug_division_2', {controller: :any_controller, action: :any_action, id: 2, as: :current}
Just a little hack.
How to make the request_uri a global variable in rails?
1) Add to folder 'vendor/plugins/myplugin/lib/myplugin' file request_global.rb with folowing code:
module Rack
class MethodOverrideWithParams < Rack::MethodOverride
def call(env)
$request = Rack::Request.new(env) # $request is global vriable
super(env)
end
end
end
2) In vendor/plugins/myplugin/lib/myplugin.rb add:
require 'myplugin/request_global'
3) In config/application.rb add:
config.middleware.swap 'Rack::MethodOverride', 'Rack::MethodOverrideWithParams'
4) VoilĂ , $request is now available from anywhere point the Rails application!
In my case it's useless because doing every time a database query for each $request to get the handler need to reload the routes (Rails::Application.reload_routes!). It degrades the performance. Defining all possible routes is more profitable even if these routes a few thousand. Reload the routes occurs only if someone edited the divisions.
Yes, try using request.request_uri.
request.request_uri is the way to find the information you want. If you don't have access to it then you need to add a parameter to your function and call it from some place that does have access.
From memory Controllers do have access to the request_uri.
I think what you actually want is just one controller/action route in your table that accepts any paths, and in the controller action do the lookup and call the relevant function. Check out path globbing (using the '*' character in Rails 2.3, not sure if you're using Rails 3), and see if that fits what you are doing.
Then what you'll have is a single route that takes a long path, the controller and action breaks that path up into its own parts, performs the lookup, and calls the appropriate function (or other controller/action).
However I have to say a few words about a few things that I think you're doing wrong.
Unless you're doing something very tricky and quite out of the ordinary, don't store the controller and action in the database. That's what the ruby routes are for themselves. If you need to store these in a database then it sounds to me like you're doing it wrong.
You shouldn't hard code an id number into a route, let that be a variable that gets set. So instead of hard coding /some/thing/23 to match 'some/thing/23', instead make the route match 'some/thing/:id', and you'll get :id => 23 automatically.