I have an rails application where i used slugged urls. How can i test those urls with Rspec.
rake routes is generating following results
new_user_session GET /login(.:format) sessions#new
user_session POST /login(.:format) sessions#create
bays GET /:slug/bays(.:format) bays#index
POST /:slug/bays(.:format) bays#create
new_bay GET /:slug/bays/new(.:format) bays#new
edit_bay GET /:slug/bays/:id/edit(.:format) bays#edit
bay GET /:slug/bays/:id(.:format) bays#show
PATCH /:slug/bays/:id(.:format) bays#update
PUT /:slug/bays/:id(.:format) bays#update
DELETE /:slug/bays/:id(.:format) bays#destroy
Now when i run rpec for bays controller, i caught with following error.
Failure/Error: get :index, {}, valid_session
ActionController::UrlGenerationError:
No route matches {:action=>"index", :controller=>"bays"}
Using
rspec-rails (3.0.1)
rails (4.0.0)
As you have defined it... bays index requires a :slug parameter. According to the error message, you have passed no slug to this route. You must either pass :slug (eg get :index, :slug => "1234", valid_session) or redefine the route to not need it.
for testing routes in rspec... That's a basic part of rspec: rspec routing specs
in your case it'd be something like:
{ :get => "/1234/bays" }.
should route_to(
:controller => "bays",
:slug => "1234"
)
For rspec 3.x you can go with:
scenario 'get correct slug', :type => :routing do
expect(get("/models/slug")).to route_to(:controller => "controller_name", :action => 'action_name', :id => "your_slug_name")
end
Note the type: :routing definition before the block.
More info here.
Related
I have AWS and Paperclip working successfully in one model, now I am trying to add it to another. Currently I am getting a undefined method "fields" for nil:NilClass error on this bit of code in my projects/form:
<%= form_for #project, html: { multipart: true, class: "directUpload", data: {
'form-data' => (#s3_direct_post.fields), // <-- err: #s3_direct_post is nil
'url' => #s3_direct_post.url,
'host' => URI.parse(#s3_direct_post.url).host }
} do |f| %>
In my projects controller I have included this private method:
def set_s3_direct_post
#s3_direct_post = S3_BUCKET.presigned_post(key: "uploads/#{SecureRandom.uuid}/${filename}", success_action_status: '201', acl: 'public-read')
end
and included :image in my controllers params.require()
Unfortunately I am not finding many threads on this error on SO and none have a conclusive solution. This same bit of code is currently working fine in the other model, yet it seems that the method in the projects controller (only) is not being read? It's the exact same code and setup as the Users controller. How do I fix this?
Some additional info:
I am reusing the code in application.js, config/initializers/aws.rb, and I am using the same bucket for multiple controllers (for now), as well as the same AWS credentials as I did for the model in which paperclip/aws is working
I have restarted my server a couple times
I am using rails 4.2.3, paperclip 5.0 and aws-sdk 2.3
Any additional info needed I will be happy to supply. Thanks :)
Answer: I forgot to set my before_action in my controller
before_action :set_s3_direct_post, only: [:new, :edit, :create, :update]
My route.rb file has this line:
devise_for :users,
:controllers => { registrations: 'register' },
:path => '',
:path_names => {
:sign_in => 'login',
:sign_out => 'logout',
:sign_up => 'register'
}
sing_in and sing_out overriding works well, but sing_up doesn't.
If I visit /register I obtain an uninitialized constant RegisterController.
I'm sure that I'm doing something wrong, but I'm pretty new to Rails and I don't understand very well what that code do. It comes out from many search on Google...
update 1
I follow also this official guide: https://github.com/plataformatec/devise/wiki/How-To:-Change-the-default-sign_in-and-sign_out-routes#another-simple-way-to-do-the-same-thing
update 2
Ok, I don't know way I added the :controllers params to the previous code, but after removed it
devise_for :users,
:path => '',
:path_names => {
:sign_in => 'login',
:sign_out => 'logout',
:sign_up => 'register'
}
And now if I run rake routes | grep devise on my console I got this:
cancel_user_registration GET /cancel(.:format) devise/registrations#cancel
user_registration POST / devise/registrations#create
new_user_registration GET /register(.:format) devise/registrations#new
edit_user_registration GET /edit(.:format) devise/registrations#edit
PATCH / devise/registrations#update
PUT / devise/registrations#update
DELETE / devise/registrations#destroy
And as you can see now the route for the creation of a user is POST /, and I'm sure that this is not a good thing... right? And the major problem is here: GET /have to be the homepage and not the get-all-users-page.
may the :path => '' introduce errors?
I'm not sure the path_names param is what you should be doing. You can assign the controller methods using:
devise_scope :user do
get '/logout', :to => 'devise/sessions#destroy', :as => :destroy_user_session
post '/signin', :to => 'devise/sessions#create', :as => :user_session
end
Following the instructions at https://github.com/plataformatec/devise/wiki/How-To:-Test-controllers-with-Rails-3-and-4-%28and-RSpec%29, I have set up some macros in a file spec/support/rspec_macros.rb:
module ControllerMacros
def login_admin
before(:each) do
#request.env["devise.mapping"] = Devise.mappings[:user]
sign_in FactoryGirl.create(:user, role: 4)
end
end
def login_user
before(:each) do
#request.env["devise.mapping"] = Devise.mappings[:user]
sign_in FactoryGirl.create(:user)
end
end
end
(Note that in my app, "admin" is a role -- role 4 -- that any user can be assigned to, and yes, once I get this working I'll DRY this up and get rid of the magic number).
However, putting login_admin into my spec doesn't work: it can't see login_admin.
So, following the advice at ControllerMacros cannot be seen in RSpec I add
config.include ControllerMacros, :type => :controller
to my spec_helper.rb file. Now ControllerMacros is an uninitialized constant, so following the advice at rspec not working with devise user authentication I add:
require 'support/controller_macros'
to my spec_helper file, and I find that I'm back where I started with undefined local variable or method login_admin
Help! How do I get to the macro? And is there one single place where the whole process is documented?
For info, the relevant bits of my spec_helper file are:
require 'rubygems'
require 'factory_girl'
require 'support/controller_macros'
require 'devise'
RSpec.configure do |config|
config.include Devise::TestHelpers, :type => :controller
config.include ControllerMacros, :type => :controller
end
And my spec file is:
require 'rails_helper'
RSpec.describe UsersController, :type => :controller do
describe "GET show" do
login_admin
it "returns http success" do
user = User.first
get :show, id: user[:id]
expect(response).to be_success
end
end
end
Make sure that rails_helper.rb loads files in spec/support folder.
If not add that line to your rails_helper.rb:
Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }`
after require 'rspec/rails' and move devise config to rails_helper.rb
RSpec.configure do |config|
config.include Devise::TestHelpers, :type => :controller
config.include ControllerMacros, :type => :controller
end
I've got a Rails engine (for authentication, though I don't think it will matter). It comes, as is traditional, with a dummy app in the /spec directory.
The engine defines a couple of routes in the application, and the dummy app defines a few of its own.
When I run the dummy app in WEBrick using rails s, it works fine. However, when try to run it using Pow (symlinking to my_engine/spec/dummy in ~/.pow), it doesn't seem to recognize the routes provided by the engine, and I get:
ActionController::UrlGenerationError at /login
No route matches {:action=>"new", :controller=>"my_engine/sessions"}
What's wrong with this, and why does it only happen in Pow?
Here are the routes files, in case it matters:
my_engine/config/routes.rb:
Rails.application.routes.draw do
get 'login', :controller => 'my_engine/sessions', :action => :new
post 'login', :controller => 'my_engine/sessions', :action => :create
get 'logout', :controller => 'my_engine/sessions', :action => :destroy
end
my_engine/spec/dummy/config/routes.rb:
Rails.application.routes.draw do
mount MyEngine::Engine => "/auth"
root 'home#index'
controller :home do
get :index
get :private, :as => 'private'
end
end
Edit: I've determined that this doesn't work when the engine is used in a normal application as well, so it's not just the dummy app.
So, turned out to be completely unrelated. The engine-served page I was linking to contained a link_to helper in which the second argument (the path) was dependent on ENV['RAILS_ENV']. In Pow, this value was nil (whereas in WEBrick, it was set to 'development', as the author presumably expected), and so it was trying to render link_to('text', nil). Which somehow produced the above error.
I'm versioning my rails app and I want to be able to authenticate an user with 2 different routes :
get 'v1/auth/:provider' => 'The omniauth method containing the appropriate callback'
get 'v1/auth/:provider/callback => 'v1/sessions#create'
get 'v2/auth/:provider' => 'The omniauth method containing the appropriate callback'
get 'v2/auth/:provider/callback => 'v2/sessions#create'
Is it possible to "hack" the prefix_path attributes so I can generate both routes ?