I scoured my app's directories, and I can't find the html page for the default rails Welcome Aboard page. I also cannot find a route for the default Welcome Aboard page in routes.rb. How does my rails app route http://localhost:3000/ to a non-existent page in my app?
The rails server produces this information:
Started GET "/" for 127.0.0.1 at 2013-07-31 02:00:13 -0600
Processing by Rails::WelcomeController#index as HTML
Rendered /Users/7stud/.rvm/gems/ruby-2.0.0-p247#railstutorial_rails_4_0/gems/railties-4.0.0/lib/rails/templates/rails/welcome/index.html.erb (0.1ms)
Completed 200 OK in 3ms (Views: 2.5ms | ActiveRecord: 0.0ms)
So it looks to me like there is a controller buried in a gem somewhere that handles the request.
Since Rails 4, the "Welcome aboard" page is no longer located in public/index.html. It is - as you've already detected - located inside one of the Rails gems.
So you already answered the question yourself; the "Welcome aboard" page is - in your case - located at /Users/7stud/.rvm/gems/ruby-2.0.0-p247#railstutorial_rails_4_0/gems/railties-4.0.0/lib/rails/templates/rails/welcome/index.html.erb
To get rid of it, following the instructions on the page. Basically they are:
Create a controller
Add a root route in config/routes.rb to route to that newly created controller.
As for how the request to your application ends up at a controller inside railties, let's dig into the gem: Inside Rails::Application::Finisher we find this:
initializer :add_builtin_route do |app|
if Rails.env.development?
app.routes.append do
get '/rails/info/properties' => "rails/info#properties"
get '/rails/info/routes' => "rails/info#routes"
get '/rails/info' => "rails/info#index"
get '/' => "rails/welcome#index"
end
end
end
This block adds a few routes to your application when running in development mode - one of those is the route to the "Welcome aboard" action: get '/' => "rails/welcome#index"
This - like any other initializer - is done when your start your application server (running rails server or however you do it). In the case of Finisher, all its initializer are run after all other initializers are run.
Note how the routes are appended so that they are appear last in the Routeset. This, combined with the fact that Rails uses the first matching route it finds, ensures those default routes will only get used if no other route is defined.
Related
I am working on a page that shows user-uploaded videos and pictures. The path for this page is /users/:id/ and the pictures/videos are located in /public/media/users/[userName]/
user_controller:
def show
#user = User.find(params[:id])
posts = #author.posts
#pictures = posts.select(&:picture?)
#videos = posts.select(&:video?)
end
views/user/show.html.erb:
<% #pictures.each do |picture| %>
<%= image_tag("/" + picture.path) %>
<% end %>
<% #videos.each do |video| %>
<%= video_tag("/" + video.path) %>
<% end %>
The page loads all of the pictures/videos correctly. For example, one of the generated video tags looks like <video src="/media/users/user1/example.mp4"></video> which is perfect.
However, after loading the page Rails seems to issue an extra GET request for each of the videos.
Completed 200 OK in 126ms (Views: 13.7ms | ActiveRecord: 1.9ms | Allocations: 21392)
Started GET "/users//media/users/user1/vids/example.mp4" for ::1 at 2022-08-13 10:21:25 -0400
Started GET "/users//media/users/user1/vids/example2.mp4" for ::1 at 2022-08-13 10:21:25 -0400
Started GET "/users//media/users/user1/vids/example3.mp4" for ::1 at 2022-08-13 10:21:25 -0400
ActionController::RoutingError (No route matches [GET] "/users/media/users/user1/vids/example.mp4"):
ActionController::RoutingError (No route matches [GET] "/users/media/users/user1/vids/example2.mp4"):
ActionController::RoutingError (No route matches [GET] "/users/media/users/user1/vids/example3.mp4"):
Some observations:
This is only occurring for videos, no extra requests are generated for pictures
Rails seems to be prepending the controller name to the start of these paths
Why are these requests being issued?
First, I have no idea why the requests are happening twice, I suspect Rails is either trying to speed up page loads by delaying loading the actual videos until after the page has rendered or it is making the second request to try and get a :poster value from the video object (see docs for video_tag)
But, I think this is probably intended behavior and the problem isn't that the 2nd GET request is happening, the problem is that the 2nd GET request has a bad URL.
I think I have an idea why the 2nd call's URL is bad.
My thought is that Rails doesn't have all the [userName] folders added to the asset pipeline.
Hence why you need to have the '/' before the picture and video path.
But, because the folders aren't in the pipeline, they are being resolved by just appending the generated video route to the current route, hence why you are seeing two backslashes together in the 2nd GET calls.
IF these folders are dynamically created, adding them to the asset pipeline without restarting the app is beyond me, but probably possible with some meta Rails programming.
If these folders are static, or the app can be restarted after a new folder is created, you can make sure they get added to the asset pipeline:
First, see if these folders are in the asset pipeline:
You can view the search path by inspecting Rails.application.config.assets.paths in the Rails console.
If they aren't in there, it might be because you've put them in /public but haven't enabled public assets:
In previous versions of Rails, all assets were located in subdirectories of public such as images, javascripts and stylesheets. With the asset pipeline, the preferred location for these assets is now the app/assets directory. Files in this directory are served by the Sprockets middleware.
Assets can still be placed in the public hierarchy. Any assets under public will be served as static files by the application or web server when config.public_file_server.enabled is set to true. You should use app/assets for files that must undergo some pre-processing before they are served.
# application.rb
module YourAppName
class Application < Rails::Application
...
config.public_file_server.enabled = true
...
end
end
or this behavior can be customized per environment:
# production.rb, development.rb, or test.rb
Rails.application.configure do
...
config.public_file_server.enabled = true
...
end
If this still doesn't fix it, you might have to manually add public/media/users/* to the pipeline like this.
Why when I write rails generate controller home index the index.html.erb file is not created in the views folder? And when I run rails server and want to watch http://127.0.0.1:3000/home/index terminal output.
Started GET "/home/index" for 127.0.0.1 at 2021-01-10 01:54:30 +0200
Processing by HomeController#index as HTML
Completed 204 No Content in 0ms (ActiveRecord: 0.0ms | Allocations: 60)
When I check error log I see HomeController#index, I would like you to check rails routes first. You should see a result similar to this:
Prefix Verb URI Pattern Controller#Action
home_index GET /home/index(.:format) home#index
...
If you are seeing homecontroller#index instead of home#index you can access by going to related URI pattern.
You can control which files are created when you run rails generate command. This is a sample output:
➜ rails g controller home index
Running via Spring preloader in process 1934
create app/controllers/home_controller.rb
route get 'home/index'
invoke erb
create app/views/home
create app/views/home/index.html.erb
invoke helper
create app/helpers/home_helper.rb
invoke assets
invoke scss
create app/assets/stylesheets/home.scss
As you see there is a file app/views/home/index.html.erb make sure that it is not empty. For example put <p>Home</p> in this file, if it is empty.
I hope it is clear enough and I think this will solve your problem.
ActionController::RoutingError (No route matches [GET] "/google83362a7a0f381ff0.html"):
I see the above logs in production, how should I prevent it.
If user mistypes a URL, how should I re-direct to a common error page
You can redirect the user to the desire page you want if no route matchs
Write down the following code at the bottom of your routes.rb file
In /config/routes.rb
#If no route matches
match ":url" => "application#redirect_user", :constraints => { :url => /.*/ }
Then redirect the user to the error page in the application_controller.rb file
*In /app/controllers/application_controller.rb*
def redirect_user
redirect_to '/404'
end
You don't need to trigger a controller to do that.
Just add this as the last rule in routes.rb:
match '*path', via: :all, to: redirect('/404')
Rails does this automatically when application running in production mode.When uploading application to live server, Rails takes care of handling those exceptions and rendering the correct error pages with the correct header status.You can directly find the files inside public folder.
Whenever you set up your Rails application on a live server, you give the site root as the /public folder in your application. Then, whenever a request is made to that server address, Web server first looks in that public folder and tries to serve a static asset (this is a configurable option in config/environment.rb). If it can't find the requested page, then the request is forwarded through the Ruby stack.
When in production mode, if Rails encounters an error that isn't handled, it throws the error to the stack, which then tells Web server to render an appropriate error.
Here are some common errors that you'll see in development mode and what they render in production mode:
ActiveRecord::RecordNotFound => 404 (page not found)
nil.method => 500 (server error) unless you turn off whiny nils
ActionController::RoutingError => 404 (page not found)
I'm converting a legacy app to Rails 3.1. The new app uses an engine that provides a glob route:
# myengine/config/routes.rb
Rails.application.routes.draw do
match 'foo/bar/*path' => 'myengine/foobar#index', :format => false
end
The legacy app used a final catchall wildcard route to provide custom handling (rather than the familiar Rails "Routing Error" page) for otherwise unmatched routes:
# myapp/config/routes.rb
Myapp::application.routes.draw do
# ...
match '*path' => 'failures#index', :format => false
end
Somehow this catchall route is interfering with the engine's route. If I comment out the app's catchall route, the engine's route works fine. But if I leave it in the engine route is never matched and the app's catchall route to failures#index is used instead:
Started GET "/foo/bar//projects/x/vol1/prod22/9907042031/9907042031.aff/ImageProperties.xml" for 10.71.1.136 at 2011-08-02 15:46:48 -0700
Processing by FailuresController#index as JS
Parameters: {"path"=>"foo/bar/projects/x/vol1/prod22/9907042031/9907042031.aff/ImageProperties.xml"}
Rendered failures/index.html.erb within layouts/application (0.0ms)
Completed 200 OK in 47ms (Views: 46.9ms)
How would one override the default Rails 3.1 routing error handler without breaking engine routes?
The right way to handle this used to be rescue_from and a custom error handler, rather than with an engines-hostile catchall route. However, custom error handlers are no longer supported in Rails 3.1 and this likely won't be fixed until Rails 3.2, if ever. If you need custom error handling and you use engines with routes, the vidibus-routing_error gem provides a workaround.
Another option is to put your custom error handler into a Rack endpoint at the bottom of your stack.
Warp Drive is a nice way to package an entire Rails application into a Gem for use in other Rails applications. I've gotten Warp Drive to work for a blogging engine I'm creating. There's just one problem - Authlogic OpenID authentication fails.
I created a bare-bones OpenID example application. I can compile to a gem with no problems:
$ warpify
$ rake warp_drive:compile
I then installed the compiled gem on my system. Creating a blank Rails project, I ran:
$ install_warp_drive rails-openid
You can get this project here.
In my blank Rails projects, I needed to configure gems through environment.rb (I'm probably doing this the wrong way):
config.gem "authlogic"
config.gem "authlogic-oid", :lib => "authlogic_openid"
config.gem "ruby-openid", :lib => "openid"
To get the blank Rails application working, I ran rake db:migrate, then through the console I added a user with an :openid_identifier field set to one that I control. So far so good. But trying to create a new session fails with this error:
Processing UserSessionsController#create (for 127.0.0.1 at 2009-12-31 11:35:59) [POST]
Parameters: {"commit"=>"Login", "user_session"=>{"openid_identifier"=>"richdev.myopenid.com"}, "authenticity_token"=>"BcsIKNpumqZrTV/bdSLQ6szBvq6kpaAIxJRmYgxySLU="}
OpenIdAuthentication::Association Load (0.3ms) SELECT * FROM "open_id_authentication_associations" WHERE ("open_id_authentication_associations"."server_url" = 'http://www.myopenid.com/server')
Generated checkid_setup request to http://www.myopenid.com/server with assocication {HMAC-SHA1}{4b3cf228}{mWlzhg==}
Redirected to http://www.myopenid.com/server?openid.assoc_handle=%7BHMAC-SHA1%7D%7B4b3cf228%7D%7BmWlzhg%3D%3D%7D&openid.ax.mode=fetch_request&openid.identity=http%3A%2F%2Frichdev.myopenid.com%2F&openid.mode=checkid_setup&openid.return_to=http%3A%2F%2Flocalhost%3A3001%2Fuser_sessions%2Fcreate%3Ffor_session%3D1%26_method%3Dpost%26open_id_complete%3D1%26openid1_claimed_id%3Dhttp%253A%252F%252Frichdev.myopenid.com%252F%26rp_nonce%3D2009-12-31T19%253A35%253A59ZUEd2eN&openid.trust_root=http%3A%2F%2Flocalhost%3A3001%2F
Completed in 15ms (DB: 0) | 302 Found [http://localhost/user_sessions]
Processing ApplicationController#index (for 127.0.0.1 at 2009-12-31 11:36:00) [POST]
Parameters: {"openid.mode"=>"id_res", "openid.return_to"=>"http://localhost:3001/user_sessions/create?for_session=1&_method=post&open_id_complete=1&openid1_claimed_id=http%3A%2F%2Frichdev.myopenid.com%2F&rp_nonce=2009-12-31T19%3A35%3A59ZUEd2eN", "openid.sig"=>"l+tfFAmeKsskHKlOYRoZF7yHM7Q=", "rp_nonce"=>"2009-12-31T19:35:59ZUEd2eN", "openid.op_endpoint"=>"http://www.myopenid.com/server", "for_session"=>"1", "openid.response_nonce"=>"2009-12-31T19:36:00ZBhX5fE", "openid1_claimed_id"=>"http://richdev.myopenid.com/", "openid.identity"=>"http://richdev.myopenid.com/", "open_id_complete"=>"1", "openid.assoc_handle"=>"{HMAC-SHA1}{4b3cf228}{mWlzhg==}", "openid.signed"=>"assoc_handle,identity,mode,op_endpoint,response_nonce,return_to,signed"}
ActionController::MethodNotAllowed (Only get, put, and delete requests are allowed.):
Rendered rescues/_trace (96.3ms)
Rendered rescues/_request_and_response (0.5ms)
Rendering rescues/layout (method_not_allowed)
The problem seems to occur during the redirect back from the openid provider, at which point ApplicationController#index gets called, instead of UserSessionsController#create. I'm not sure if this is an OpenID issue or a Warp Drive issue.
How can I bundle an Authlogic/OpenID application as a Warp Drive Gem and get authentication to work successfully?
Update: Adding an explicit resource definition for user_session fixes the problem. In routes.rb:
map.resources :user_sessions
Not sure why, and this doesn't seem to be required for any other controller.
Two things worked:
Add an explicit user_session resource definition in routes.rb:
map.resources :user_sessions
Remove default routes in routes.rb of the app using the warp drive gem.
Removing default routes in routes.rb
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'
solved a horrific routing issue where a resource routing in the warp drive:
map.resources :users, :member => {:activate => [:post, :get]}
created a URL: /users/:id/activate(.:format)
But an HTTP request to that URL resulted in the :action and :id getting reversed when passed to the controller (as if interpreted as a default URL). e.g.
Parameters = {"action"=>"123456", "id"=>"activate", "controller"=>"users"}
Not pretty. Removing the default routes in the warp drive or the client app did it. Seems safer to do it in the client app, though.