Commit f074930f

mo khan <mo@mokhan.ca>
2014-10-16 03:18:21
extract user repository
1 parent 2383271
app/controllers/admin/users_controller.rb
@@ -1,11 +1,20 @@
 module Admin
   class UsersController < AdminController
+    def initialize(users_repository = Spank::IOC.resolve(:users))
+      @users_repository = users_repository
+      super()
+    end
+
     def index
-      @users = User.search_by(params[:q])
+      @users = users_repository.search_by(params[:q])
     end
 
     def show
-      @user = User.includes(creations: :photos).find(params[:id])
+      @user = users_repository.includes(creations: :photos).find(params[:id])
     end
+
+    private
+
+    attr_reader :users_repository
   end
 end
app/controllers/profiles_controller.rb
@@ -1,12 +1,21 @@
 class ProfilesController < ApplicationController
   before_action :authenticate!, :except => [:index, :show]
 
+  def initialize(repository = Spank::IOC.resolve(:users))
+    @repository = repository
+    super()
+  end
+
   def index
-    @profiles = User.includes(:avatar).where('creations_count > 0').order(creations_count: :desc).page(params[:page]).per(12)
+    @profiles = repository.artists.page(params[:page]).per(12)
   end
 
   def show
-    @user = User.find(params[:id])
+    @user = repository.find(params[:id])
     @creations = @user.creations.includes(:photos)
   end
+
+  private
+
+  attr_reader :repository
 end
app/models/user.rb
@@ -5,16 +5,16 @@ class User < ActiveRecord::Base
 
   validates :name, presence: true
   validates :email, presence: true, uniqueness: true, email: true
-  validates :website, :format => URI::regexp(%w(http https)), :allow_blank => true
-  validates_length_of       :password, :within => 6..20, :allow_blank => true
+  validates :website, format: URI::regexp(%w(http https)), allow_blank: true
+  validates_length_of :password, within: 6..20, allow_blank: true
 
-  has_many :creations, :dependent => :destroy
-  has_many :favorites, :dependent => :destroy
-  has_many :tutorials, :dependent => :destroy
+  has_many :creations, dependent: :destroy
+  has_many :favorites, dependent: :destroy
+  has_many :tutorials, dependent: :destroy
   has_many :activities, dependent: :destroy
   has_many :comments, dependent: :destroy
   has_many :user_sessions, dependent: :destroy
-  has_and_belongs_to_many :interests, :join_table => 'users_interests', :autosave => true
+  has_and_belongs_to_many :interests, join_table: 'users_interests', autosave: true
   has_one :avatar, class_name: 'Photo', as: :imageable
   acts_as_tagger
 
@@ -66,15 +66,6 @@ class User < ActiveRecord::Base
   end
 
   class << self
-    def ordered
-      User.order(:creations_count => :desc)
-    end
-
-    def search_by(query)
-      return self.all if query.blank?
-      self.where('name like :query or email like :query', query: "#{query}%")
-    end
-
     def login(username, password)
       user = User.find_by(email: username)
       return false if user.nil?
app/models/user_repository.rb
@@ -0,0 +1,24 @@
+class UserRepository
+  def initialize(connection = User)
+    @connection = connection
+  end
+
+  delegate :all, :includes, :find, to: :connection
+
+  def ordered
+    connection.order(creations_count: :desc)
+  end
+
+  def artists
+    connection.includes(:avatar).where('creations_count > 0').order(creations_count: :desc)
+  end
+
+  def search_by(query)
+    return connection.all if query.blank?
+    connection.where('name like :query or email like :query', query: "#{query}%")
+  end
+
+  private
+
+  attr_reader :connection
+end
app/views/creations/_show.html.erb
@@ -8,7 +8,7 @@
       <% if current_user.already_likes(@creation) %>
         <i class="fa fa-star fa-4x pull-right"></i>
       <% else %>
-        <%= link_to creation_favorites_path(creation_id: @creation.id), method: :post, class: 'pull-right' do %>
+        <%= link_to creation_favorites_path(creation_id: @creation.id), method: :post, id: 'add-to-favorites-button', class: 'pull-right' do %>
           <i class="fa fa-star-o fa-4x"></i>
         <% end %>
       <% end %>
app/views/creations/show.html.erb
@@ -21,4 +21,4 @@
   </div>
 <% end %>
 
-<%= render :partial => "shared/disqus", :locals => { :id => "c-#{@creation.id}" } %>
+<%= render partial: "shared/disqus", locals: { id: "c-#{@creation.id}" } %>
config/initializers/container.rb
@@ -18,6 +18,7 @@ class ConfigureContainerCommand
     # repositories
     container.register(:cakes) { |builder| Creation }
     container.register(:photos) { |builder| Photo }
