Error using Capybara while testing an rails 4 engine - ruby-on-rails

I want to test a rails engine by using capybara and factory_girl with Test::Unit (not rspec).
I write the following test:
test 'get review show' do
review = create(:review)
visit aecs_review.admin_review_path(review.id)
assert true
end
rake test now get the following error:
1) Error:
NavigationTest#test_get_review_show:
ActionView::Template::Error: undefined method `reviewnumber' for nil:NilClass
D:/Webserver/rails-server/ecommerce/aecs_review/app/views/aecs_review/admin/reviews/show.html.erb:1:in `_____ebserve
r_rails_server_ecommerce_aecs_review_app_views_aecs_review_admin_reviews_show_html_erb___218004451_53574504'
reviewnumber is a small model method to give back a formated id. It is executed by #review.reviewnumber in the view.
I get also errors at the other views (index, ect.) at the points, where i try to access a attribute of a variable.
Why are the variables in the views always nil?
How can I solve this problem?
Here is my controller method:
require_dependency 'aecs_review/application_controller'
module AecsReview
class Admin::ReviewsController < ApplicationController
def show
#review = Review.find(params[:id])
end
end
end
And my view:
<h1>Rezension anzeigen: <%= #review.reviewnumber %></h1>
[...]
rake routes of the dummy app of the engine:
root GET / aecs_review/admin/reviews#index
admin_reviews GET /admin/index(.:format) aecs_review/admin/reviews#index
admin_review GET /admin/:id/show(.:format) aecs_review/admin/reviews#show
admin_review_toggle_visibility GET /admin/:id/toggle_visibility(.:format) aecs_review/admin/reviews#toggle_visibility
admin_review_destroy GET /admin/:id/destroy(.:format) aecs_review/admin/reviews#destroy
review_create POST /create(.:format) aecs_review/reviews#create
reviews GET /product/:id(.:format) aecs_review/reviews#index
reviews_overview GET /product/:id/overview(.:format) aecs_review/reviews#overview
reviews_rating GET /product/:id/rating(.:format) aecs_review/reviews#rating
review_new GET /product/:id/new(.:format) aecs_review/reviews#new
review GET /:id(.:format) aecs_review/reviews#show
review_edit GET /:id/edit(.:format) aecs_review/reviews#edit
review_update PATCH /:id/update(.:format) aecs_review/reviews#update
review_destroy GET /:id/destroy(.:format) aecs_review/reviews#destroy
review_create_evaluation_good GET /:id/create_evaluation/good(.:format) aecs_review/reviews#create_evaluation_good
review_create_evaluation_bad GET /:id/create_evaluation/bad(.:format) aecs_review/reviews#create_evaluation_bad
review_create_evaluation_abusing GET /:id/create_evaluation/abusing(.:format) aecs_review/reviews#create_evaluation_abusing

I found the problem!
In the controller I have a before_filter, which is a part of the main app. So I wanted to override it. But i accidentally override the complete controller, so there was no more controller method to execute.
Now I skip the before_filter and it works!

Related

Routing Error uninitialized constant controller

