I wrote a basic test to ensure pages and titles are rendered as expected.
static_pages_controller_test.rb
require 'test_helper'
class StaticPagesControllerTest < ActionController::TestCase
test "should_get_contact" do
get :contact
assert_response :success
assert_select "title", "Contact"
end
end
routes.rb
Rails.application.routes.draw do
root 'static_pages#home'
get 'static_pages/help'
get 'static_pages/about'
get 'static_pages/contact'
end
contact.html.erb
<% provide(:title, "Contact")%>
<h1>Help</h1>
<p>
Some text.
</p>
application.html.erb
<!DOCTYPE html>
<html>
<head>
<title><%= yield(:title) %></title>
...
</head>
<body>
<%= render 'layouts/header' %>
<div class="container">
<%= yield %>
<%= render 'layouts/footer' %>
</div>
</body>
</html>
and this is my static_pages_controller.rb
class StaticPagesController < ApplicationController
def home
end
def help
end
def about
end
end
As you notice there is no "contact" action so I expected test not to pass, whilst I keep getting green light.
davide#davidell:~/Desktop/app/sample_app$ bundle exec rake test
Run options: --seed 62452
# Running:
....
Finished in 0.194772s, 20.5369 runs/s, 41.0737 assertions/s.
4 runs, 8 assertions, 0 failures, 0 errors, 0 skips
Why? What am I missing? Thanks a lot for your answers, and happy new year :)
For better or for worse, this is one of the various "features" exposed by Rails as part of the convention over configuration approach. In my experience, this specific feature is mostly an unwanted side effect.
If your request matches a route and there is a template for that route matching the controller and the request format, then Rails will pretend the action to be defined as a simple empty method in the controller.
In your case, because you created the contact.html.erb template and you created a route that matches to the #contact action, this is equivalent to the same controller
class StaticPagesController < ApplicationController
def home
end
def help
end
def about
end
def contact
end
end
Related
I'm trying to add tests for an existing application that's a bit unconventional. I can get it to render a page fine on the dev server. But when I add a controller test, I get the following error whenever I render a view:
NoMethodError: undefined method `formats' for "foo":String
test/controllers/dashboard_controller_test.rb:15:in `block in <class:DashboardControllerTest>'
Here's the code:
# config/routes.rb
get 'foo', to: 'dashboard#foo'
# app/controllers/dashboard_controller.rb
class DashboardController < ApplicationController
def foo
#render plain: 'ok'
end
end
# app/views/dashboard/foo.html.erb
ok!
# app/views/layouts/application.rb
<!DOCTYPE html>
<html>
<head>
<title>Dashboard</title>
</head>
<body>
<%= yield %>
</body>
</html>
# test/controllers/dashboard_controller_test.rb
require 'test_helper'
class DashboardControllerTest < ActionController::TestCase
test "get foo" do
get :foo
assert_response :success
end
end
I visit /foo in my browser and I get ok!.
I run my tests and I get the error above.
If I uncomment the render plain line in DashboardController#foo, the test passes.
It would appear something's breaking when the test tries to render the view, but I can't figure out what and the error message isn't offering me much help. What does this error mean?
Update
Just noticed that the application is using render_anywhere gem. I wonder if this has something to do with it.
Disabling the render_anywhere gem indeed solved the issue. It was being included in a rake task.
The rake task is not being tested, so I simply side-stepped the issue for now like so:
unless Rails.env.test?
require 'render_anywhere'
include RenderAnywhere
end
Im trying to display a simple starting view in my browser by doing http://localhost:3000/project/claim but it keeps giving:
No route matches [GET] "/project/claim"
routes.rb file:
Rails.application.routes.draw do
........
get 'project/claim' => 'claim#index'
controller/claim_controller file:
class ClaimController < ApplicationController
def index
#message = "Hello, World!"
end
end
/views/claim/claim.html.erb file:
<h1>A greeting for you! </h1>
<p> <%= #message %> </p>
rename:
/views/claim/claim.html.erb
on
/views/claim/index.html.erb
I generated a Rails application, and am playing around with the internals. Previously my application.html.erb was rendering properly, but now it seems like Rails is totally ignoring it because it won't even generate an error.
There have been a bunch of questions on Stack Overflow regarding this problem. I've looked at what I think is all of them, but none have helped.
My routes:
Rails.application.routes.draw do
# static_pages from rails tutorial ch. 3
get 'static_pages/home'
get 'static_pages/help'
get 'static_pages/about'
end
Here is the views/layout/application.html.erb
<!DOCTYPE html>
<html>
<head>
<title>This Title is not showing up</title>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
<%= csrf_meta_tags %>
</head>
<body>
<p> why isnt this showing up?? </p>
<%= yield %>
</body>
</html>
Here is the static_pages_controller:
class StaticPagesController < ApplicationController
layout 'application' #<- I know this shouldn't be necessary, but I thought i'd try
def initialize
#locals = {:page_title => 'Default'}
end
def about
#locals[:page_title] = 'About'
render #locals
end
def help
#locals[:page_title] = 'Help'
render #locals
end
def home
#locals[:page_title] = 'Home'
render #locals
end
end
Here is the Application Controller:
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
end
There are no other layouts. My Views folder has the following structure:
-Views
|-layouts
||-application.html.erb
|
|-static_pages
||-about.html.erb
||-home.html.erb
||-help.html.erb
I've tried purposefully generating an error in the application.html.erb, calling variables that don't exist and whatever other shenanigans. Rails is totally ignoring me and I'm feeling insecure.
All I wanted to do is to display the page name in the <title>, but I can't even get plaintext to render correctly. How can I get this to work so that I can properly fail at getting the controller variable in the title?
You should not override the controller initialize method. Doing this will break the base class behavior.
While, I believe, just calling the super from the initialize will fix your issue, the correct Rails way to initialize a controller for a specific action is to use a before filter instead.
Example:
class StaticPagesController < ApplicationController
layout 'application'
before_action :load_locals
def load_locals
#locals = {:page_title => 'Default'}
end
...
end
I tried hard to find this exact match of my error but I am unable to do so. I am new to Ruby and stuck for long after this block. Please help.
I have checked my route.rb file my controller method show and my show.html.erb file error remains.
I destroyed and created controller again and again to check but still the error remains.
Is it asking me to define/declare variable user?? have not I did so?? like in controller i did #user and then called databsae.. I think so.
Thanks in advance
The controller:
class PersonsController < ApplicationController
def show
#user = Users.find(params[:id])
end
end
The view:
<%= provide(:title, #user.name %>
<h1> #user.name </h1>
<%=#user.name %>, <%=#user.email %>
The routes:
Rails.application.routes.draw do
get 'persons/show'
root 'staticpages#home'
get 'help' => 'staticpages#help'
get 'about' => 'staticpages#about'
resources :persons
resources :person
end
Model names in Rails are singular:
#user = User.find(params[:id])
When I run my tests I get this error:
1) Error:
CategoriesControllerTest#test_new:
ActionView::Template::Error: No such file or directory # unlink_internal - C:/Users/Javi/AppData/Local/Temp/execjs201504
29-7044-qg60v0json
app/views/layouts/application.html.erb:6:in `_app_views_layouts_application_html_erb__20669174_54234900'
test/controllers/categories_controller_test.rb:6:in `test_new'
4 runs, 3 assertions, 0 failures, 1 errors, 0 skips
Here is my application.html.erb file:
<!DOCTYPE html>
<html>
<head>
<title>TestingBasics</title>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
<%= csrf_meta_tags %>
</head>
<body>
<%= yield %>
</body>
</html>
I created a categories/new.html.erb file and saved it
This is my controller test that is failing:
require "test_helper"
class CategoriesControllerTest < ActionController::TestCase
def test_new
get :new
assert_response :success
end
end
EDIT::
Here is my controller:
class CategoriesController < ApplicationController
def new
#category = Category.new
end
end
I also have the following in my routes file:
Rails.application.routes.draw do
resources :categories
end
I have a new.html.erb on my views but its not working...
Does anyone know what is happening? It looks like there is a problem with my application file picking up json? I am new to testing so not sure what this is.
#coderwannabe2 your view should be named 'test_new.html.erb' not 'new.html.erb'
The error is stating that it cannot find a template matching 'test_new' which is true. Your template right now is 'new' so change 'new.html.erb' to 'test_new.html.erb' and you should have magick!
You should always remember that if in your controller you have inside the class
def view_one
end
def view_two
end
then your views must match the method name so in this case you would have
view_one.html.erb
view_two.html.erb
This is really watered down explanation but it should help get your mind around it all and how the method names relate to views and vice versa.