+    container.register(:users) { |builder| UserRepository.new }.as_singleton
   end
 end
 
spec/controllers/admin/users_controller_spec.rb
@@ -18,7 +18,9 @@ module Admin
 
       it "returns users that match the search results" do
         matching_user = double
-        User.stub(:search_by).with('mo').and_return([matching_user])
+        repository = double
+        controller.stub(:users_repository).and_return(repository)
+        repository.stub(:search_by).with('mo').and_return([matching_user])
         get :index, q: 'mo'
         expect(assigns(:users)).to include(matching_user)
       end
spec/features/add_to_favorites_spec.rb
@@ -1,19 +1,19 @@
 require "rails_helper"
 
-describe "adding a cake to your favorites", :js => true do
+describe "adding a cake to your favorites", js: true do
   let!(:creation) { create(:creation, user: create(:user), photos: [create(:photo)]) }
-  let!(:me) { create(:user, :password => "password") }
+  let!(:me) { create(:user, password: "password") }
 
   before :each do
     visit login_path
     within('.form-inline') do
-      fill_in('session_username', :with => me.email)
-      fill_in('session_password', :with => "password")
+      fill_in('session_username', with: me.email)
+      fill_in('session_password', with: "password")
     end
     click_button("Sign In")
     visit root_path
     click_link(creation.name[0...12])
-    click_button("ADD TO FAVORITES")
+    click_link_or_button("add-to-favorites-button")
   end
 
   it "should redirect you to the cake after" do 
spec/features/profiles_spec.rb
@@ -2,10 +2,9 @@ require 'rails_helper'
 
 describe "Profiles" do
   describe "GET /profiles" do
-    it "works! (now write some real specs)" do
+    it "it loads" do
       visit profiles_path
-      page.should have_content 'CakeSide'
+      expect(page).to have_content('CakeSide')
     end
   end
-
 end
spec/models/user_repository_spec.rb
@@ -0,0 +1,45 @@
+require 'rails_helper'
+
+describe UserRepository do
+  subject { UserRepository.new }
+
+  describe "#all" do
+    let!(:user) { create(:user) }
+
+    it 'returns all the users' do
+      expect(subject.all).to include(user)
+    end
+  end
+
+  describe "#ordered" do
+    let!(:first_person) { create(:user, creations_count: 0) }
+    let!(:second_person) { create(:user, creations_count: 1) }
+
+    let(:results) { subject.ordered }
+
+    it "should load the person with the most cakes first" do
+      expect(results.first).to eql(second_person)
+    end
+
+    it "should load the person with the least cakes last" do
+      expect(results.last).to eql(first_person)
+    end
+  end
+
+  describe "#search_by" do
+    let!(:mo) { create(:user) }
+    let!(:bob) { create(:user) }
+
+    it "returns a user that has a matching email address" do
+      results = subject.search_by(mo.email)
+      expect(results).to include(mo)
+      expect(results).to_not include(bob)
+    end
+
+    it "returns a user that has a matching name" do
+      results = subject.search_by(bob.name)
+      expect(results).to include(bob)
+      expect(results).to_not include(mo)
+    end
+  end
+end
spec/models/user_spec.rb
@@ -123,21 +123,6 @@ describe User do
     end
   end
 
-  describe "when loading all the users" do
-    let!(:first_person) { create(:user, :creations_count => 0) }
-    let!(:second_person) { create(:user, :creations_count => 1) }
-
-    let(:results) { User.ordered }
-
-    it "should load the person with the most cakes first" do
-      results.first.should == second_person
-    end
-
-    it "should load the person with the least cakes last" do
-      results.last.should == first_person
-    end
-  end
-
   describe "send welcome email" do
     let(:user) { build(:user) }
     let(:mailer) { double("mailer", welcome_email: true) }
@@ -183,21 +168,4 @@ describe User do
       end
     end
   end
-
-  describe ".search_by" do
-    let!(:mo) { create(:user) }
-    let!(:bob) { create(:user) }
-
-    it "returns a user that has a matching email address" do
-      results = User.search_by(mo.email)
-      expect(results).to include(mo)
-      expect(results).to_not include(bob)
-    end
-
-    it "returns a user that has a matching name" do
-      results = User.search_by(bob.name)
-      expect(results).to include(bob)
-      expect(results).to_not include(mo)
-    end
-  end
 end