close #34. Pagination for content entries implemented + do not use Kaminari anymore + fix a couple of tiny bugs (wrong field name for the default order_by field of a has_many relationship, automatically remove the order_by attribute from a query selector, ...etc)

did committed Mar 20, 2015
commit 3b6daf8ee49801fc1b44d83c934d7ebcf9d9b6d8
Showing 31 changed files with 417 additions and 368 deletions
Gemfile +2 -0
@@ @@ -19,6 +19,8 @@ group :test do
gem 'pry-byebug', '~> 3.0.1'
+ gem 'rack-test', '~> 0.6.3'
+
gem 'codeclimate-test-reporter', '~> 0.4.7', require: false
gem 'coveralls', '~> 0.7.11', require: false
end
Gemfile.lock +1 -29
@@ @@ -10,7 +10,6 @@ PATH
dragonfly (~> 1.0.7)
haml (~> 4.0.6)
httparty (~> 0.13.3)
- kaminari (~> 0.16.3)
kramdown (~> 1.6.0)
locomotivecms-solid (~> 4.0.0.alpha2)
locomotivecms_common (~> 0.0.2)
@@ @@ -30,19 +29,6 @@ GEM
remote: https://rubygems.org/
specs:
RedCloth (4.2.9)
- actionpack (4.2.0)
- actionview (= 4.2.0)
- activesupport (= 4.2.0)
- rack (~> 1.6.0)
- rack-test (~> 0.6.2)
- rails-dom-testing (~> 1.0, >= 1.0.5)
- rails-html-sanitizer (~> 1.0, >= 1.0.1)
- actionview (4.2.0)
- activesupport (= 4.2.0)
- builder (~> 3.1)
- erubis (~> 2.7.0)
- rails-dom-testing (~> 1.0, >= 1.0.5)
- rails-html-sanitizer (~> 1.0, >= 1.0.1)
activesupport (4.2.0)
i18n (~> 0.7)
json (~> 1.7, >= 1.7.7)
@@ @@ -51,7 +37,6 @@ GEM
tzinfo (~> 1.1)
addressable (2.3.7)
bson (2.3.0)
- builder (3.2.2)
byebug (3.5.1)
columnize (~> 0.8)
debugger-linecache (~> 1.2)
@@ @@ -95,7 +80,6 @@ GEM
addressable (~> 2.3)
multi_json (~> 1.0)
rack
- erubis (2.7.0)
eventmachine (1.0.4)
execjs (2.4.0)
ffi (1.9.8)
@@ @@ -114,17 +98,12 @@ GEM
json_spec (1.1.4)
multi_json (~> 1.0)
rspec (>= 2.0, < 4.0)
- kaminari (0.16.3)
- actionpack (>= 3.0.0)
- activesupport (>= 3.0.0)
kramdown (1.6.0)
locomotivecms-liquid (4.0.0.alpha2)
locomotivecms-solid (4.0.0.alpha2)
locomotivecms-liquid (~> 4.0.0.alpha2)
locomotivecms_common (0.0.2)
colorize
- loofah (2.0.1)
- nokogiri (>= 1.5.9)
method_source (0.8.2)
mime-types (2.4.3)
mimetype-fu (0.1.2)
@@ @@ -160,14 +139,6 @@ GEM
rack (>= 1.0)
rack_csrf (2.5.0)
rack (>= 1.1.0)
- rails-deprecated_sanitizer (1.0.3)
- activesupport (>= 4.2.0.alpha)
- rails-dom-testing (1.0.5)
- activesupport (>= 4.2.0.beta, < 5.0)
- nokogiri (~> 1.6.0)
- rails-deprecated_sanitizer (>= 1.0.1)
- rails-html-sanitizer (1.0.2)
- loofah (~> 2.0)
rake (10.4.2)
rb-fsevent (0.9.4)
rb-inotify (0.9.5)
@@ @@ -235,6 +206,7 @@ DEPENDENCIES
moped (~> 2.0.4)
origin (~> 2.1.1)
pry-byebug (~> 3.0.1)
+ rack-test (~> 0.6.3)
rake (~> 10.4.2)
rspec (~> 3.2.0)
thin
locomotive/steam.rb b/lib/locomotive/steam.rb +0 -1
@@ @@ -7,7 +7,6 @@ require 'active_support/core_ext'
require_relative 'steam/core_ext'
require_relative 'steam/configuration'
- require_relative_all 'steam/monkey_patches'
require_relative_all 'steam/decorators'
require_relative 'steam/liquid'
locomotive/steam/adapters/filesystem.rb b/lib/locomotive/steam/adapters/filesystem.rb +4 -0
@@ @@ -50,6 +50,10 @@ module Locomotive::Steam
''
end
+ def count(mapper, scope, &block)
+ query(mapper, scope, &block).count
+ end
+
private
def _query(mapper, scope, &block)
locomotive/steam/adapters/filesystem/yaml_loaders/content_entry.rb b/lib/locomotive/steam/adapters/filesystem/yaml_loaders/content_entry.rb +1 -1
@@ @@ -50,7 +50,7 @@ module Locomotive
attributes[:"#{field.name}_id"] = attributes.delete(field.name.to_sym)
# _position_in_<name>
- attributes[:"_position_in_#{field.name}"] = attributes[:_position]
+ attributes[:"position_in_#{field.name}"] = attributes[:_position]
end
def modify_many_to_many_association(field, attributes)
locomotive/steam/adapters/mongodb.rb b/lib/locomotive/steam/adapters/mongodb.rb +9 -0
@@ @@ -18,6 +18,15 @@ module Locomotive::Steam
all(mapper, query)
end
+ def count(mapper, scope, &block)
+ query = query_klass.new(scope, mapper.localized_attributes, &block)
+ query.against(collection(mapper)).count
+ end
+
+ def find(mapper, scope, id)
+ query(mapper, scope) { where(_id: BSON::ObjectId.from_string(id)) }.first
+ end
+
def key(name, operator)
name.__send__(operator)
end
locomotive/steam/adapters/mongodb/query.rb b/lib/locomotive/steam/adapters/mongodb/query.rb +13 -3
@@ @@ -7,7 +7,7 @@ module Locomotive::Steam
attr_reader :criteria, :sort
def initialize(scope, localized_attributes, &block)
- @criteria, @sort, @fields = {}, nil, nil
+ @criteria, @sort, @fields, @skip, @limit = {}, nil, nil, nil, nil
@scope, @localized_attributes = scope, localized_attributes
apply_default_scope
@@ @@ -33,13 +33,23 @@ module Locomotive::Steam
end
end
+ def offset(offset)
+ self.tap { @skip = offset }
+ end
+
+ def limit(limit)
+ self.tap { @limit = limit }
+ end
+
def against(collection)
_query = to_origin
selector, fields, sort = _query.selector, _query.options[:fields], _query.options[:sort]
collection.find(selector).tap do |results|
- results.sort(sort) if sort
- results.select(fields) if fields
+ results.sort(sort) if sort
+ results.select(fields) if fields
+ results.skip(@skip) if @skip
+ results.limit(@limit) if @limit
end
end
locomotive/steam/entities/content_type_field.rb b/lib/locomotive/steam/entities/content_type_field.rb +6 -3
@@ @@ -24,9 +24,12 @@ module Locomotive::Steam
end
def order_by
- return self[:order_by] if self[:order_by]
-
- type == :has_many ? "position_in_#{self[:inverse_of]}" : nil
+ if (order_by = self[:order_by]).present?
+ name, direction = order_by.split
+ { name.to_sym => direction || 'asc' }
+ else
+ type == :has_many ? { :"position_in_#{self[:inverse_of]}" => 'asc' } : nil
+ end
end
alias :target :class_name
locomotive/steam/liquid.rb b/lib/locomotive/steam/liquid.rb +0 -1
@@ @@ -4,6 +4,5 @@ require_relative 'liquid/errors'
require_relative 'liquid/patches'
require_relative 'liquid/drops/base'
require_relative 'liquid/drops/i18n_base'
- require_relative 'liquid/drops/proxy_collection'
require_relative 'liquid/tags/hybrid'
require_relative_all %w(. drops filters tags/concerns tags), 'liquid'
locomotive/steam/liquid/drops/content_entry_collection.rb b/lib/locomotive/steam/liquid/drops/content_entry_collection.rb +77 -0
@@ @@ -0,0 +1,77 @@
+ module Locomotive
+ module Steam
+ module Liquid
+ module Drops
+
+ class ContentEntryCollection < ::Liquid::Drop
+
+ delegate :first, :last, :each, :each_with_index, :empty?, :any?, to: :collection
+
+ def initialize(content_type, repository = nil)
+ @content_type = content_type
+ @repository = repository
+ end
+
+ def all
+ collection
+ end
+
+ def count
+ repository.count(conditions)
+ end
+
+ alias :size :count
+ alias :length :count
+
+ def public_submission_url
+ services.url_builder.public_submission_url_for(@content_type)
+ end
+
+ def api
+ Locomotive::Common::Logger.warn "[Liquid template] the api for content_types has been deprecated and replaced by public_submission_url instead."
+ { 'create' => public_submission_url }
+ end
+
+ def before_method(meth)
+ if (meth.to_s =~ /^group_by_(.+)$/) == 0
+ repository.group_by_select_option(@content_type, $1)
+ elsif (meth.to_s =~ /^(.+)_options$/) == 0
+ content_type_repository.select_options(@content_type, $1)
+ else
+ Locomotive::Common::Logger.warn "[Liquid template] trying to call #{meth} on a content_type object"
+ nil
+ end
+ end
+
+ protected
+
+ def slice(index, length)
+ repository.all(conditions) { offset(index).limit(length) }
+ end
+
+ def collection
+ @collection ||= repository.all(conditions)
+ end
+
+ def conditions
+ @context['with_scope']
+ end
+
+ def services
+ @context.registers[:services]
+ end
+
+ def content_type_repository
+ services.repositories.content_type
+ end
+
+ def repository
+ @repository || services.repositories.content_entry.with(@content_type)
+ end
+
+ end
+
+ end
+ end
+ end
+ end
locomotive/steam/liquid/drops/content_types.rb b/lib/locomotive/steam/liquid/drops/content_types.rb +1 -52
@@ @@ -8,7 +8,7 @@ module Locomotive
repository = @context.registers[:services].repositories.content_type
if content_type = repository.by_slug(meth.to_s)
- ContentTypeProxyCollection.new(content_type)
+ ContentEntryCollection.new(content_type)
else
nil
end
@@ @@ -16,57 +16,6 @@ module Locomotive
end
- class ContentTypeProxyCollection < ProxyCollection
-
- def initialize(content_type)
- @content_type = content_type
- super(nil)
- end
-
- def public_submission_url
- services.url_builder.public_submission_url_for(@content_type)
- end
-
- def api
- Locomotive::Common::Logger.warn "[Liquid template] the api for content_types has been deprecated and replaced by public_submission_url instead."
- { 'create' => public_submission_url }
- end
-
- def before_method(meth)
- if (meth.to_s =~ /^group_by_(.+)$/) == 0
- repository.group_by_select_option(@content_type, $1)
- elsif (meth.to_s =~ /^(.+)_options$/) == 0
- content_type_repository.select_options(@content_type, $1)
- else
- Locomotive::Common::Logger.warn "[Liquid template] trying to call #{meth} on a content_type object"
- nil
- end
- end
-
- protected
-
- def paginate(options = {})
- raise "TODO #{options.inspect}"
- end
-
- def services
- @context.registers[:services]
- end
-
- def content_type_repository
- services.repositories.content_type
- end
-
- def collection
- @collection ||= repository.all(@context['with_scope'])
- end
-
- def repository
- services.repositories.content_entry.with(@content_type)
- end
-
- end
-
end
end
end
locomotive/steam/liquid/drops/page.rb b/lib/locomotive/steam/liquid/drops/page.rb +1 -1
@@ @@ -41,7 +41,7 @@ module Locomotive
if @_source.content_type
# content_type can be either the slug of a content type or a content type
content_type = content_type_repository.by_slug(@_source.content_type)
- ContentTypeProxyCollection.new(content_type)
+ ContentEntryCollection.new(content_type)
else
nil
end
locomotive/steam/liquid/drops/proxy_collection.rb b/lib/locomotive/steam/liquid/drops/proxy_collection.rb +0 -33
@@ @@ -1,33 +0,0 @@
- module Locomotive
- module Steam
- module Liquid
- module Drops
-
- class ProxyCollection < ::Liquid::Drop
-
- attr_reader :collection
-
- delegate :first, :last, :each, :each_with_index, :empty?, :any?, to: :collection
-
- def initialize(collection)
- @collection = collection
- end
-
- def count
- @count ||= collection.count
- end
-
- def all
- collection
- self
- end
-
- alias :size :count
- alias :length :count
-
- end
-
- end
- end
- end
- end
locomotive/steam/liquid/tags/paginate.rb b/lib/locomotive/steam/liquid/tags/paginate.rb +3 -7
@@ @@ -56,16 +56,12 @@ module Locomotive
collection = context[@collection_name]
current_page = context['current_page']
- raise ::Liquid::ArgumentError.new("Cannot paginate array '#{@collection_name}'. Not found.") if collection.nil?
+ raise ::Liquid::ArgumentError.new("Cannot paginate '#{@collection_name}'. Not found.") if collection.nil?
- pagination = (if collection.is_a?(Array)
- Kaminari.paginate_array(collection).page(current_page).per(@per_page)
- else
- collection.send(:paginate, page: current_page, per_page: @per_page)
- end)
+ pager = Locomotive::Steam::Models::Pager.new(collection, current_page, @per_page)
# make sure the pagination object is a hash with strings as keys (and not symbol)
- HashConverter.to_string(pagination.to_liquid).tap do |_pagination|
+ HashConverter.to_string(pager.to_liquid).tap do |_pagination|
_pagination['parts'] = []
end
end
locomotive/steam/models.rb b/lib/locomotive/steam/models.rb +1 -0
@@ @@ -9,3 +9,4 @@ require_relative 'models/entity'
require_relative 'models/mapper'
require_relative 'models/scope'
require_relative 'models/repository'
+ require_relative 'models/pager'
locomotive/steam/models/associations/has_many.rb b/lib/locomotive/steam/models/associations/has_many.rb +0 -1
@@ @@ -1,7 +1,6 @@
module Locomotive::Steam
module Models
- # Note: represents an embedded collection
class HasManyAssociation < ReferencedAssociation
def __load__
locomotive/steam/models/associations/many_to_many.rb b/lib/locomotive/steam/models/associations/many_to_many.rb +0 -1
@@ @@ -1,7 +1,6 @@
module Locomotive::Steam
module Models
- # Note: represents an embedded collection
class ManyToManyAssociation < ReferencedAssociation
def __load__
locomotive/steam/models/pager.rb b/lib/locomotive/steam/models/pager.rb +53 -0
@@ @@ -0,0 +1,53 @@
+ module Locomotive::Steam
+ module Models
+
+ class Pager
+
+ DEFAULT_PER_PAGE = 10.freeze
+
+ attr_reader :collection, :current_page, :per_page, :total_pages, :total_entries
+
+ def initialize(source, page, per_page)
+ @current_page, @per_page = page || 1, per_page || DEFAULT_PER_PAGE
+
+ @total_entries = source.count
+ @total_pages = (@total_entries.to_f / @per_page).ceil
+
+ index = (@current_page - 1) * @per_page
+ offset = (index + @per_page - 1) >= @total_entries ? @total_entries : (index + @per_page - 1)
+
+ @collection = paginate(source, index, offset)
+ end
+
+ def previous_page
+ current_page <= 1 ? nil : current_page - 1
+ end
+
+ def next_page
+ current_page >= total_pages ? nil : current_page + 1
+ end
+
+ def to_liquid
+ {
+ collection: collection,
+ current_page: current_page,
+ per_page: per_page,
+ previous_page: previous_page,
+ next_page: next_page,
+ total_entries: total_entries,
+ total_pages: total_pages
+ }
+ end
+
+ private
+
+ def paginate(source, index, offset)
+ limit = offset - index + 1
+ limit = 0 if limit < 1
+ source.send(:slice, index, limit) || []
+ end
+
+ end
+
+ end
+ end
locomotive/steam/models/repository.rb b/lib/locomotive/steam/models/repository.rb +9 -3
@@ @@ -39,6 +39,10 @@ module Locomotive::Steam
adapter.query(mapper, scope, &block)
end
+ def count(&block)
+ adapter.count(mapper, scope, &block)
+ end
+
def first(&block)
adapter.query(mapper, scope, &block).first
end
@@ @@ -66,12 +70,14 @@ module Locomotive::Steam
end
def prepare_conditions(*conditions)
- first = { order_by: @local_conditions.delete(:order_by) }.delete_if { |_, v| v.blank? }
+ _local_conditions = @local_conditions.dup
+
+ first = { order_by: _local_conditions.delete(:order_by) }.delete_if { |_, v| v.blank? }
- [first, *conditions].inject({}) do |memo, hash|
+ [first, *conditions.flatten].inject({}) do |memo, hash|
memo.merge!(hash) unless hash.blank?
memo
- end.merge(@local_conditions)
+ end.merge(_local_conditions)
end
# TODO: not sure about that. could it be used further in the dev
locomotive/steam/monkey_patches/haml.rb b/lib/locomotive/steam/monkey_patches/haml.rb +0 -17
@@ @@ -1,17 +0,0 @@
- # require 'haml'
-
- # module Haml::Filters
-
- # remove_filter("Markdown") #remove the existing Markdown filter
-
- # module Markdown # the contents of this are as before, but without the lazy_require call
-
- # include Haml::Filters::Base
-
- # def render text
- # Locomotive::Steam::Markdown.new.render text
- # end
-
- # end
-
- # end
locomotive/steam/monkey_patches/kaminari.rb b/lib/locomotive/steam/monkey_patches/kaminari.rb +0 -45
@@ @@ -1,45 +0,0 @@
- # Note: avoid this issue https://github.com/amatsuda/kaminari/issues/518
- require 'kaminari/config'
- require 'kaminari/models/configuration_methods'
- require 'kaminari/models/page_scope_methods'
- require 'kaminari/models/array_extension'
-
- module Kaminari
-
- module PageScopeMethods
-
- def to_liquid(options = {})
- {
- collection: to_a,
- current_page: current_page,
- previous_page: first_page? ? nil : current_page - 1,
- total_entries: total_count,
- per_page: limit_value
- }.tap do |hash|
- # note: very important to avoid extra and useless mongodb requests
- hash[:total_pages] = (hash[:total_entries].to_f / limit_value).ceil
- hash[:next_page] = current_page >= hash[:total_pages] ? nil : current_page + 1
- end
- end
-
- end
-
- # FIXME: it does not seem to be called
- # class PaginatableArray < Array
-
- # def to_liquid(options = {})
- # puts "PaginatableArray.instance.to_liquid"
- # {
- # collection: to_a,
- # current_page: current_page,
- # previous_page: first_page? ? nil : current_page - 1,
- # next_page: last_page? ? nil : current_page + 1,
- # total_entries: total_count,
- # total_pages: num_pages,
- # per_page: limit_value
- # }
- # end
-
- # end
-
- end
locomotive/steam/repositories/content_entry_repository.rb b/lib/locomotive/steam/repositories/content_entry_repository.rb +30 -7
@@ @@ -32,29 +32,38 @@ module Locomotive
self # chainable
end
- def all(conditions = {})
- conditions = prepare_conditions({ _visible: true }, conditions)
+ def all(conditions = {}, &block)
+ conditions, order_by = conditions_without_order_by(conditions)
# priority:
# 1/ order_by passed in the conditions parameter
# 2/ the default order (_position) defined in the content type
- order_by = conditions.delete(:order_by)|| conditions.delete('order_by') || content_type.order_by
+ order_by ||= content_type.order_by
- query { where(conditions).order_by(order_by) }.all
+ query {
+ (block_given? ? instance_eval(&block) : where).
+ where(conditions).
+ order_by(order_by)
+ }.all
+ end
+
+ def count(conditions = {})
+ conditions, _ = conditions_without_order_by(conditions)
+ super() { where(conditions) }
end
def find(id)
- conditions = prepare_conditions(_id: id)
+ conditions, _ = conditions_without_order_by(_id: id)
first { where(conditions) }
end
def exists?(conditions = {})
- conditions = prepare_conditions(conditions)
+ conditions, _ = conditions_without_order_by(conditions)
query { where(conditions) }.all.size > 0
end
def by_slug(slug)
- conditions = prepare_conditions(_slug: slug)
+ conditions, _ = conditions_without_order_by(_slug: slug)
first { where(conditions) }
end
@@ @@ -97,6 +106,10 @@ module Locomotive
end
end
+ def to_liquid
+ Locomotive::Steam::Liquid::Drops::ContentEntryCollection.new(content_type, self)
+ end
+
private
def mapper
@@ @@ -110,6 +123,16 @@ module Locomotive
end
end
+ def conditions_without_order_by(conditions = {})
+ _conditions = prepare_conditions(conditions)
+ order_by = _conditions.delete(:order_by) || _conditions.delete('order_by')
+ [_conditions, order_by]
+ end
+
+ def prepare_conditions(*conditions)
+ super({ _visible: true }, conditions)
+ end
+
def add_localized_fields_to_mapper(mapper)
unless self.content_type.localized_names.blank?
mapper.localized_attributes(*self.content_type.localized_names)
locomotivecms_steam.gemspec +0 -1
@@ @@ -40,7 +40,6 @@ Gem::Specification.new do |spec|
spec.add_dependency 'coffee-script', '~> 2.3.0'
spec.add_dependency 'compass', '~> 1.0.3'
- spec.add_dependency 'kaminari', '~> 0.16.3'
spec.add_dependency 'kramdown', '~> 1.6.0'
spec.add_dependency 'RedCloth', '~> 4.2.9'
spec.add_dependency 'haml', '~> 4.0.6'
spec/integration/liquid/tags/paginate_spec.rb +33 -74
@@ @@ -13,9 +13,10 @@ describe Locomotive::Steam::Liquid::Tags::Paginate do
EOF
}
+ let(:page) { nil }
let(:site) { Locomotive::Steam::Site.new(_id: site_id, locales: %w(en fr nb)) }
let(:services) { Locomotive::Steam::Services.build_instance }
- let(:assigns) { { 'contents' => Locomotive::Steam::Liquid::Drops::ContentTypes.new } }
+ let(:assigns) { { 'contents' => Locomotive::Steam::Liquid::Drops::ContentTypes.new, 'fullpath' => '/', 'current_page' => page } }
let(:context) { ::Liquid::Context.new(assigns, {}, { services: services }) }
before {
@@ @@ -26,95 +27,53 @@ EOF
subject { render_template(source, context) }
- context 'Filesystem' do
-
- let(:site_id) { 1 }
- let(:adapter) { Locomotive::Steam::FilesystemAdapter.new(default_fixture_site_path) }
-
- it { is_expected.to eq '!RoR!MongoDB!Liquid!ReactJS!DCI' }
-
- end
-
-
-
-
- # describe 'simple array' do
-
- # subject { output }
-
- # it { is_expected.to include '!RoR!MongoDB!Liquid!ReactJS!DCI' }
- # it { is_expected.not_to include '!Bootstrap' }
+ shared_examples_for 'pagination' do
- # describe 'second page of results: display the last item' do
+ it { is_expected.to match '!Song #1!Song #2!Song #3!Song #4!Song #5' }
- # let(:page) { 2 }
- # it { is_expected.to include '!Bootstrap' }
- # it { is_expected.not_to include '!RoR!MongoDB!Liquid!ReactJS!DCI' }
+ describe 'second page' do
+ let(:page) { 2 }
+ it { is_expected.to match '!Song #6!Song #7!Song #8' }
+ end
- # end
+ describe 'pagination of a has_many association' do
- # end
-
- # describe 'array from a db collection' do
-
- # let(:projects) { KindaDBCollection.new(['RoR', 'MongoDB', 'Liquid', 'ReactJS', 'DCI', 'Bootstrap']) }
-
- # subject { output }
-
- # it { is_expected.to include '!RoR!MongoDB!Liquid!ReactJS!DCI' }
- # it { is_expected.not_to include '!Bootstrap' }
-
- # end
+ let(:source) { <<-EOF
+ {% with_scope _slug: 'the-who' %}
+ {% assign band = contents.bands.first %}
+ {% endwith_scope %}
+ {% paginate band.songs by 1 %}
+ -{% for song in paginate.collection %}!{{ song.title }}{% endfor %}-
+ {% endpaginate %}'
+ EOF
+ }
- # describe 'a very big collection' do
+ it { is_expected.to match '-!Song #5-' }
- # let(:projects) { (1..100).to_a }
- # let(:page) { 20 }
- # let(:source) { '{% paginate projects by 2, window_size: 10 %}{% assign _pagination = paginate %}{% endpaginate %}' }
+ end
- # before { output }
- # subject { context['_pagination']['parts'] }
+ end
- # it { expect(subject.first['title']).to eq 1 }
- # it { expect(subject[1]['title']).to eq '&hellip;' }
- # it { expect(subject[2]['title']).to eq 11 }
- # it { expect(subject[21]['title']).to eq '&hellip;' }
- # it { expect(subject.last['title']).to eq 50 }
+ context 'Filesystem' do
- # end
+ it_should_behave_like 'pagination' do
- # describe ''
+ let(:site_id) { 1 }
+ let(:adapter) { Locomotive::Steam::FilesystemAdapter.new(default_fixture_site_path) }
- # end
+ end
- # class KindaDBCollection < Struct.new(:collection)
+ end
- # def paginate(options = {})
- # total_pages = (collection.size.to_f / options[:per_page].to_f).to_f.ceil + 1
- # offset = (options[:page] - 1) * options[:per_page]
+ context 'MongoDB' do
- # {
- # collection: collection[offset..(offset + options[:per_page]) - 1],
- # current_page: options[:page],
- # previous_page: options[:page] == 1 ? 1 : options[:page] - 1,
- # next_page: options[:page] == total_pages ? total_pages : options[:page] + 1,
- # total_entries: collection.size,
- # total_pages: total_pages,
- # per_page: options[:per_page]
- # }
- # end
+ it_should_behave_like 'pagination' do
- # def each(&block)
- # collection.each(&block)
- # end
+ let(:site_id) { BSON::ObjectId.from_string('54eb49c12475804b2b000002') }
+ let(:adapter) { Locomotive::Steam::MongoDBAdapter.new(database: 'steam_test', hosts: ['127.0.0.1:27017']) }
- # def method_missing(method, *args)
- # collection.send(method, *args)
- # end
+ end
- # def to_liquid
- # self
- # end
- # end
+ end
end
spec/integration/repositories/content_entry_repository_spec.rb +5 -0
@@ @@ -18,6 +18,11 @@ describe Locomotive::Steam::ContentEntryRepository do
it { expect(subject.size).to eq 3 }
end
+ describe '#count' do
+ subject { repository.count }
+ it { is_expected.to eq 3 }
+ end
+
describe '#by_slug' do
subject { repository.by_slug('alice-in-chains') }
it { expect(subject.name).to eq 'Alice in Chains' }
spec/unit/adapters/filesystem/yaml_loaders/content_entry_spec.rb +1 -1
@@ @@ -28,7 +28,7 @@ describe Locomotive::Steam::Adapters::Filesystem::YAMLLoaders::ContentEntry do
it 'adds a new attribute for the foreign key' do
expect(subject.first[:band_id]).to eq 'pearl-jam'
expect(subject.first[:band]).to eq nil
- expect(subject.first[:_position_in_band]).to eq 0
+ expect(subject.first[:position_in_band]).to eq 0
end
end
spec/unit/entities/content_type_field_spec.rb +3 -3
@@ @@ -20,12 +20,12 @@ describe Locomotive::Steam::ContentTypeField do
context 'has_many field' do
let(:attributes) { { name: 'articles', type: 'has_many', inverse_of: 'author' } }
- it { is_expected.to eq 'position_in_author' }
+ it { is_expected.to eq(position_in_author: 'asc') }
context 'order_by is specified' do
let(:attributes) { { name: 'articles', type: 'has_many', inverse_of: 'author', order_by: 'name asc' } }
- it { is_expected.to eq 'name asc' }
+ it { is_expected.to eq(name: 'asc') }
end
@@ @@ -60,7 +60,7 @@ describe Locomotive::Steam::ContentTypeField do
subject { content_type.association_options }
- it { is_expected.to eq({ target_id: 'articles', inverse_of: 'author', order_by: 'position_in_author' }) }
+ it { is_expected.to eq(target_id: 'articles', inverse_of: 'author', order_by: { position_in_author: 'asc' }) }
end
spec/unit/liquid/drops/content_entry_collection_spec.rb +81 -0
@@ @@ -0,0 +1,81 @@
+ require 'spec_helper'
+
+ describe Locomotive::Steam::Liquid::Drops::ContentEntryCollection do
+
+ let(:assigns) { {} }
+ let(:content_type) { instance_double('ContentType', slug: 'articles') }
+ let(:services) { Locomotive::Steam::Services.build_instance }
+ let(:context) { ::Liquid::Context.new(assigns, {}, { services: services }) }
+ let(:drop) { described_class.new(content_type).tap { |d| d.context = context } }
+
+ describe '#public_submission_url' do
+ it { expect(drop.public_submission_url).to eq '/entry_submissions/articles' }
+ end
+
+ describe '#api' do
+ it { expect(drop.api).to eq({ 'create' => '/entry_submissions/articles' }) }
+ end
+
+ describe 'acts as a collection' do
+
+ before do
+ allow(services.repositories.content_entry).to receive(:all).with(nil).and_return(['a', 'b'])
+ end
+
+ describe '#first' do
+ it { expect(drop.first).to eq('a') }
+ end
+
+ describe '#last' do
+ it { expect(drop.last).to eq('b') }
+ end
+
+ context 'with a scope' do
+
+ let(:assigns) { { 'with_scope' => { 'visible' => true } } }
+
+ describe '#first' do
+ before do
+ expect(services.repositories.content_entry).to receive(:all).with({ 'visible' => true }).and_return(['a', 'b'])
+ end
+ it { expect(drop.first).to eq('a') }
+ end
+
+ describe '#count' do
+ before do
+ expect(services.repositories.content_entry).to receive(:count).with({ 'visible' => true }).and_return(2)
+ end
+ it { expect(drop.count).to eq 2 }
+ end
+
+ end
+
+ end
+
+ describe 'get options of a select field' do
+
+ before do
+ expect(services.repositories.content_type).to receive(:select_options).with(content_type, 'category').and_return(['a', 'b'])
+ end
+
+ it { expect(drop.before_method(:category_options)).to eq ['a', 'b'] }
+
+ end
+
+ describe 'group entries by a select/belongs_to field' do
+
+ before do
+ expect(services.repositories.content_entry).to receive(:group_by_select_option).with(content_type, 'category').and_return([['a', [1, 2]]])
+ end
+
+ it { expect(drop.before_method(:group_by_category)).to eq [['a', [1, 2]]] }
+
+ end
+
+ describe 'unknown method' do
+
+ it { expect(drop.before_method(:foo)).to eq nil }
+
+ end
+
+ end
spec/unit/liquid/drops/content_type_proxy_collection_spec.rb +0 -83
@@ @@ -1,83 +0,0 @@
- require 'spec_helper'
-
- describe Locomotive::Steam::Liquid::Drops::ContentTypeProxyCollection do
-
- let(:assigns) { {} }
- let(:content_type) { instance_double('ContentType', slug: 'articles') }
- let(:services) { Locomotive::Steam::Services.build_instance }
- let(:context) { ::Liquid::Context.new(assigns, {}, { services: services }) }
- let(:drop) { described_class.new(content_type).tap { |d| d.context = context } }
-
- describe '#public_submission_url' do
- it { expect(drop.public_submission_url).to eq '/entry_submissions/articles' }
- end
-
- describe '#api' do
- it { expect(drop.api).to eq({ 'create' => '/entry_submissions/articles' }) }
- end
-
- describe 'acts as a collection' do
-
- before do
- allow(services.repositories.content_entry).to receive(:all).with(nil).and_return(['a', 'b'])
- end
-
- describe '#first' do
- it { expect(drop.first).to eq('a') }
- end
-
- describe '#last' do
- it { expect(drop.last).to eq('b') }
- end
-
- describe '#count' do
- it { expect(drop.count).to eq 2 }
- end
-
- context 'with a scope' do
-
- let(:assigns) { { 'with_scope' => { 'visible' => true } } }
-
- before do
- expect(services.repositories.content_entry).to receive(:all).with({ 'visible' => true }).and_return(['a', 'b'])
- end
-
- describe '#first' do
- it { expect(drop.first).to eq('a') }
- end
-
- describe '#count' do
- it { expect(drop.count).to eq 2 }
- end
-
- end
-
- end
-
- describe 'get options of a select field' do
-
- before do
- expect(services.repositories.content_type).to receive(:select_options).with(content_type, 'category').and_return(['a', 'b'])
- end
-
- it { expect(drop.before_method(:category_options)).to eq ['a', 'b'] }
-
- end
-
- describe 'group entries by a select/belongs_to field' do
-
- before do
- expect(services.repositories.content_entry).to receive(:group_by_select_option).with(content_type, 'category').and_return([['a', [1, 2]]])
- end
-
- it { expect(drop.before_method(:group_by_category)).to eq [['a', [1, 2]]] }
-
- end
-
- describe 'unknown method' do
-
- it { expect(drop.before_method(:foo)).to eq nil }
-
- end
-
- end
spec/unit/liquid/tags/paginate_spec.rb +1 -1
@@ @@ -45,7 +45,7 @@ EOF
subject { output }
- it { expect { subject }.to raise_error(::Liquid::ArgumentError, "Liquid error: Cannot paginate array 'projects'. Not found.") }
+ it { expect { subject }.to raise_error(::Liquid::ArgumentError, "Liquid error: Cannot paginate 'projects'. Not found.") }
end
spec/unit/models/pager_spec.rb +82 -0
@@ @@ -0,0 +1,82 @@
+ require 'spec_helper'
+
+ describe Locomotive::Steam::Models::Pager do
+
+ let(:page) { 1 }
+ let(:per_page) { 2 }
+ let(:source) { ['MongoDB', 'Rails', 'Liquid', 'Rack', 'Devise'] }
+ let(:pager) { described_class.new(source, page, per_page) }
+
+ describe '#collection' do
+
+ subject { pager.collection }
+
+ it { is_expected.to eq ['MongoDB', 'Rails'] }
+
+ describe 'last page' do
+ let(:page) { 3 }
+ it { is_expected.to eq ['Devise'] }
+ end
+
+ describe 'per_page is 1' do
+ let(:per_page) { 1 }
+ it { is_expected.to eq ['MongoDB'] }
+ end
+
+ describe 'per_page is > to the number of total entries' do
+ let(:per_page) { 10 }
+ it { is_expected.to eq ['MongoDB', 'Rails', 'Liquid', 'Rack', 'Devise'] }
+ end
+
+ describe 'page is > to the total number of pages' do
+ let(:page) { 4 }
+ it { is_expected.to eq [] }
+ end
+
+ end
+
+ describe '#previous_page' do
+
+ subject { pager.previous_page }
+
+ it { is_expected.to eq nil }
+
+ describe 'another page' do
+ let(:page) { 2 }
+ it { is_expected.to eq 1 }
+ end
+
+ end
+
+ describe '#next_page' do
+
+ subject { pager.next_page }
+
+ it { is_expected.to eq 2 }
+
+ describe 'another page' do
+ let(:page) { 3 }
+ it { is_expected.to eq nil }
+ end
+
+ end
+
+ describe '#to_liquid' do
+
+ subject { pager.to_liquid }
+
+ it do
+ is_expected.to eq({
+ collection: ['MongoDB', 'Rails'],
+ current_page: 1,
+ per_page: 2,
+ previous_page: nil,
+ next_page: 2,
+ total_entries: 5,
+ total_pages: 3
+ })
+ end
+
+ end
+
+ end