I randomly get this error when in production from certain IP Addresses on the root path. The rails app does not support the formats :formats=>[:gif, "image/x-xbitmap", :jpeg, "image/pjpeg", "application/x-shockwave-flash", "application/vnd.ms-excel", "application/vnd.ms-powerpoint", "application/msword"] so this error seems to be expected if a request is being made for them. I'm guessing that someone or some bot is trying to run an exploit against the site -- how can I redirect or route these kinds of requests back to the route path such that an error is not produced?
ActionView::MissingTemplate: Missing template front_page/index, application/index with {:locale=>[:en], :formats=>[:gif, "image/x-xbitmap", :jpeg, "image/pjpeg", "application/x-shockwave-flash", "application/vnd.ms-excel", "application/vnd.ms-powerpoint", "application/msword"], :variants=>[], :handlers=>[:erb, :builder, :raw, :ruby, :coffee, :arb, :jbuilder]}. Searched in:
* "/app/app/views"
* "/app/vendor/bundle/ruby/2.0.0/gems/activeadmin-1.0.0.pre2/app/views"
* "/app/vendor/bundle/ruby/2.0.0/gems/kaminari-0.16.3/app/views"
* "/app/vendor/bundle/ruby/2.0.0/gems/devise-3.5.2/app/views"
File "/app/vendor/bundle/ruby/2.0.0/gems/actionview-4.2.4/lib/action_view/path_set.rb", line 46, in find
File "/app/vendor/bundle/ruby/2.0.0/gems/actionview-4.2.4/lib/action_view/lookup_context.rb", line 121, in find
File "/app/vendor/bundle/ruby/2.0.0/gems/actionview-4.2.4/lib/action_view/renderer/abstract_renderer.rb", line 18, in find_template
The full error is here
To achieve the result desired in your comment:
constraints :format => "html" do
resources ...
end
Or if you need more flexibility:
# application_controller.rb
ApplicationController < ActionController::Base
before_action :check_format!
...
def check_format!
unless request.format == :html
render :nothing status: :bad_request
end
end
...
end
But overall, I feel like this is all a ton of overkill...
Plus, it's very typical to see buckets of respond_to in controllers, because the normal behaviour is to try and serve up the any format. Otherwise, there would probably be tons of configurations and such.
Is there a way to do this for all controller actions unless explicitly stated
So when you say unless explicitly stated you're sort of swimming against the current.
I'm not sure that this will work for you, but perhaps something like:
def index
...
respond_to do |format|
format.html
format.all { render status: :bad_request }
end
end
Related
I am trying to IP whitelist access to a particular file by placing a constraint on the file's route.
## config/routes.rb
get 'SOME FILE',
to: 'main#(function that renders the file as plain)',
constraints: <IP CONSTRAINT CLASS>.new
## (ip constraint class).rb
require 'ipaddr'
WHITELIST = %w(8.8.8.8/27).freeze
def matches?(request)
request && APPLE_IP_WHITELIST.reduce(false) do |match, range|
match || IPAddr.new(range).include?(request.remote_addr)
end
end
For IPs outside of the whitelist, a RoutingError is thrown. I try to handle the error by using a catch all route.
## config/routes.rb
get '*unmatched_route', :to => 'application#show_not_found', via: :all
## app/controllers/application_controller.rb
def show_not_found
render_error_status(404)
end
def render_error_status(status)
#status = status
template = case #status
when 400, 401, 403, 405
'application/errors/standard'
when 404, 422
'application/errors/with_block'
when 500
'application/errors/custom_500'
end
render template: template, layout: 'error', status: #status
end
Interestingly, when I try to access some nonsense route, like 'localhost:3000/asdf', the proper 404 page (application/errors/with_block.html.haml) is shown. However, when the whitelist RoutingError is handled, I get a
ActionView::MissingTemplate (Missing template application/errors/with_block with {:locale=>[:en], :formats=>[:text], :variants=>[], :handlers=>[:raw, :erb, :html, :builder, :ruby, :haml, :coffee]}. Searched in:
* "... /app/views"
* "... /.rbenv/versions/2.5.7/lib/ruby/gems/2.5.0/gems/kaminari-0.17.0/app/views"
):
tldr: how do I handle RoutingError resulting from a constraint failing?
Edit: it appears that formats: [:html] needs to added when calling render - but why is this necessary now and not the other times when render_error_status is called?
The main issue is with the request type, when the routing constraint fails Rails tries to find file with text format, see the error:
ActionView::MissingTemplate (Missing template application/errors/with_block with {:locale=>[:en], :formats=>[:text]
This is because you are requesting a text file from the route which cannot be returned because your routing constraint failed. So when the request type is text the error page should also be in that format. For example if I have an API where I send a JSON request and if there is an issue of permission and I provide HTML response then it will be of no use to the API. So the request and response format should be same in Rails when using the default conventions.
Your method should have different response types like this:
def render_error_status(status)
status = status
template = case status
when 400, 401, 403, 405
'application/errors/standard'
when 404, 422
'application/errors/with_block'
when 500
'application/errors/custom_500'
end
respond_to do |format|
format.html { render template, status: status }
format.text { render text: 'Not found', status: :not_found }
end
end
There are other options too available to do this like responding with HTML in case of text request but the standard Rails way is like this.
I am trying to conditionally route two different controller actions. I have created RoutesController#root and sent root there from routes.rb, however the app just wants to find a root template to render no matter what i write in the root method.
What I am trying to achieve is:
user requests ‘/’
user gets pushed to sign in
upon successful sign in if current_user.company.present? (current_user should be available in the Routes controller right?) then render Quotes#new
else if no company then render Companies#new
I'm hitting a missing template error;
Missing template companies/1/quotes/new.1 with {:locale=>[:en], :formats=>[:html], :variants=>[], :handlers=>[:raw, :erb, :html, :builder, :ruby, :coffee, :jbuilder]}. Searched in: * "app/views"
I want it to be searching in app/views/quotes/new, what am i doing wrong?
RoutesController.rb
class RoutesController < ActionController::Base
before_filter :authenticate_user!
def root
if current_user.company.present?
render new_company_quote_path(current_user)# 'quotes#new'
else
render new_company_path(current_user) # 'companies#new'
end
end
end
routes.rb
root 'routes#root'
render is used when you just want to render/display a particular view from the path, it doesn't execute any code. For detailed differences, see this post.
Thus, in your case, it should be redirect_to instead of render.
And regarding the best practice thing, it looks good to me.
i have a simple application to snooker league and i have a action add_player in LeaguesController. My client (AngularJS) call this action and i want to respond with json format using JBuilder. This working fine:
def add_player
...
render :json => #league.players.to_json(:only => [ :id, :firstname, :lastname, :max_break, :email ])
end
But when i delete this line and add:
respond_to do |format|
format.html
format.json
end
i have this error:
ActionView::MissingTemplate (
Missing template leagues/add_player,
application/add_player
with {:locale=>[:en], :formats=>[:html], :variants=>[], :handlers=>[:erb, :builder, :raw, :ruby, :coffee, :jbuilder, :haml]}.
Searched in:
* "/home/daniel/SitesWWW/snookerLeague/app/views"
):
app/controllers/leagues_controller.rb:67:in `add_player'
Of course i have file add_player.json.jbuilder:
json.players #league.players do |player|
json.id player.id
json.firstname player.firstname.capitalize if player.firstname
json.lastname player.lastname.capitalize if player.lastname
json.email player.email
json.max_break player.max_break
end
So, what i should do?
Notice in your error message :formats=>[:html] this indicates to me it is trying to render add_player.html.erb and not your jbuilder template.
To verify this, try changing the calling code and append .json to the url which will force the format to be json.
You can also specify a default of json on your routes and not include it in the url:
resources :leagues, defaults: { format: :json } do
member do
post :add_player
end
end
see also: http://guides.rubyonrails.org/routing.html#defining-defaults
I'm using a versioned API design from this RailsCasts episode and it's working great, except my jbuilder templates aren't rendering.
Here's my controller code:
module Api
module V1
class LocationsController < ApplicationController
respond_to :json
def index
#locations = Location.all
end
end
end
end
And my jbuilder file is at app/views/api/v1/locations/index.json.jbuilder
I get the following error:
ActionView::MissingTemplate (Missing template api/v1/locations/index,
api/v1/api/index, application/index with {:locale=>[:en], :formats=>[:json],
:variants=>[], :handlers=>[:erb, :builder, :raw, :ruby, :coffee, :jbuilder]}.
Searched in: * "/XXX/XXX/XXX/XXX/app/views"
EDIT: And here's the code in my routes.rb file:
namespace :api, defaults: { format: :json } do
namespace :v1 do
resources :locations, only: [ :index ]
end
end
Any ideas how I could debug this? Why are the files in the api folder not being found by Rails? Thanks!
I have this issue all the time. It can sometimes be a typo or error raised in the actual code within the json templates. Try commenting out all the lines in the index.json.jbuilder file, reload, work? Try uncommenting a line at a time. I haven't found a solution for better debugging this issue with jbuilder... yet.
in routes you should remove the defaults: { format: :json }
In my Rails app, I have in the Application controller
respond_to :json
A controller that inherits Application controller responds with json like so in the action...
# Some code
if mission_updated.eql? true
render :json => {}
else
render :json => {}
end
However, whenever I run a rspec test in reference to the above action
it "should return appropriate response" do
post :update_unlocked_missions
parsed_body = JSON.parse(response.body)
parsed_body.should == {}
end
I'm returned with the following rspec error
ActionView::MissingTemplate:
Missing template api/v1/missions/update_unlocked_missions, api/v1/base/update_unlocked_missions with {:locale=>[:en], :formats=>[:html], :handlers=>[:erb, :builder, :coffee, :rabl, :haml]}. Searched in:
* "#<RSpec::Rails::ViewRendering::EmptyTemplatePathSetDecorator:0x007f9ea2903b00>"
My question is why is it going to the view when it should respond with json and how do I fix this?
Try testing with an action that's just render json: {}. If that works, the problem is probably something in mission_updated.