cancancan gem passing params to ability - ruby-on-rails-4

Am using cancancan and activeadmin gems in my application, in cancan gem i want to pass the params to ability.
controller.rb
controller do
def scoped_collection
end_of_association_chain.accessible_by(current_ability, params[:project_id]) # passing params
end
end
ability.rb
if ((user.has_role? :LA_Tracker_Manager) && (user.has_application? :LA_Tracker))
can :manage, Job, project_id: params[:project_id] # getting the params heree
end
if (user.has_role? :LA_Tracker_Analyst)
can [:read, :update], Job, employee_id: user.employee.id
end
the above code not working. how to achieve this.

Related

Cannot find existing route

I have this route
get 'versions' => 'main#versions', formats: [:xml]
In my MainController, I have an action versions thus:
class MainController < ApplicationController
...
def versions
render formats: [:xml]
end
end
and under app/views/main I have versions.xml.erb.
I have written an RSpec controller test:
require 'rails_helper'
RSpec.describe MainController, type: :controller do
...
describe '#versions' do
it 'renders versions template' do
get :versions, formats: [:xml]
expect(response).to render_template(:versions)
end
end
end
However, I continue to get this error:
Failure/Error: get :versions, formats: [:xml]
ActionController::UrlGenerationError:
No route matches {:action=>"versions", :controller=>"main", :formats=>["xml"]}
However, when I run rake routes, I get:
versions GET /versions(.:format) main#versions {:formats=>[:xml]}
I still don't understand why I'm getting this error when the route exists with the right parameters.
Ruby 2.1.5
Rails 4.1.6
RSpec 3.8.x
NOTE: I'm constrained to not rewrite any code and can only suggest changes.
Rails' routing uses a format key, not formats. It's automatically supported for all endpoints by default, and will pass on whatever format is required to your controller actions.
I'd suggest the following modifications:
# routes.rb
get 'versions', to: 'main#versions'
# main_controller.rb
def versions
respond_to do |format|
format.xml
end
end
# main_controller_spec.rb
it 'renders the version template' do
get :versions, format: :xml
...
end

Routing to Controller in ActiveAdmin 1.0.0

rake routes gives the output
POST /admin/users(.:format) admin/users/new
But where is the new action executed? The /admin/user is the registered resource. There are no actions. However creating a new user through the standard AA form puts my user in the database but which controller is used?
UPDATE:
I want to create a new user using ActiveAdmin with a password and store the hashed password using devise. The new action works in my normal user controller which i test through rails console
#user=User.create(params.permit(:name, :phone, :active, :password_digest
#user.password = Devise.friendly_token
So far i hacked the action in the AA user.rb resource like this:(basically the same statements encapsulated in controller do...)
controller do
def new
#user.password = Devise.friendly_token
#user=User.create(params.permit(:name, :phone, :active, :password_digest
The Issue i have now it that the user gets saved in my db but with an unshashed password.(?)
The live demo and the documentation are a bit short on detailed information or examples on this issue.
ActiveAdmin uses inherited resources gem for the default controller actions. If you want to overwrite the new controller action, you can overwrite it in your activeadmin resource code like so:
ActiveAdmin.register User do
controller do
def new
super #use the default methods and response block
#user.activate! #if you want to add some methods
end
end
end
The ActiveAdmin Gem creates a Admin::UsersController on the fly, based on the configuration of you admin/user.rb

Doorkeeper: How to know when a grant is created?

I would like to create a membership record when a user grants access to an app.
Does Doorkeeper have any event?
My solution was to use a rails observer:
Gemfile:
gem 'rails-observers'
app/models/doorkeeper/access_token_observer.rb:
class Doorkeeper::AccessTokenObserver < ActiveRecord::Observer
def after_create(access_token)
# do stuff with:
# access_token.application_id
# access_token.resource_owner_id
end
end

"undefined method `env' for nil:NilClass" in 'setup_controller_for_warden' error when testing Devise using Rspec

