Dynamic routes in rails - ruby-on-rails

I have a rails application which, among other things, provides a simple wrapper around API calls to a third-party service. I want to set up a route which starts with /api, but anything added on to the end of it is taken as a string variable. For example, if a client requests:
/api/apps/guid/details
...then I want to invoke the index action of the controller ApiController and make the string /apps/guid/details available to it.
I have read through the documentation on controllers and routes, but everything seems to assume that /apps/guid/details will be resources within my app, when actually I don't care about the structure of anything after /api.
How can I set up a route which allows me to do this?

You can use globbing in your config/routes.rb:
get "/api/*path", to: "api#index"
Which would be accessible in the controller via params[:path]
Details can be found in the rails guide.

Related

how to fetch the route i.e path of my current api in routes.rb file

I'm new to rail. I have few clarifications, which I have listed below.
I have referred many links and stack overflow questions, everywhere it's mentioned to use request and fetch the details regarding the path, controller, action etc. but if I use request in my routes.rb it throws undefined local variable or method error.
I used constraints in my routes.rb and from there it calls a method matches? from a class where dynamic constraints are defined inside lib/constraints directory. In here the matches?(request) receives a parameter named request, which has details about current route, from where the parameter value is sent?, I have this doubt because while using this method inside routes.rn in constraint(ClassName) I'm not sepecifying the method name (matches?) or the parameter request
I would like to know the working of things behind the scene.
Thank You
Are you looking for it
request.url
# => "http://localhost:3000/lists/7/items"
request.path
# => "/lists/7/items"
If you have URIs:
localhost:3000/users/:id
localhost:3000/users
localhost:3000/users/new
....
You can do something like
rake routes | grep user
in order to get only those that contain user in its path name.
Hope this helps..
conventionally you don't access the current path in the routes.rb, at least as how it seems you're asking to access it. There are a number of different matching methods and techniques used in the rails router that serve the utility I imagine your looking for.
Here's a link to the docs: https://guides.rubyonrails.org/routing.html
Can you share exactly why you want to access the curret route in the routes.rb file?

Accessing an arbitrary action in rails

I am somewhat confused as to how to properly access an action in a rails controller that is NOT associated with one particular model. The routing file, by default, seems to be routing the action name to "id". So if I type, say, /user/login, I end up with an error that says: "Couldn't find User with 'id'= login"
What is the proper way to access arbitrary action names in rails?
Make a route for it, obviously. The request goes this way:
first it hits a route
from there it hits a controllers' action
[an action may invoke a model] (optional, but common)
controller specified a view and fetches data to render
view is sent back in response to a request
resource and resources might not be obvious about what they do. But in fact, they are shorthands to corresponding collections of routes used quite often, like this is what resources adds. And they're not monoliths, they can be customised to fit your needs. Providing options is just a start, you can provide a block to define your custom action routes for this resource like so:
resources :users do
get :login
end
This will add a /users/login route that maps to UsersController#login, following Rails' conventions.
See this guide for more details and don't forget to run rake routes to see what you have at the moment.

How to add a view in rails

I am quite new to rails but i have searched a lot how to do this but it doesnt seem to work for me. Im trying to create a new view called request for my model called steppy_steps, so i created a new file in the views directory called request.html.rb, added this to my routes, match '/request' => 'pages#request', also tried get "steppy_tests/home", and lastly added (def request, end), to my Steppy_Tests_Controller.rb but when i check the url it gives me an error:Couldn't find SteppyTest with id=home
I cant figure out what to do any help would be great! Thanks in advance.
You should read up on the MVC programming pattern (which is what Rails is based on)
In order to make a view, you need to have the controller and model aspects in place too. I think you're doing this already, but to help you understand more, I'll outline below:
Views : Controller Actions
If you want to show a view from the steppy_steps controller, you need to first have a controller action set up to handle the request. You'd normally use a self-named controller for this (controller name steppy_steps), and have various actions for that
In your routes, you'll then "capture" the request to your steppy_steps controller like this:
#config/routes.rb
resources :steppy_steps
This will create a set of RESTful routes, which you can then translate into your controller, like this:
#app/controllers/steppy_steps_controller.rb
def index
#Index code
end
def show
#Show code
end
This will allow you to create a views directory which can contain the views for /views/steppy_steps/show.html.erb and /views/steppy_steps/index.html.erb
Routes Are Super Important
The error you're getting is caused by you sending /home to your view
The problem here is that if you're using a route which has an in-built id param (the show action routes have this), then Rails will look for the extra params after the URL
To fix this, you'll have to provide more of your code, but I also believe you'd be better understanding the fundamentals of Rails a little more
Adding Routes
You can add routes & views as you wish
If you're looking to add a requests route / view, I'd do this:
#config/routes.rb
resources :steppy_steps do
collection do
get :requests
end
end
This will allow you to create /steppy_steps/requests

How do I add access controls to named routes in config/routes.rb?

I use require_admin! frequently in my controllers. It works great.
Now, I want to add named route like so:
# config/routes.rb
match "poniesandrainbows" => redirect("https://poniesandrainbows.com")
# ^sadly, not really a website, btw.^
How do I restrict access to that route? Is this possible? Obviously it redirects to a public URL, but I still want to keep the route private.
You cannot restrict access from routes.
The safest way to match "poniesandrainbows" with a controller where you can use require_admin! and then redirect them to the public url.
You can try to solve the problem on the front end. Maybe only show the link to admin users.
It won't stop other users to paste the link directly to their browser url though
That kind of functionality should be encapsulated in the controller. The router handles the plumbing of passing a request to the correct controller. It is the controller's job to correctly figure out how to process the request. In this cause, the controller would use the auth service (such as require_admin!) to determine if the user is allowed to be redirected or if they are doom to another fate.
It is actually possible although as the other posters mentioned very rarely a good idea. You can read about how in this blog post: (scroll down to the routes section)
http://collectiveidea.com/blog/archives/2011/05/31/user-centric-routing-in-rails-3/

Resolve Route Server Side in Rails

Just as you figure out the route when the browser hits the webpage in Rails, how would you resolve it on the server side?
For example I want to return a URL to a RESTful resource called Bookmark in an API call and want to return the 'show' action of it, and I know that:
Bookmark id: 12
Then I want to resolve it to a string:
'/bookmarks/edit/12'
so that I can get this from my Model for example.
How would I go about doing this?
Thanks!
Pretty much everywhere in the views/controllers you can use route helpers to DRY up route references.
In models, you'll need to explicitly call the route helper like so.
Rails.application.routes.url_helpers.edit_bookmark_path(id) # => '/bookmarks/12/edit'
When using the default resourceful route generator method in routes.rb like
resource :bookmarks
I'm not sure I understand - your server is the thing that's making all of those routes work - the client's browser isn't figuring out what the route is - you application is doing it.
The paths to your resources are available as helper methods at all times (at least within the controllers, and views). As such, you should return the string as the body of a response in one of your actions, in the controller that's handling your API calls.
Check your rake routes on the command line, and you'll see a list of them. In the case of your example above, it would likely be called edit_bookmark_path(12)

Resources