I am setting up my Rails API server following this tutorial: building-awesome-rails-apis-part-1
Everything works well, except the part that mentions that it is not necessary to indicate the namespace in the route. Eg.
Now our URls look like: http://api.example.com/v1/people or just
http://api.example.com/people if you don’t use the version, it
doesn’t interfere with your regular people routes, and it looks great.
When I call http://api.mydomain.com/v1/therapists/ it works, but when I try to omit the v1 namespace in the URL it's not working, do I need to do any extra configuration?
I'm using Rails 6.0.3.4
This is my specific routes.rb file:
Rails.application.routes.draw do
namespace :api, :path => "", :constraints => {:subdomain => "api"} do
namespace :v1 do
resources :therapists do
resources :appointments
end
end
end
end
Solution
As zhisme suggested, I used rack-rewrite gem to do what I wanted.
First, I added the gem to my Gemfile:
gem 'rack-rewrite', '~> 1.5', '>= 1.5.1'
After that I added the configuration in config/application.rb file
config.middleware.insert_before(Rack::Runtime, Rack::Rewrite) do
rewrite '/therapists', '/v1/therapists'
end
And it worked.
In order to achieve this, you will need to insert inside Rack code. There is a gem rack-rewrite that can do redirects before Rails code execute, thus before rails routes resolving. Check their README for installation.
so modifying README example to your question, you can do something like
config.middleware.insert_before(Rack::Runtime, Rack::Rewrite) do
rewrite '/api/therapists/appointments', '/api/v1/therapists/appointments'
end
or you can make redirects to give your api consumers to know that correct url is a bit different
config.middleware.insert_before(Rack::Runtime, Rack::Rewrite) do
moved_permanently '/api/therapists/appointments', '/api/v1/therapists/appointments'
end
There is quite good article describing different solutions, take a look for more details.
If you omit the v1 namespace in the URL, you must also remove it from your routes.rb file.
The quote from the tutorial stated "or just http://api.example.com/people if you don’t use the version", meaning if you don't include the v1 namespace in the routes.rb file.
Related
I have an application my_app, and an engine my_engine.
my_app routes:
Rails.application.routes.draw do
mount MyEngine::Engine => "/api"
end
my_engine routes:
MyEngine::Engine.routes.draw do
post "files/sync" => "files#sync"
end
From my_app, I run rails routes, and see the following:
Prefix Verb URI Pattern Controller#Action
my_engine_engine /api MyEngine::Engine
Routes for MyEngine::Engine:
As you can see, Routes for MyEngine::Engine: displays 0 results. I've tried every answer in the books about this issue, but nothing works.
Why are my engine routes not being listed by the app?
(Note that my_engine is a local gem — do I have to do something special to reload it possibly?)
One solution turned out to be changing:
gem 'my_engine', path: '/Users/me/Desktop/my_engine_gem'
to:
gem 'my_engine', path: '/Users/me/Desktop/my_engine_gem', require: 'my_engine'
This worked, even though placing require 'my_engine' in an initializer did not work. Not sure what the distinction is.
I'm writing a gem and I'm going to use it with Rails 4. Is it possible for me to add a route from my Gem rather than from config/routes.rb in my rails project? I want this to be inside a gem so I can include it in more than one Rails project without having to configure every Rails project, rather do it once in the gem. Is that possible and how?
i.e :
If my routes were :
get 'test' => 'users#test'
how would that translate into my gem. If my gem were used as an engine just like RB suggested in his answer :
module Blorgh
class Engine < ::Rails::Engine
get 'test' => 'users#test'
end
end
This doesn't work, what am I doing wrong?
Read the Engine Guide of Ruby on Rails. Basically you'll want to create the file in config/routes.rb (on your gem folder) and add the following:
YourGemName::Engine.routes.draw do
get 'test' => 'users#test'
end
Yes it is possible if you make your gem an engine.
Read the Getting Started with Engines guide.
I've been creating a gem and I need to create a route that maps to a controller in the gem.
I have a file ( config/routes.rb ) which looks like this:
Rails.application.routes.draw do
match "rest/*path" => "bconnected/apis#rest"
end
My controller lives in *app/controllers/bconnected/apis_controller.rb*
My gemspecs file includes all of these files.
I run gem build, and gem install.
I include my gem in the rails Gemfile but when I try to hit that URL I get:
No route matches [GET] "/rest/test"'
Do I need to do anything special for Rails to read my routes.rb file from the gem?
I'm new to Ruby on Rails (formerly and currently PHP expert) so forgive my ignorance but I'm trying to get Sinatra working as middleware to redirect some old urls since I tried the gem rack-rewrite and couldn't get that to work either.
I am using code samples from ASCIIcast so in my routes.rb I have the following:
root :to => HomeApp
(^ I'm redirecting the root only for testing)
In my lib folder I have home_app.rb
class HomeApp < Sinatra::Base
get "/" do
"Hello from Sinatra"
end
end
When I start the server (or if its already running) it produces the error:
routes.rb:10: uninitialized constant HomeApp
Which seems that it just isn't aware of the lib/home_app.rb file.
I have included Sinatra in my Gemfile and ran bundle install and confirms it is included.
I just want to reroute old urls from my old site to my new ruby app but can't get any of this middleware/rack stuff working. All documentation assumes you aren't a total newb or is for RoR pre-3.0.
You don't need to use Sinatra if you want to redirect some URLs. You can use the new redirect method. See the Rails Dispatch article.
match "/stories/:year/:month/:day/:name" => redirect("/%{name}")
constraints :user_agent => /iPhone/, :subdomain => /^(?!i\.)/ do
match "*path" => redirect {|params, req| "http://i.myapp.com/#{req.fullpath}" }
end
In your specific case, the problem is that the HomeApp class is not loaded. Either add the /lib folder to your load path changing application.rb
config.autoload_paths += %W( #{config.root}/lib )
or require the file.
I'm trying to get a sinatra app as a subpath in my rails 3 app.
Specifically, the resque queuing system has a sinatra based web interface that I would like to have accessible through /resque on my usual rails app.
You can see the project here: http://github.com/defunkt/resque
I found some people talking about adding a rackup file and doing this sort of thing:
run Rack::URLMap.new( \
"/" => ActionController::Dispatcher.new,
"/resque" => Resque::Server.new
)
But I don't really know where to put that or how to make it run. My deployment is with passenger, but it would me nice to also have it running when I run 'rails server' too. Any suggestions?
--edit--
I've made some progress by putting the following in config/routes.rb:
match '/resque(/:page)', :to => Rack::URLMap.new("/resque" => Resque::Server.new)
Which seems to work pretty well, however it loses the public folder, (which is defined within the gem I guess), and as a result, there is no styling information, nor images.
You can setup any rack endpoint as a route in rails 3. This guide by wycats goes over what you are looking for and many of the other things you can do in rails3:
http://yehudakatz.com/2009/12/26/the-rails-3-router-rack-it-up/
For example:
class HomeApp < Sinatra::Base
get "/" do
"Hello World!"
end
end
Basecamp::Application.routes do
match "/home", :to => HomeApp
end
Yehuda (/Scott S)'s solution doesn't work for me with Rails 3.0.4 and Sinatra 1.2.1... setting :anchor => false in the matcher is the key:
# in routes.rb
match "/blog" => MySinatraBlogApp, :anchor => false
# Sinatra app
class MySinatraBlogApp < Sinatra::Base
# this now will match /blog/archives
get "/archives" do
"my old posts"
end
end
(answer c/o Michael Raidel - http://inductor.induktiv.at/blog/2010/05/23/mount-rack-apps-in-rails-3/)