I'm trying to create a spec for a sign out flow by using factorygirl to create a user and then use Devise's sign_in method to authenticate the user, then use capybara to click the "Sign Out" link.
I'm getting (what seems to me to be) a strange error when I run the spec:
Failures:
1) Sign out flow successfully redirects to the welcome index (root)
Failure/Error: Unable to find matching line from backtrace
NoMethodError:
undefined method `env' for nil:NilClass
# /home/vagrant/.rvm/gems/ruby-2.0.0-p576/gems/devise-3.4.1/lib/devise/test_helpers.rb:24:in `setup_controller_for_warden'
Finished in 0.00226 seconds (files took 3.32 seconds to load)
1 example, 1 failure
Here's the spec:
require 'rails_helper'
describe "Sign out flow" do
include Devise::TestHelpers
describe "successfully" do
it "redirects to the welcome index (root)" do
user = create(:user)
sign_in user
within '.user-info' do
click_link 'Sign Out'
end
expect(current_path).to eq root_path
end
end
end
And my user.rb factory:
FactoryGirl.define do
factory :user do
name "Fake User"
sequence(:email, 100) { |n| "person#{n}#example.com" }
password "helloworld"
password_confirmation "helloworld"
confirmed_at Time.now
end
end
The error seems to be triggered simply from the line include Devise::TestHelpers, as I've tried commenting out the entire content of the spec and still get the same error.
I thought the Devise test helpers would work out of the box; did I miss some configuration? Thanks.
In Rails 5 you must include Devise::Test::IntegrationHelpers instead Devise::Test::ControllerHelpers:
# rails_helper.rb
config.include Devise::Test::IntegrationHelpers, type: :feature
See more:
https://github.com/plataformatec/devise/issues/3913#issuecomment
https://github.com/plataformatec/devise/pull/4071
Apparently there are issues with Devise::TestHelpers and integration testing, so perhaps that's the problem here.
https://github.com/plataformatec/devise (mentioned in README, Issues, etc.; also see related SO questions):
These helpers are not going to work for integration tests driven by Capybara or Webrat. They are meant to be used with functional tests only. Instead, fill in the form or explicitly set the user in session;
FWIW it seems like the issues have been fixed, however I ran into the issue after not reading the documentation well enough.
This was our code:
RSpec.configure do |config|
...
config.include Devise::TestHelpers
...
end
This means every test will include the test helpers, including models. This wound up being the issue for us. Should we have read the documentation closer we would have noticed Devise suggests limiting it to only controllers with:
RSpec.configure do |config|
...
config.include Devise::TestHelpers, type: :controller
...
end
This solved the issue for us. All tests passing :)
Here's my solution:
class ActiveSupport::TestCase
# all the normal stuff
end
class ActionController::TestCase
include Devise::TestHelpers
end
I meet the same error on rails 5.
Here's my solution
spec/rails_helper.rb
RSpec.configure do |config|
config.include Devise::TestHelpers, type: :controller
config.include Devise::TestHelpers, type: :view
config.include Warden::Test::Helpers
end
spec/controllers/your_controller_spec.rb
RSpec.describe YourController, type: :controller do
before(:all) do
user = FactoryGirl.create(:user)
login_as user, scope: :user
end
it "#index" do
get "index"
expect(response).to render_template(:index)
expect(response).to have_http_status(200)
end
$ rspec --tag focus
Run options: include {:focus=>true}
DashboardController
#index
Finished in 3.9 seconds (files took 3.5 seconds to load)
1 example, 0 failures
Like others have already said, you're including the Devise::TestHelpers. That's for testing controllers. If you'd still like to automatically login a test user in your integration tests, check out the official Devise Instructions on using it with Capybara.
Using Devise with Capybara
Basically, what you need to do is first enable Warden's test mode:
include Warden::Test::Helpers
Warden.test_mode!
Then, (create and) login your user:
user = FactoryGirl.create(:user)
login_as(user, scope: :user)
Example:
# spec/features/survey_spec.rb
require 'rails_helper'
feature 'survey app' do
include Warden::Test::Helpers
let(:user) { create(:user) }
let(:survey) { create(:survey_with_questions) }
before do
# Sign the User in
Warden.test_mode!
login_as(user, scope: user)
end
it 'renders the survey' do
visit survey_show_path(survey)
expect(page).to have_content(survey.title)
end
end
I was having this problem when trying to sign_in a user in a before hook:
before(:context) do
create(:skill, name: 'Google Maps API'.downcase)
user = create(:user)
sign_in user
end
Placing sign_in inside the before hook leads to:
Failure/Error: sign_in user
NoMethodError:
undefined method `env' for nil:NilClass
But placing it inside an example works fine:
shared_examples_for('an authenticated resource.') do
describe 'An authenticated request' do
it "responds with HTTP status OK" do
user = create(:user)
sign_in user
make_request
expect(response).to have_http_status(:ok)
end
end
end
But this can be improved, placing the sign_in into a before(:example) that will also work:
context 'allow search by keyword' do
let!(:skill){ create(:skill, name: 'Google Maps API'.downcase) }
let!(:user) { create(:user) }
before(:example) { sign_in user }
it 'finds matching records' do
get :search, name: "Google Maps API", format: :json
expect(assigns(:skills).size).to be(1)
end
it 'finds records that start with keyword'
it 'finds records that end with keyword'
it 'finds records that contains keyword'
end
My Devise version is 4.2.0 so I just included
config.include Devise::Test::ControllerHelpers, type: :controller
in my rails helper file.
Alternatively you can use the same in your spec as
include Devise::Test::ControllerHelpers
The correct syntax for Rails 5 / Devise (4.2.0) is
RSpec.configure do |config|
config.include Devise::Test::ControllerHelpers, :type => :controller
end
Devise::TestHelpers are deprecated so use Devise::Test::ControllerHelpers
:type => :controller - to limit only for
controllers and not models for example.
For the sake of being complete, with Rails 5 and RSpec I have run into similar issues when using the latest helpers, as they need to be set explicitly with the type when not used as a superclass.
So if you find yourself receiving there errors in your model tests there's a pretty good chance the type is not set.
Here's what I use in the spec_helper:
config.include Devise::Test::ControllerHelpers, type: :controller
config.include Devise::Test::ControllerHelpers, type: :view
config.include Devise::Test::IntegrationHelpers, type: :feature
I know that the docs do mention this, but there are times when you may run across an older blog that gives you an older approach, or upgrading from an older setup, and next thing you know this happens.

Getting tripped up by verify_partial_doubles with rails 4 and rspec 3

I'm using authlogic for my user authentication and in my ApplicationController I have "current_user", "current_user_session", etc. defined and set as helper_methods.
I have an extremely simple view spec for my main index:
RSpec.describe "main/index.html.erb", :type => :view do
context "when not logged in" do
before do
allow(view).to receive(:current_user).and_return(nil)
end
it "has an h1" do
render
expect(rendered).to include('h1')
end
end
end
The problem is that if "mocks.verify_partial_doubles = true" in my config then this causes an impressively massive error as it dumps an entire object and then says at the bottom:
1) main/index.html.erb when not logged in has an h1
Failure/Error: allow(view).to receive(:current_user).and_return(nil)
#<#<Class:0x00000104c249d0>:.........
#rendered_views={}>> does not implement: current_user
Of course, it is recommended that verify_partial_doubles is set to true, but in doing so this breaks. I pulled this straight from the documentation:
https://www.relishapp.com/rspec/rspec-rails/v/3-1/docs/view-specs/view-spec#passing-view-spec-that-stubs-a-helper-method
If the method appears in ApplicationHelper it'll work. But if it's in ApplicationController and defined as a helper_method there's no such luck:
helper_method :current_user, ...
def current_user
return #current_user if defined?(#current_user)
#current_user = current_user_session && current_user_session.record
end
I want the protection that verify_partial_doubles provides, how can I work around this?
This is a known issue and the only way to get it working is to extract the methods into a module and include it in your view helpers and the controller.
More information at: https://github.com/rspec/rspec-rails/issues/1076
You can disable double verification for views as follows:
RSpec.configure do |config|
config.before(:each, type: :view) do
config.mock_with :rspec do |mocks|
mocks.verify_partial_doubles = false
end
end
config.after(:each, type: :view) do
config.mock_with :rspec do |mocks|
mocks.verify_partial_doubles = true
end
end
end
This way you'll be able to keep stubbing view methods with:
allow(view).to receive(:current_user).and_return(nil)
More information at: https://github.com/rspec/rspec-rails/issues/1076