Im building an API on rails and im new in this framework. I want to add a status route to the API.
For example, running in local, if i make a request to endpoint: GET /status (http://localhost:3000/status) it should have to return status code 204, just that.
How can i do it?
I was thinking of creating a model called status and just use the index method, rendering status: :204, but I think there has to be an easier way.
Thanks!
There is no need for a Status model in this example.
Add a new routes to your config/routes.rb:
resource :status, only: [:show] # note the singular `resource` instead `resources`
And add a new controller at app/controllers/statuses_controller.rb (plural here) with this content;
class StatusesController < ApplicationController
def show
head :no_content
end
end
Related
I am trying to redirect from a show action to a custom collection action, but the id param is being carried over, causing the routing to fail. A minimal example:
routes.rb:
resources :first_models, only: [:show]
resources :second_models do
get 'custom_action', on: :collection
end
first_models_controller.rb
class FirstModelsController < ApplicationController
def show
redirect_to controller: 'SecondModelsController', action: 'custom_action'
end
end
second_models_controller.rb
class SecondModelsController < ApplicationController
def custom_action
# Do something
end
end
After setting that up, navigating to /first_models/2 results in an error:
No route matches {:action=>"custom_action", :controller=>"SecondModelsController", :id=>"2"}
I cannot figure out how to strip out the id param from the original request so that the routing matches.
The reason why this happens is that you call redirect_to with a Hash argument. Internally Rails uses url_for to build the final location, which in turn uses default_url_options which uses the ID of the current resource. From the API docs:
Missing routes keys may be filled in from the current request's parameters (e.g. :controller, :action, :id and any other parameters that are placed in the path).
See: http://api.rubyonrails.org/v5.1/classes/ActionDispatch/Routing/UrlFor.html
Solution: Use a named path helper.
Run bundle exec rake routes on the command line to get a list of all your routes and named path helpers. Pick the one that you need and use it as follows:
redirect_to my_named_path_helper_path
It is not the param the problem:
class FirstModelsController < ApplicationController
def show
redirect_to controller: 'second_models', action: 'custom_action'
end
end
You can type rails routes and see all your routes and how rails recognize them.
This should work. However you can be more explicit and use:
redirect_to custom_action_second_models_path
I made custom REST action called makedefault:
class PicturesController < ApplicationController
def makedefault
...
end
end
But I get No route matches [POST] "/pictures/12" error.
In routes I've tried:
get "/pictures/:id" => "pictures#show"
But it didn't help. How can I make my own REST action and route it properly?
Since you want to create a POST route (this is what I understand from the question), you should try this:
post "/pictures/:id" => "pictures#makedefault"
The second argument after # must be pointed to your custom action.
Can you have non-restful methods in a controller which includes the WickedWizard gem?
Controller:
class Books::BookUpdateController < ApplicationController
include Wicked::Wizard
steps :title_step, :ai_archive_step, :ai_override_step #etc
def show
...
end
def update
...
end
def waterfall
...# loads of code to set up instance variables in the view, which I don't want to have to include in the normal show action for all the wizard steps.
end
end
Routes:
resources :book_update do
member do
get 'waterfall'
... and others
end
end
Version 1 and lower of the gem allows non restful actions, but this commit to solve this PR enforces step names. My error on going to this route http://localhost:3000/book_update/3949/waterfall is
Wicked::Wizard::InvalidStepError in Books::BookUpdateController#waterfall
The requested step did not match any steps defined for this controller.
I suppose I should spark up a new controller and tuck the non restful actions into there, but alternatives would be great.
You need to add:
skip_before_filter :setup_wizard, only: :waterfall
in your wicked controller
I'm creating a new webpage were my users can have profile pages, and I can't seem to find the way to make a url like this:
webpage.com/profile/username
To go to my profile_controller action index and use the variable that comes on /username.
But I can't seem to find the way.
profile_controller.rb
class ProfileController < ApplicationController
def index
profile_info = Profile.find(params[:username])
end
end
And I've tried to work it around with the routes.rb but couldn't make it...
This route in your routes.rb should map get requests on /profiles/username to the index action of your profiles controller and pass the username value in params[:username]
get '/profiles/:username' => 'profiles#index'
Rails comes with RESTful resources out of the box, but do you use those for your actual public API? If so, how would you accomplish versioning of your API i.e. example.com/api/v2/foo/bar?
Typically, APIs for my applications are indeed built on the same resources that make up the HTML interface. For some (not me), that might be just using the code that comes out of the scaffold generator—but regardless of whether I write it custom or let the generator handle it, there are very few instances where I expose resources only to the programmatic API and not to the end user view.
Versioning hasn't been a problem for the applications I've built so far, but I can think of two ways to implement it.
1) You could add routes with the prefix 'v1,' 'v2,' etc., that set a parameter that you can then access in the controller to specify the processing to occur:
in routes.rb:
map.resources :posts, :path_prefix => '/:version'
in posts_controller.rb
class PostsController < ApplicationController
def index
respond_to do |format|
format.xml do
if params[:version] == 'v1'
# ...
else
# ...
end
end
end
end
end
2) You might also consider adding a custom response format for each version
in initializers/mime_types.rb
Mime::Type.register_alias "application/xml", :v1
Mime::Type.register_alias "application/xml", :v2
in posts_controller.rb
class PostsController < ApplicationController
def index
respond_to do |format|
format.v1 do
# ...
end
format.v2 do
# ...
end
end
end
end
The former would give you URLs like example.com/v1/posts.xml and example.com/v2/posts.xml; the latter would give you URLs like example.com/posts.v1 and example.com/posts.v2