Rails 3 renders Haml file as Html - ruby-on-rails

Following the guide at http://github.com/fortuity/rails3-mongoid-devise I've managed to setup Rails3 with Haml, Devise, and Mongoid. (As a side-note, the guide is really detailed; recommended reading for new Rails users!)
Only problem is I can't get Rails to render my Haml views:
Started GET "/" for 127.0.0.1 at 2010-07-01 14:40:23 +0200
Processing by HomeController#index as HTML
MONGODB miabreto_development['users'].find({}, {})
Rendered home/index.html.haml within layouts/application (4.2ms)
Completed 200 OK in 21ms (Views: 21.0ms)
Note that it doesn't return a missing template error, it just renders the view as plain html. The filename follows the convention:
app/views/home/index.html.haml
and in the Gemfile I have:
# Bundle gems needed for Haml
gem 'haml', '3.0.13'
gem "rails3-generators", :group => :development
Since I am new to Rails, I am not sure what the execution path looks like for deciding what renderer to use, etc. Can someone suggest what I may have missed in my setup or where to look for errors? (This is Rails.3.beta4)

Couple of things
First of all, rails will render index.html.erb if it is present in the views folder. It will do this before it renders index.html.haml. So, take a look in your views folder and if you do have a file called index.html.erb, then just delete it and rails should start doing haml for you
Secondly, even when it does render the haml version of your file, it will still read " Processing by HomeController#index as HTML"
Hope this helps, and yeah, it's a great tutorial, read it myself a few days ago
PS - two ways to tell if your template is doing haml
add the words "hello from haml" into your haml file
look at the output server output you should see something along the lines of:
Rendered home/index.html.haml within layouts/application (42.9ms)

Related

ActionView is missing template in Preview. How to resolve?

