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?
Related
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.
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 have a gem that I am making and it is located at the same level as a rails app.
I am trying to use the gem in the rails app, but am not able to make it work - the constant I am trying to use, which is defined in the gem, is not accessible to the rails app for some reason.
What am I doing wrong here? What steps can I take to begin debugging the cause of the problem?
In the rails console, $:.grep /mygem/ shows me ["/Users/zabba/mygem/lib"]
Directory structure, with the contents of certain files:
~/mygem/
lib/
mygem/
some_class.rb
module Mygem
class SomeClass
end
end
mygem.rb
require 'mygem/some_class'
~/railsapp/
Gemfile:
gem 'mygem', path: '../mygem', require: 'mygem'
app/
models/
a_model.rb:
# require 'mygem' cannot find file
class AModel
def hello_world
SomeClass.new # Cannot find constant
Mygem::SomeClass.new # Cannot find constant
end
end
Can you create a folder vendor/gems and copy your gem in there. Then in you Gemfile
Gemfile
gem 'mygem', :path => "vendor/gems/mygem-0.0.1"
Then bundle install
My environment:
Rails 3.2.8
Ruby 1.9.3p194
Fedora 16 x86_64
This problem seems specific to Rails Engines.
It seems that when using the HttpHelpers in a Rails Engine's routes file, I get "uninitialized constant Controller" when accessing a route via a browser. But, if I use a URL matcher in the Engine's routes file, it routes correctly.
Here's how I created a failing example:
$ rails plugin new my_engine --mountable
$ cd my_engine
$ rails g controller things index
$ rails s -p 3005
The controller generator uses the HttpHelpers#get method by default, so at this point the Rails Engine's config/routes.rb file looks like:
MyEngine::Engine.routes.draw do
get "things/index"
end
And, the test/dummy application's config/routes.rb file looks like:
Rails.application.routes.draw do
mount MyEngine::Engine => "/my_engine"
end
So, I should be able to hit http://locahost:3005/my_engine/things/index and see the Things#index view from the Engine. But, instead in the browser I see:
Routing Error
uninitialized constant ThingsController
If I manually change the Engine's config/routes.rb file to:
MyEngine::Engine.routes.draw do
#get "things/index"
match "things/index" => "things#index"
end
... and hit http://locahost:3005/my_engine/things/index, I see the correct Things#index view.
I noticed that when I use the HttpHelpers#get method in the Engine's config/routes.rb file, and run rake routes from the test/dummy directory, I see:
$ rake routes
my_engine /my_engine MyEngine::Engine
Routes for MyEngine::Engine:
things_index GET /things/index(.:format) things#index
But, if I change the Engine's config/routes.rb file to use the URL matcher method, I see:
$ rake routes
my_engine /my_engine MyEngine::Engine
Routes for MyEngine::Engine:
things_index /things/index(.:format) my_engine/things#index
Notice that when using the URL matcher, the controller and action are correctly namespaced under the engine. While, when using the HttpHelpers#get, the controller and action seem to be non-namespaced.
So, my question: Am I doing something wrong here? Or, is this a bug?
Note: I searched the rails issues and didn't see anything directly related to this. Though I did see several other engine and routing issues.