Skip to content

Commit

Permalink
Add characters list
Browse files Browse the repository at this point in the history
This also enables cancan and improves testing.
  • Loading branch information
ekampp committed Apr 3, 2013
1 parent 254a7f3 commit 6d782fe
Show file tree
Hide file tree
Showing 18 changed files with 205 additions and 3 deletions.
3 changes: 3 additions & 0 deletions app/controllers/application_controller.rb
Expand Up @@ -10,6 +10,9 @@ class ApplicationController < ActionController::Base
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception

# Enable CanCan
enable_authorization

# Allows decent exposure to use strong parameters.
decent_configuration do
strategy DecentExposure::StrongParametersStrategy
Expand Down
12 changes: 12 additions & 0 deletions app/controllers/characters_controller.rb
@@ -0,0 +1,12 @@
class CharactersController < ApplicationController
expose :character, attributes: :character_params
expose(:characters){ current_user.characters }
load_and_authorize_resource

private

def character_params
params.require(:character).permit(:name)
end

end
1 change: 1 addition & 0 deletions app/controllers/users_controller.rb
@@ -1,5 +1,6 @@
class UsersController < ApplicationController
expose :user, attributes: :user_params
load_and_authorize_resource

def update
user.save
Expand Down
21 changes: 21 additions & 0 deletions app/models/ability.rb
@@ -0,0 +1,21 @@
class Ability
include CanCan::Ability

def initialize(user)
user ||= User.new

can :access, :sessions
can :read, :application
can :read, :characters

# Registered users
if user.persisted?
can :update, :users, id: user.id

if user.valid?
can :update, :characters, user_id: user.id
can :access, :users, id: user.id
end
end
end
end
10 changes: 10 additions & 0 deletions app/models/character.rb
@@ -0,0 +1,10 @@
class Character
include Mongoid::Document
include Mongoid::Timestamps

field :name, type: String

belongs_to :user

validates :name, presence: true
end
3 changes: 3 additions & 0 deletions app/models/user.rb
Expand Up @@ -22,6 +22,9 @@ class User
validates :age, presence: true, confirmation: true,
numericality: { greater_than_or_equal_to: 16 }

# Associations
has_many :characters

# Returns a user object based on the hash schema returned by the omniauth
# gem.
#
Expand Down
15 changes: 15 additions & 0 deletions app/views/characters/index.html.haml
@@ -0,0 +1,15 @@
.container
.row
.span12
%h1= t(".title")
%p.lead= t(".lead")

.row
.span12
.media
- characters.each do |character|
= link_to [:edit, character], class: "pull-left" do
%img(data-source="http://placehold.it/64x64" class="media-object")
.media-body
= link_to [:edit, character] do
%h2= character.name
16 changes: 16 additions & 0 deletions config/initializers/cancan.rb
@@ -0,0 +1,16 @@
module CanCan
class ControllerResource

# Extends CanCan in such a way that it supports the way that decent
# exposure sets collection variables.
#
def collection_instance
collection_name = instance_name.to_s.pluralize
if @controller.instance_variable_defined? "@#{collection_name}"
@controller.instance_variable_get("@#{collection_name}")
elsif @controller.respond_to?(collection_name, true)
@controller.send(collection_name)
end
end
end
end
14 changes: 13 additions & 1 deletion config/locales/en.yml
@@ -1,4 +1,16 @@
en:
sessions:
new:
sign_in: Sign in
twitter_sign_in: "Sign in with twitter"
developer_sign_in: "Sign in as a developer"

characters:
index:
title: "My characters"
lead: |
Below you can see your current characters, and their progress.
layouts:
menu:
sign_out_tip: "Sign out"
Expand All @@ -23,7 +35,7 @@ en:
create:
success: You have been signed in
missing_information: |
To somplete you sign in, we need a little more information
To complete you sign in, we need a little more information
application:
render_404: Sorry. That page isn't available.
render_401: You are not authorized to view that page!
3 changes: 3 additions & 0 deletions db/seeds.rb
Expand Up @@ -6,3 +6,6 @@
role: :admin,
email: nil
emil.save validation: false