I am currently trying to have ActionMailer send an email with Letter_Opener gem. When I try to view the preview with localhost:3000/mailer/order_mailer the terminal logs this error:
app/mailers/order_mailer.rb:10:in `new_order_email'
Started GET "/rails/mailers/order_mailer/new_order_email" for ::1 at 2023-01-27 16:27:38 -0800
Processing by Rails::MailersController#preview as HTML
Parameters: {"path"=>"order_mailer/new_order_email"}
OrderMailer#new_order_email: processed outbound mail in 1.2ms
Completed 500 Internal Server Error in 24ms (Allocations: 9119)
ActionView::MissingTemplate (Missing template order_mailer/new_order_email with "mailer".
Searched in:
* "order_mailer"
):
app/mailer/order_mailer.rb:
class OrderMailer < ApplicationMailer
default from: 'actionMailerTester2301#gmail.com'
# layout "order_mailer"
def new_order_email
#email = 'joeDANE#example.com'
mail(to: #email, subject: "Thank you for your donation.")
end
end
On the browser, the mail(to:..... line is pointed out. I've looked through multiple stackoverflow entries and I can't figure it out, though I chalked it up to my unfamiliarity with Ruby to not being about to understand the problem.
I'm hoping if I can figure out why the preview isn't working that I'll figure out the secondary problem with the Letter Opener gem.
Ruby on Rails prefers following certain conventions over configuration. In most cases, it is much easier and straight-forward to just follow the Rails' way instead of over-customizing your application.
In this specific example, I suggest to not change or re-configure where Rails finds the mailer views, but to just place the views in the default folder.
Following the conventions, for the mailer views and how your mailer and its method is named, the views should be named and located like this in the app/views folder (not in app/mailers/views):
app/views/order_mailer/new_order_email.html.erb
app/views/order_mailer/new_order_email.text.erb
Read about mailer view naming in the official Rails Guides.

Rails video_tag issuing extra GET request resulting in ActionController::RoutingError No route matches [GET]

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.

Rails: Use of absolute path in Rails 6

Recently, I've upgraded a Rails app that I'm maintaining to Rails 6 RC2 (coming from 5.2.3). So, right after upgrading, I ran the automated tests (RSpec) and the test output gave me lots of deprecation warnings. One of those warnings was:
DEPRECATION WARNING: render file: should be given the absolute path to a file
So I went to the view file that triggered the warning, and made the changes as follows,
Before:
render file: 'devise/sessions/new'
After:
render file: Rails.root.join('app', 'views', 'devise', 'sessions', 'new.html.slim')
I ran the tests again, no output of deprecation warnings was seen. However, after switching to absolute paths, the view is now only rendering plain HTML code but if I remove the .slim extension, i.e.
render file: Rails.root.join('app', 'views', 'devise', 'sessions', 'new.html')
The corresponding view is rendered properly but now the test will complain about not using absolute paths. Is there a way to fix this or is this a Rails/Slim bug?
In your case it looks like you want to render a normal view, i.e. a template.
In that case using the file option is not the recommended way. Instead you should be using the template option.
render template: 'devise/sessions/new'
Or even better, you can use this shortcut:
render 'devise/sessions/new'
Background
The file option is intended to render a view which is outside your Rails application, where you can't rely on Rails' view lookup logic. Consequently Rails wants to have an absolute path. Demanding an absolute path also forces the developer to think about relative path segments (/../).
Omitting the .slim extension and then having the file processed by the template engine is a feature intended for templates. Using file seems to provide the very same functionality, but my guess is that this is just a side effect of the internal workings of the view path lookup. It looks like the Rails developers want to improve the distrinction between files and templates in the future and deprecating relative files is an intermediate step to not break too many existing applications which rely on using file and still expect the features of a template.
PS: It is not necessary to manually split your path. So if you for some reason still want to use file with an absolute path, instead of
render file: Rails.root.join('app', 'views', 'devise', 'sessions', 'new.html.slim')
use this
render file: Rails.root.join('app/views/devise/sessions/new.html.slim')
I had this same challenge when working on Rails 6 API-only application.
I wanted to render a static page from a controller called home_controller.rb
Here's my code:
require 'rails/application_controller'
class HomeController < Rails::ApplicationController
def index
render file: Rails.root.join('public/index.html')
end
end
But when I try accessing the page I get the error:
Started GET "/favicon.ico" for ::1 at 2021-02-23 16:25:41 +0100
Processing by HomeController#index as */*
Parameters: {"other"=>"favicon"}
Completed 500 Internal Server Error in 1ms (ActiveRecord: 0.0ms | Allocations: 301)
ArgumentError (`render file:` should be given the absolute path to a file. '/home/my-computer/Projects/MyWebsite/public/index.html' was given instead):
Here's how I solved it:
The issue was that I was missing the file index.html in the directory public, so Rails could not locate it.
All I had to do was to add the file index.html in the directory public. This time when I tested it was fine.
That's all.
I hope this helps

Where is the default "Welcome Aboard" page located in my app?

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.

Rails is Using HTML View When Requesting Javascript

Weird issue where I'm asking for the JS file, but Rails is serving the HTML file. And it's only on my staging server (Heroku) and not on my local machine.
I have a dynamic Javascript file which is something that needs to be included in other pages via a script to like so:
<script type="text/javascript" src="http://example.com/embed.js></script>
That embed maps to a controller and action which also handles HTML. The relevant route looks like this:
match "/embed(.:format)" => "articles#embed", as: "embed"
And the controller action is pretty standard.
def embed
respond_to do |format|
format.html do
#it renders some HTML
end
format.js #no block is given
end
end
And, I have two views under app/views/articles
embed.html.haml
embed.js.coffee
On my local machine, requesting localhost:3000/embed.js works. It renders the Javascript without a problem. However, on my staging server, here's what I see in the logs:
Started GET "/embed.js" for 124.168.219.36 at 2012-11-04 00:23:01 +0000
Processing by ArticlesController#embed as JS
Rendered articles/embed.html.haml (1.5ms)
Completed 500 Internal Server Error in 2ms
The Internal Server Error is not the issue. The issue is that it recognises the request as JS, yet decides to render the HTML template and only on staging.
What's going on?

Resources