Commit 7421d9c8
Changed files (12)
app
controllers
models
concerns
creation
services
application
spec
features
models
services
application
queries
app/controllers/concerns/pageable.rb
@@ -0,0 +1,12 @@
+module Pageable
+ extend ActiveSupport::Concern
+ DEFAULT_PER_PAGE=12
+
+ def page
+ params[:page]
+ end
+
+ def per_page
+ params[:per_page] || DEFAULT_PER_PAGE
+ end
+end
app/controllers/application_controller.rb
@@ -1,4 +1,5 @@
class ApplicationController < ActionController::Base
+ include Pageable
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
app/controllers/creations_controller.rb
@@ -1,6 +1,6 @@
class CreationsController < ApplicationController
def index
- @creations = FindAllCreationsQuery.new.fetch(params)
+ @creations = AllCakesQuery.new.fetch(params).page(page).per(per_page)
end
def show
app/models/concerns/filterable.rb
@@ -0,0 +1,11 @@
+module Filterable
+ extend ActiveSupport::Concern
+
+ module ClassMethods
+ def filtered_by(search_filters)
+ search_filters.inject(self) do |memo, next_filter|
+ next_filter.call(memo)
+ end
+ end
+ end
+end
app/models/creation/repository.rb
@@ -1,5 +1,7 @@
class Creation
+ include Filterable
scope :tagged, ->(tag) { tagged_with([tag]).where('photos_count > 0') }
+ scope :published, ->() { unscoped.distinct.includes(:user, :photos).joins(:photos).where('photos.image_processing' => nil) }
class Repository < SimpleDelegator
def initialize(connection = Creation)
@@ -15,10 +17,6 @@ class Creation
connection.includes(:user, :photos).where(["upper(name) like :query OR upper(story) like :query", { query: "%#{query.upcase}%" }])
end
- def visible_creations
- connection.unscoped.distinct.includes(:user, :photos).joins(:photos).where('photos.image_processing' => nil)
- end
-
private
attr_reader :connection
app/services/application/all_cakes_query.rb
@@ -0,0 +1,23 @@
+class AllCakesQuery
+ def initialize(repository = Spank::IOC.resolve(:cakes))
+ @repository = repository
+ end
+
+ def fetch(params)
+ @repository.filtered_by(search_filters_for(params))
+ end
+
+ private
+
+ def search_filters_for(params)
+ [
+ ->(cakes) { cakes.published },
+ ->(cakes) { params[:category].blank? ? cakes.all : cakes.where(category_id: Category.find_by_slug(params[:category].downcase).id) },
+ ->(cakes) { cakes.order(created_at: sort(params)) },
+ ]
+ end
+
+ def sort(params)
+ params[:sort] == "oldest" ? :asc : :desc
+ end
+end
app/services/application/find_all_creations_query.rb
@@ -1,22 +0,0 @@
-class FindAllCreationsQuery
- DEFAULT_PER_PAGE=12
-
- def initialize(repository = Spank::IOC.resolve(:cakes))
- @repository = repository
- end
-
- def fetch(params)
- @repository.visible_creations.order(created_at: sort(params)).page(params[:page]).per(per_page(params))
- end
-
- private
-
- def per_page(params)
- params[:per_page] || DEFAULT_PER_PAGE
- end
-
- def sort(params)
- params[:sort] == "oldest" ? :asc : :desc
- end
-end
-
spec/features/creations_spec.rb
@@ -1,13 +1,13 @@
require 'rails_helper'
-describe "Creations" do
+describe "Creations", js: true do
describe "GET /creations" do
before :each do
visit creations_path
end
- it "should load the page properly" do
- page.should have_content("CakeSide")
+ it "loads the page" do
+ expect(page).to have_content("CakeSide")
end
end
end
spec/models/creation/repository_spec.rb
@@ -20,7 +20,7 @@ describe Creation::Repository do
end
end
- describe "#visible_creations" do
+ describe "#published" do
let!(:user){ create(:user) }
let!(:published_cake){ create(:creation, user: user) }
@@ -28,7 +28,7 @@ describe Creation::Repository do
published_cake.photos.create(image: 'example.png', image_processing: nil)
end
- let(:results) { subject.visible_creations }
+ let(:results) { subject.published }
it "returns cakes that do not have photos that are processing" do
expect(results.count).to eql(1)
spec/models/creation_repository_spec.rb
@@ -1,30 +0,0 @@
-require "rails_helper"
-
-describe CreationRepository do
- describe "#visible_creations" do
- let!(:user){ create(:user) }
- let!(:published_cake){ create(:creation, user: user) }
-
- before :each do
- published_cake.photos.create(image: 'example.png', image_processing: nil)
- end
-
- let(:results) { subject.visible_creations }
-
- it "returns cakes that do not have photos that are processing" do
- expect(results.count).to eql(1)
- expect(results).to include(published_cake)
- end
- end
-
- describe "#search" do
- let(:cake) { create(:creation, name: 'Cake') }
- let(:cup_cake) { create(:creation, name: 'Cup Cake') }
-
- it "returns cakes with a matching name" do
- results = subject.search('cake')
- expect(results).to include(cake)
- expect(results).to_not include(cup_cake)
- end
- end
-end
spec/services/application/all_cakes_query_spec.rb
@@ -0,0 +1,41 @@
+require "rails_helper"
+
+describe AllCakesQuery do
+ subject { AllCakesQuery.new }
+
+ context "with no filters" do
+ let!(:cake_with_a_photo) { create(:cake) }
+ let!(:cake_without_a_photo) { create(:cake, photos: []) }
+
+ before :each do
+ cake_with_a_photo.photos << create(:photo)
+ end
+
+ it "returns all cakes with at least one photo" do
+ results = subject.fetch({})
+ expect(results).to include(cake_with_a_photo)
+ end
+
+ it "ignores cakes without a photo" do
+ results = subject.fetch({})
+ expect(results).to_not include(cake_without_a_photo)
+ end
+ end
+
+ context "with filters" do
+ let(:cake_category) { create(:category) }
+ let!(:cake) { create(:cake, category: cake_category) }
+ let!(:cookie) { create(:cake) }
+
+ before :each do
+ cake.photos << create(:photo)
+ cookie.photos << create(:photo)
+ end
+
+ it 'returns all cakes in a specific category' do
+ cakes = subject.fetch(category: cake_category.slug)
+ expect(cakes).to include(cake)
+ expect(cakes).to_not include(cookie)
+ end
+ end
+end
spec/services/queries/find_all_creations_query_spec.rb
@@ -1,22 +0,0 @@
-require "rails_helper"
-
-describe FindAllCreationsQuery do
- subject { FindAllCreationsQuery.new }
- let(:results) { subject.fetch({}) }
-
- let!(:cake_with_a_photo) { create(:creation) }
- let!(:cake_without_a_photo) { create(:creation, photos: []) }
-
- before :each do
- cake_with_a_photo.photos << create(:photo)
- cake_with_a_photo.photos.first.update_attribute(:image_processing, nil)
- end
-
- it "returns all creations with at least one photo" do
- expect(results).to include(cake_with_a_photo)
- end
-
- it "ignores cakes without a photo" do
- expect(results).to_not include(cake_without_a_photo)
- end
-end