On Sep 17, 9:16 pm, Myron M. [email protected] wrote:
should be shown. I’m using rails 2.3.8 and rspec version 1.3.0. My
end
it "should return manage samples link for user with role
If the above doesn’t format well, here’s a gist:
Doug
that into an appropriate method on your user model:
[1]GitHub - ryanb/cancan: Authorization Gem for Ruby on Rails.
rspec-users mailing list
[email protected]://rubyforge.org/mailman/listinfo/rspec-users
Hi Myron,
I believe I understand what you’re suggesting. My code now looks like
this:
app/models/user.rb
class User < ActiveRecord::Base
has_and_belongs_to_many :roles
# stuff cut out for brevity
def role?(role)
roles.detect { |r| r.rolename == role.to_s }
end
def can_manage_samples?
[ :submitter, :reviewer, :admin ].any? { |r| role? r }
end
end
app/helpers/welcome_helper.rb
module WelcomeHelper
def manage_samples_link
if current_user.try(:can_manage_samples?)
link_to “Manage Samples”, manage_samples_path
end
end
end
spec/helpers/welcome_helper_spec.rb
require ‘spec_helper’
describe WelcomeHelper do
context "Manage Samples link" do
it "should not return manage_samples_link for nil user" do
helper.stub(:current_user).and_return(nil)
helper.manage_samples_link.should be_nil
end
it "should not return manage_samples_link for role-less user" do
user = mock_model(User)
user.stub(:can_manage_samples?).and_return(false)
helper.stub(:current_user).and_return(user)
helper.manage_samples_link.should be_nil
end
it "should return manage_samples_link for permitted user" do
user = mock_model(User)
user.stub(:can_manage_samples?).and_return(true)
helper.stub(:current_user).and_return(user)
link = %{<a href="/manage_samples">Manage Samples</a>}
helper.manage_samples_link.should == link
end
end
end
Here’s how I understand this: With a mocked User#can_manage_samples?
method, the test focuses not on the User class code, which should be
tested at the model level. What this test says is, 'If
User#can_manage_samples? is working correctly, then the correct users
will see the link.
What happens if when the app is in production and I’ve forgotten
writing this test, I’m told that some user who should be authorized to
is not seeing this link? The view test will still be passing because
I’ve told the User object to return what I want it to. Is the idea
that I should return to my integration tests and move back down
through the stack to isolate the problem?
It seems to me that the really challenging part of BDD/TDD is learning
the boundaries of what’s being tested and writing code that is
testable. I appreciate your help, very much.
As for CanCan, I am in fact using it, and based on this exchange, if I
wanted to use CanCan for determining whether to print this link, I
would set up the test up in the following way. Since CanCan adds,
among other methods, a ‘can?’ method which is included in the
controller and available to helpers and views, I would have the
following:
app/helpers/welcome_helper.rb
module WelcomeHelper
def manage_samples_link
link_to “Manage Samples”, manage_samples_path if can? :alter,
Sample
end
end
spec/helpers/welcome_helper_spec.rb
require ‘spec_helper’
describe WelcomeHelper do
context “Manage Samples link” do
it “should not return manage_samples_link for no or unauthorized
user” do
helper.should_receive(:can?).with(:alter,
Sample).and_return(false)
helper.manage_samples_link.should be_nil
end
it "should return manage_samples_link for authorized user" do
helper.should_receive(:can?).with(:alter,
Sample).and_return(true)
link = %{Manage Samples}
helper.manage_samples_link.should == link
end
end
end
My CanCan Ability implementation handles the case of a nil user,
creating an empty User object, as ryanb shows in his examples.
The reason I’m using roles and not CanCan for rendering this link and
navigating to the management page is off-topic, but it is this:
What I want to do is determine whether a user in general can do
something more than perform the :read action on a Sample, like
:submit, :edit, :delete, and so on. CanCan works at the class or
instance level, and while reviewers and admins can do stuff to any
Sample, submitters can only do stuff to certain samples, the ones they
created. I don’t want to hit the database to find out whether a
submitter has created any samples. I just want all users who can
do stuff to Samples to be able to get to the Manage Samples page.
So I would create a general “do stuff to samples” action and
give submitters, reviewers, and admins authorization to it. I call it
:alter, because :manage is a special CanCan action that maps to any
action (e.g., admins `can :manage, User’).
But, I decided, in this case I’m just interested in a class of
users. If down the line I realize I need something more complex for
allowing access to this page, then I can add it.
Again, thanks.
Doug