I'm am trying to learn Ruby on rails and I keep getting this error.
My controller is
class Clasa9Controller < ApplicationController
def multimi
end
def progresii
end
def functii
end
def vectori
end
def trigonometrie
end
def geometrie
end
end
clasa9.html.erb
<button class="btn"><%= link_to "", multimi_path %></button>
rails routes:
multimi GET /clasa_9/multimi(.:format) clasa_9#multimi
progresii GET /clasa_9/progresii(.:format) clasa_9#progresii
functii GET /clasa_9/functii(.:format) clasa_9#functii
vectori GET /clasa_9/vectori(.:format) clasa_9#vectori
trigonometrie GET /clasa_9/trigonometrie(.:format) clasa_9#trigonometrie
geometrie GET /clasa_9/geometrie(.:format) clasa_9#geometrie
and routes.rb
get 'clasa_9/multimi', to:"clasa_9#multimi", as:"multimi"
get 'clasa_9/progresii', to:"clasa_9#progresii", as:"progresii"
get 'clasa_9/functii', to:"clasa_9#functii", as:"functii"
get 'clasa_9/vectori', to:"clasa_9#vectori", as:"vectori"
get 'clasa_9/trigonometrie', to:"clasa_9#trigonometrie", as:"trigonometrie"
get 'clasa_9/geometrie', to:"clasa_9#geometrie", as:"geometrie"
devise_for :users
get 'pages/home'
get 'pages/clasa9'
get 'pages/clasa10'
get 'pages/clasa11'
get 'pages/clasa12'
get 'pages/about'
root 'pages#home'
and im am getting
Routing Error
uninitialized constant Clasa9Controller
I tried to solve this by looking up what is already posted here but I just can't solve it... I don't understand what I should change.
If your file is located inside the app/controllers folder, then it is probably a file name issue. Your file should have the name clasa9_controller.rb.
If not, then you should load the file by creating an initializer or by adding an autoload_path inside config/development.rb
Rails loads by default:
All subdirectories of app in the application and engines present at boot time. For example, app/controllers. They do not need to be the default ones, any custom directories like app/workers belong automatically to autoload_paths.
Any existing second level directories called app/*/concerns in the application and engines.
The directory test/mailers/previews.
Look it would be clasa9 but why that when you run this with the underscore method like this
Loading development environment (Rails 5.1.4)
2.3.4 :001 > "Clasa9Controller".underscore
=> "clasa9_controller"
it returns clasa9_controller that means your controller is clasa9 not clasa_9 and file name will be clasa9_controller.rb then your routes would be to: "clasa9#multimi" like this
get 'clasa_9/multimi', to: "clasa9#multimi", as: "multimi"
#or
#get 'clasa_9/multimi', to: "clasa9#multimi", as: :multimi # removed doublw quotes from multimi
...
Follow this it should work.

NoMethodError in Rails while saving data

Checks_controller
class Checkscontroller < ApplicationController
def show
#check= Tester.find(params[:id])
end
def new
end
def create
#check = Tester.new(check_params)
#check.save
redirect_to #check
end
def check_params
params.require(:check).permit(:title, :description)
end
end
I am trying to save the data in 'checks' controller to 'Tester' model, getting "NoMethodError in ChecksController#create", undefined method tester_url' for#` while trying to save the data to my DB. There seems to be some issue on this line: "redirect_to #check".
Routes.rb
Rails.application.routes.draw do
get 'home/screen'
resources :checks
root 'home#screen'
end
EDIT: I see this answer got accepted. To anyone else looking at this: PLEASE DO NOT DO THIS WITHOUT A REALLY GOOD REASON.
Ok, so since you want to use the ChecksController for your Tester model, you'll have to add this to your routes: note that I'm assuming that you do not have a Check model, since I don't see it anywhere and youre using Tester as a check?
resources :testers, as: 'checks' controller: 'checks'
This line will make it so that /checks/1 goes to a Tester object with ID: 1, and use the ChecksController show method to show it
Old answer, for posterity
You're getting this error because you're missing routes for your Tester model in your routes.rb file.
You could add resources :testers to it and it will work. Of course you also already need AT LEAST your TestersController to exist with a show action
This error is occurring because when you redirect_to #check, Rails knows it's a Tester object and expects a route called tester to route to TestersController#show. It's attempting to use a helper method that rails creates for routes, called tester_url

Action could not be found in Rspec test for nested route

I am trying to get a handle on how nested routes work with Rspec. I have one of these:
class SupportController < ResourceController
# stuff happens
def support_override
customer = Customer.find_by_id(params[:id])
customer.override( params[:override_key] )
redirect_to("support")
end
end
We have a route:
resources :support do
member do
# loads of paths
get 'support_override/:override_key' => 'support#support_override'
end
end
And the route passes a test:
it "should route GET support/1/support_override/ABCDEF to suport#support_override" do
{ get: '/support/1/support_override/ABCDEF'}.should route_to(controller: 'support', action: 'support_override', id: '1', override_key: 'ABCDEF' )
end
However when I try to test the logic in rspec:
describe SupportController do
# various levels of context and FactoryGirl calls
it "can reach override url" do
get :support_override, { :id=> #customer.id, :override_key="123" }
response.should redirect_to("support")
end
end
I get the following response:
Failure/Error: Unable to find matching line from backtrace
AbstractController::ActionNotFound:
The action 'support_override' could not be found for SupportController
I have no doubt that the problem is with my understanding of how rspec works with nested routes, but I can't see any way to figure out what path Rspec is actually seeking and consequently it's hard to know what I need to change and I'm having trouble locating the relevant documentation.
Is there a way to find what path is being created by the test or can anyone offer guidance on how exactly the path creation works in this situation?
Since, you haven't shared the complete SupportController code, I cannot pin-point exact error. BUT there are two possibilities:
You have defined support_override under private/protected by mistake.
You have closed the class SupportController before support_override method definition, by mistake
Your action must always be public so that its accessible.

RSpec controller testing with non-RESTful route redirects

I'm trying to test some basic aspects of a controller that is reached via a nonstandard set of routes. I can't seem to connect to the appropriate controller/action in my LessonsController, which is reached via redirected routes that are meant to appear to lead to the CoursesController.
When I run my specs, I either get a routing error or the response comes back empty and I'm not sure how to parse it for useful nuggets.
# app/controllers/lessons_controller.rb
def index
... set some instance vars ...
end
# The CoursesController has index and show methods of its own which aren't used here
# app/config/routes.rb
...
get 'courses/:course_name' => redirect('/courses/%{course_name}/lessons'), :as => "course"
get 'courses/:course_name/lessons' => 'lessons#index', :as => "lessons"
...
# spec/controllers/courses_controller_spec.rb
describe CoursesController do
it "test some instance vars" do
get :show, :course_name => Course.first.title_url
assigns(:some_ivar).should_not be_empty
end
end
The error:
AbstractController::ActionNotFound: The action 'course' could not be found for CoursesController
RSpec attempt #2:
# spec/controllers/courses_controller_spec.rb
...
get :course, :course_name => Course.first.title_url
...
The attempt #2 error:
NoMethodError: undefined method `empty?' for nil:NilClass
If I run similar trial-and-error approaches by instead starting with the lessons_controller_spec.rb file (e.g. trying get :index there), I get similar errors. There is no direct route set up for lessons#index, only the redirects.
The response object in my second example is enormous (though the body is empty) so I won't include it unless someone thinks it's useful.
I'm definitely regretting the non-RESTful architecture, but given what it is, is there any idea how to get the controller spec to target the appropriate action inside the LessonsController?
Rails 3.2.12, RSpec 2.14.4, Capybara 2.0.2
Short answer: No.
Actually there are two types of get available in tests.
One type is for controller testing. This get can only accept argument as "action", say :index, :show etc. So you can only use it within current controller test. (Doc here: http://api.rubyonrails.org/classes/ActionController/TestCase/Behavior.html#method-i-get)
The other type is for integration testing. This get can accept any path as argument. http://api.rubyonrails.org/classes/ActionDispatch/Integration/RequestHelpers.html#method-i-get
The two types have same name get but usage is different.
What in your question is controller testing. So you are use the first one. You can only reach actions inside CoursesController. That's why you meet error.
I strongly recommend you to revise the routes right now. It's not about RESTful or not, but your routes break conversion all the day. What's the point the path is lesson, but controller is course? And why you write a Course controller when there is no route for him?

Rails 3 routing inside a controller

I have just switched to rails from padrino/sinatra so the routing stuff puzzles me.
I have defined,
namespace :admin do
resources :teachers, :students, :lessons
end
in my routes.rb file, and when i run rake routes command it gives me,
admin_teachers GET /admin/teachers(.:format) admin/teachers#index
POST /admin/teachers(.:format) admin/teachers#create
new_admin_teacher GET /admin/teachers/new(.:format) admin/teachers#new
edit_admin_teacher GET /admin/teachers/:id/edit(.:format) admin/teachers#edit
admin_teacher GET /admin/teachers/:id(.:format) admin/teachers#show
PUT /admin/teachers/:id(.:format) admin/teachers#update
DELETE /admin/teachers/:id(.:format) admin/teachers#destroy
admin_students GET /admin/students(.:format) admin/students#index
POST /admin/students(.:format) admin/students#create
new_admin_student GET /admin/students/new(.:format) admin/students#new
edit_admin_student GET /admin/students/:id/edit(.:format) admin/students#edit
admin_student GET /admin/students/:id(.:format) admin/students#show
PUT /admin/students/:id(.:format) admin/students#update
DELETE /admin/students/:id(.:format) admin/students#destroy
admin_lessons GET /admin/lessons(.:format) admin/lessons#index
POST /admin/lessons(.:format) admin/lessons#create
new_admin_lesson GET /admin/lessons/new(.:format) admin/lessons#new
edit_admin_lesson GET /admin/lessons/:id/edit(.:format) admin/lessons#edit
admin_lesson GET /admin/lessons/:id(.:format) admin/lessons#show
PUT /admin/lessons/:id(.:format) admin/lessons#update
DELETE /admin/lessons/:id(.:format) admin/lessons#destroy
The problem is, i can't figure out how to respond a request to admin/students#update? I know how to respond to admin#teachers, in my admin controller i create a teachers function. But how to respond to admin/teachers/index? Or maybe where to respond? In which file? In which function or class?
For admin/students#update Rails will look for the action here:
class Admin::StudentsController < ApplicationController
def update
# update here
end
end
You can generate this file with:
rails generate controller admin/students update
Which will write to:
app/controllers/admin/students_controller.rb

Resources