FactoryGirl.create :character, user: emil
FactoryGirl.create :character, user: emil
5 changes: 5 additions & 0 deletions spec/controllers/characters_controller_spec.rb
@@ -0,0 +1,5 @@
require 'spec_helper'

describe CharactersController do

end
8 changes: 8 additions & 0 deletions spec/factories/characters.rb
@@ -0,0 +1,8 @@
# Read about factories at https://github.com/thoughtbot/factory_girl

FactoryGirl.define do
factory :character do
name { Faker::Name.name }
user nil
end
end
10 changes: 9 additions & 1 deletion spec/factories/users.rb
Expand Up @@ -4,7 +4,7 @@
factory :user do
name { Faker::Name.name }
email { Faker::Internet.email }
uid 345345
uid { Faker::Base.numerify "#######" }
provider "twitter"
role "user"
session_id { SecureRandom.urlsafe_base64 }
Expand All @@ -19,5 +19,13 @@
credentials: { token: u.token }
end
end

trait :with_characters do
after :create do |u|
create :character, user: u
create :character, user: u
u = u.reload
end
end
end
end
24 changes: 24 additions & 0 deletions spec/features/characters_spec.rb
@@ -0,0 +1,24 @@
require "spec_helper"

describe "Listing characters" do
let(:user) { create :user, :with_characters, :mock_omniauth }
let(:other_user) { create :user, :with_characters }

before do
user # execute the block to stub the user
visit sign_in_path
click_link "twitter_sign_in"
visit characters_path
end

describe "page" do
subject{ page }

it { should have_content I18n.translate("characters.index.title") }
it "should have all the user's characters" do
user.characters.each do |character|
should have_content character.name
end
end
end
end
2 changes: 1 addition & 1 deletion spec/features/users_spec.rb
Expand Up @@ -60,7 +60,7 @@

describe "Update settings" do
before do
@user = create :user, :mock_omniauth, provider: :developer
@user = create :user, :mock_omniauth
end

context "when logged in" do
Expand Down
34 changes: 34 additions & 0 deletions spec/models/ability_spec.rb
@@ -0,0 +1,34 @@
require "spec_helper"
require "cancan/matchers"

describe Ability do
subject{ Ability.new(user) }

describe "as guest" do
let(:user) { build :user }

it { should be_able_to :access, :sessions }
it { should be_able_to :read, :application }
it { should_not be_able_to :access, :characters }
it { should_not be_able_to :update, :user }
end

describe "as registered, incomplete user" do
let(:user) { u = build(:user, email: nil); u.save(validate: false); u }

it { should be_able_to :access, :sessions }
it { should_not be_able_to :access, :characters }
it { should be_able_to :update, user }
end

describe "as registered, complete user" do
let(:user) { create :user }
let(:other_user) { create :user }

it { should be_able_to :access, :sessions }
it { should be_able_to :update, :characters, user_id: user.id }
it { should be_able_to :update, build(:character, user: user) }
it { should_not be_able_to :update, build(:character, user: other_user) }
it { should be_able_to :access, user }
end
end
17 changes: 17 additions & 0 deletions spec/models/character_spec.rb
@@ -0,0 +1,17 @@
require 'spec_helper'

describe Character do
subject{ build :character }

# Fields
it { should be_timestamped_document }
it { should have_field(:name).with_default_value_of(nil) }

# Validations
it { should be_valid }
it { should validate_presence_of(:name) }

# Associations
it { should belong_to :user }

end
10 changes: 10 additions & 0 deletions spec/models/user_spec.rb
Expand Up @@ -43,6 +43,16 @@
it { should validate_presence_of(:age) }
it { should validate_numericality_of(:age).greater_than_or_equal_to(16) }

describe "factories" do
describe "with_characters" do
subject{ create(:user, :with_characters).characters }
its(:count) { should eq 2 }
end
end

# Associations
it { should have_many :characters }

describe "class methods" do
describe ".find_or_build_from_omniauth_hash" do
subject{ User.find_or_build_from_omniauth_hash(hash) }
Expand Down

0 comments on commit 6d782fe

Please sign in to comment.