introduce the proxy collection liquid drop so that we can paginate for real + fix the cucumber features for the public part of the engine
This commit is contained in:
parent
02e48f5c36
commit
085a54d7c1
2
Gemfile
2
Gemfile
@ -33,7 +33,7 @@ group :test do
|
||||
|
||||
# gem 'growl-glue'
|
||||
|
||||
# gem 'cucumber-rails'
|
||||
gem 'cucumber-rails'
|
||||
gem 'rspec-rails', '~> 2.8.0'
|
||||
gem 'shoulda-matchers'
|
||||
|
||||
|
@ -135,6 +135,10 @@ GEM
|
||||
gherkin (~> 2.7.1)
|
||||
json (>= 1.4.6)
|
||||
term-ansicolor (>= 1.0.6)
|
||||
cucumber-rails (1.2.1)
|
||||
capybara (>= 1.1.2)
|
||||
cucumber (>= 1.1.3)
|
||||
nokogiri (>= 1.5.0)
|
||||
database_cleaner (0.7.1)
|
||||
devise (1.5.3)
|
||||
bcrypt-ruby (~> 3.0)
|
||||
@ -317,6 +321,7 @@ DEPENDENCIES
|
||||
coffee-rails (~> 3.2.2)
|
||||
compass!
|
||||
compass-rails!
|
||||
cucumber-rails
|
||||
custom_fields!
|
||||
database_cleaner
|
||||
factory_girl_rails (~> 1.6.0)
|
||||
|
@ -11,8 +11,8 @@ If we have to give a couple of features to describe our application, there will
|
||||
* nice looking UI (see http://www.locomotivecms.com for some screenshots)
|
||||
* flexible content types
|
||||
* content localization out of the box
|
||||
* playing smoothly with Heroku and MongoHQ
|
||||
* inline editing (beta)
|
||||
* playing smoothly with Heroku, Bushido and MongoHQ
|
||||
* inline editing (wip)
|
||||
* API
|
||||
|
||||
h2. Strategy / Development status
|
||||
@ -24,8 +24,8 @@ h2. Gems
|
||||
|
||||
Here is a short list of main gems / technologies used in the application.
|
||||
|
||||
* Rails 3.1 (3.2 soon)
|
||||
* Mongoid 2.4.2 (with MongoDB 2.0)
|
||||
* Rails 3.2
|
||||
* Mongoid 2.4.3 (with MongoDB 2.0)
|
||||
* Liquid
|
||||
* Devise
|
||||
* Carrierwave
|
||||
@ -40,7 +40,7 @@ See the "official website":http://www.locomotivecms.com
|
||||
|
||||
h2. Upgrading
|
||||
|
||||
If you wish to upgrade your locomotive install from an older version to the current 1.0.0rc1 then "please refer to the upgrade guide":http://www.locomotivecms.com/support/howto/upgrade
|
||||
We work on the procedure to upgrade from a previous version of the engine (below the 2.0.0)
|
||||
|
||||
h2. Community
|
||||
|
||||
|
46
Rakefile
46
Rakefile
@ -5,6 +5,38 @@ rescue LoadError
|
||||
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
||||
end
|
||||
|
||||
APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
||||
|
||||
# === Locomotive tasks ===
|
||||
load 'lib/tasks/locomotive.rake'
|
||||
|
||||
# === Gems install tasks ===
|
||||
Bundler::GemHelper.install_tasks
|
||||
|
||||
# === Travis
|
||||
task :travis do
|
||||
["rspec spec", "cucumber -b"].each do |cmd|
|
||||
puts "Starting to run #{cmd}..."
|
||||
system("export DISPLAY=:99.0 && bundle exec #{cmd}")
|
||||
raise "#{cmd} failed!" unless $?.exitstatus == 0
|
||||
end
|
||||
end
|
||||
|
||||
# === RSpec ===
|
||||
require 'rspec/core/rake_task'
|
||||
RSpec::Core::RakeTask.new(:spec)
|
||||
|
||||
# === Cucumber ===
|
||||
load 'lib/tasks/cucumber.rake'
|
||||
|
||||
# === Default task ===
|
||||
task :default => [:spec, :cucumber]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# begin
|
||||
# require 'rdoc/task'
|
||||
# rescue LoadError
|
||||
@ -13,20 +45,6 @@ end
|
||||
# RDoc::Task = Rake::RDocTask
|
||||
# end
|
||||
|
||||
APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
||||
|
||||
load 'lib/tasks/locomotive.rake'
|
||||
|
||||
# FIXME: it is disabled because it loaded twice the Locomotive engine
|
||||
# load 'rails/tasks/engine.rake'
|
||||
|
||||
require 'rspec/core/rake_task'
|
||||
RSpec::Core::RakeTask.new(:spec)
|
||||
|
||||
task :default => :spec
|
||||
|
||||
Bundler::GemHelper.install_tasks
|
||||
|
||||
|
||||
# # require File.expand_path('../config/application', __FILE__)
|
||||
#
|
||||
|
@ -1,3 +1,4 @@
|
||||
@wip
|
||||
@javascript
|
||||
Feature: Engine
|
||||
As an author
|
@ -5,16 +5,17 @@ Given %r{^I have an? "([^"]*)" model which has many "([^"]*)"$} do |parent_model
|
||||
end
|
||||
@child_model = FactoryGirl.build(:content_type, :site => @site, :name => child_model).tap do |ct|
|
||||
ct.entries_custom_fields.build :label => 'Body', :type => 'string', :required => false
|
||||
ct.entries_custom_fields.build :label => parent_model.singularize, :kind => 'has_one', :required => false, :target => parent_model
|
||||
ct.entries_custom_fields.build :label => parent_model.singularize.downcase, :type => 'belongs_to', :required => false, :class_name => @parent_model.klass_with_custom_fields(:entries).to_s
|
||||
ct.save!
|
||||
end
|
||||
|
||||
@parent_model.entries_custom_fields.build({
|
||||
:label => child_model,
|
||||
:kind => 'has_many',
|
||||
:target => @child_model.content_klass.to_s,
|
||||
:reverse_lookup => @child_model.content_klass.custom_field_alias_to_name(parent_model.downcase.singularize)
|
||||
:type => 'has_many',
|
||||
:class_name => @child_model.klass_with_custom_fields(:entries).to_s,
|
||||
:inverse_of => parent_model.singularize.downcase
|
||||
})
|
||||
@parent_model.save
|
||||
end
|
||||
|
||||
Then /^I should be able to view a paginaed list of a has many association$/ do
|
||||
@ -23,17 +24,14 @@ Then /^I should be able to view a paginaed list of a has many association$/ do
|
||||
|
||||
# Create contents
|
||||
article = @parent_model.entries.create!(:slug => 'parent', :body => 'Parent')
|
||||
@child_model.entries.create!(:slug => 'one', :body => 'One', :custom_field_2 => article.id.to_s)
|
||||
@child_model.entries.create!(:slug => 'two', :body => 'Two', :custom_field_2 => article.id.to_s)
|
||||
@child_model.entries.create!(:slug => 'three', :body => 'Three', :custom_field_2 => article.id.to_s)
|
||||
|
||||
@child_model.entries.each do |comment|
|
||||
article.comments << comment
|
||||
end
|
||||
@child_model.entries.create!(:slug => 'one', :body => 'One', :article => article)
|
||||
@child_model.entries.create!(:slug => 'two', :body => 'Two', :article => article)
|
||||
@child_model.entries.create!(:slug => 'three', :body => 'Three', :article => article)
|
||||
|
||||
# Create a page
|
||||
raw_template = %{
|
||||
{% for article in contents.articles %}
|
||||
{% for article in models.articles %}
|
||||
{{ article.body }}
|
||||
{% paginate article.comments by 2 %}
|
||||
{% for comment in paginate.collection %}
|
||||
{{ comment.body }}
|
||||
@ -48,11 +46,11 @@ Then /^I should be able to view a paginaed list of a has many association$/ do
|
||||
|
||||
# The page should have the first two comments
|
||||
visit '/hello'
|
||||
|
||||
page.should have_content 'One'
|
||||
page.should have_content 'Two'
|
||||
page.should_not have_content 'Three'
|
||||
|
||||
|
||||
# The second page should have the last comment
|
||||
click_link '2'
|
||||
page.should_not have_content 'One'
|
||||
|
@ -1,6 +1,6 @@
|
||||
Then /^I should be able to display paginated models$/ do
|
||||
# Create our article model and three articles
|
||||
@article_model = FactoryGirl.build(:content_type, :site => @site, :name => 'Articles').tap do |ct|
|
||||
@article_model = FactoryGirl.build(:content_type, :site => @site, :name => 'Articles', :order_by => '_position').tap do |ct|
|
||||
ct.entries_custom_fields.build :label => 'Body', :type => 'string', :required => false
|
||||
ct.save!
|
||||
end
|
||||
|
@ -1,4 +1,5 @@
|
||||
require 'locomotive/liquid/drops/base'
|
||||
require 'locomotive/liquid/drops/proxy_collection'
|
||||
|
||||
%w{. tags drops filters}.each do |dir|
|
||||
Dir[File.join(File.dirname(__FILE__), 'liquid', dir, '*.rb')].each { |lib| require lib }
|
||||
|
@ -9,6 +9,10 @@ module Locomotive
|
||||
self._source._id.to_s
|
||||
end
|
||||
|
||||
def _label
|
||||
@_label ||= self._source._label
|
||||
end
|
||||
|
||||
# Returns the next content for the parent content type.
|
||||
# If no content is found, nil is returned.
|
||||
#
|
||||
@ -40,11 +44,16 @@ module Locomotive
|
||||
|
||||
if not @@forbidden_attributes.include?(meth.to_s)
|
||||
value = self._source.send(meth)
|
||||
end
|
||||
end
|
||||
|
||||
def _label
|
||||
@_label ||= self._source._label
|
||||
if value.respond_to?(:all)
|
||||
# returns a mongoid criterion in order to chain pagination criteria
|
||||
value.all
|
||||
else
|
||||
value
|
||||
end
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -5,49 +5,18 @@ module Locomotive
|
||||
|
||||
def before_method(meth)
|
||||
type = @context.registers[:site].content_types.where(:slug => meth.to_s).first
|
||||
ProxyCollection.new(type)
|
||||
ContentTypeProxyCollection.new(type)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class ProxyCollection < ::Liquid::Drop
|
||||
class ContentTypeProxyCollection < ProxyCollection
|
||||
|
||||
def initialize(content_type)
|
||||
@content_type = content_type
|
||||
@collection = nil
|
||||
end
|
||||
|
||||
def first
|
||||
self.collection.first
|
||||
end
|
||||
|
||||
def last
|
||||
self.collection.last
|
||||
end
|
||||
|
||||
def each(&block)
|
||||
self.collection.each(&block)
|
||||
end
|
||||
|
||||
def each_with_index(&block)
|
||||
self.collection.each_with_index(&block)
|
||||
end
|
||||
|
||||
def count
|
||||
@count ||= self.collection.count
|
||||
end
|
||||
|
||||
alias :size :count
|
||||
alias :length :count
|
||||
|
||||
def empty?
|
||||
self.collection.empty?
|
||||
end
|
||||
|
||||
def any?
|
||||
self.collection.any?
|
||||
end
|
||||
|
||||
def public_submission_url
|
||||
@context.registers[:controller].main_app.locomotive_entry_submissions_url(@content_type.slug)
|
||||
end
|
||||
@ -59,16 +28,11 @@ module Locomotive
|
||||
klass.send(meth, :ordered_entries)
|
||||
else
|
||||
Rails.logger.warn "[Liquid template] trying to call #{meth} on a content_type object"
|
||||
# klass.send(meth)
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def paginate(options = {})
|
||||
self.collection.page(options[:page]).per(options[:per_page])
|
||||
end
|
||||
|
||||
def collection
|
||||
@collection ||= @content_type.ordered_entries(@context['with_scope'])
|
||||
end
|
||||
|
56
lib/locomotive/liquid/drops/proxy_collection.rb
Normal file
56
lib/locomotive/liquid/drops/proxy_collection.rb
Normal file
@ -0,0 +1,56 @@
|
||||
module Locomotive
|
||||
module Liquid
|
||||
module Drops
|
||||
|
||||
class ProxyCollection < ::Liquid::Drop
|
||||
|
||||
def initialize(collection)
|
||||
@collection = collection
|
||||
end
|
||||
|
||||
def first
|
||||
self.collection.first
|
||||
end
|
||||
|
||||
def last
|
||||
self.collection.last
|
||||
end
|
||||
|
||||
def each(&block)
|
||||
self.collection.each(&block)
|
||||
end
|
||||
|
||||
def each_with_index(&block)
|
||||
self.collection.each_with_index(&block)
|
||||
end
|
||||
|
||||
def count
|
||||
@count ||= self.collection.count
|
||||
end
|
||||
|
||||
alias :size :count
|
||||
alias :length :count
|
||||
|
||||
def empty
|
||||
self.collection.empty?
|
||||
end
|
||||
|
||||
def any
|
||||
self.collection.any?
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def paginate(options = {})
|
||||
@collection = collection.page(options[:page]).per(options[:per_page])
|
||||
end
|
||||
|
||||
def collection
|
||||
@collection
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
@ -3,6 +3,7 @@
|
||||
require 'mongoid'
|
||||
|
||||
module Mongoid#:nodoc:
|
||||
|
||||
module Document #:nodoc:
|
||||
def as_json(options = {})
|
||||
attrs = super(options)
|
||||
@ -21,6 +22,12 @@ module Mongoid#:nodoc:
|
||||
class RawArray < ::Array; end
|
||||
end
|
||||
|
||||
class Criteria
|
||||
def to_liquid
|
||||
Locomotive::Liquid::Drops::ProxyCollection.new(self)
|
||||
end
|
||||
end
|
||||
|
||||
# without callback feature
|
||||
module Callbacks #:nodoc:
|
||||
module ClassMethods #:nodoc:
|
||||
@ -34,7 +41,6 @@ module Mongoid#:nodoc:
|
||||
|
||||
# make the validators work with localized field
|
||||
module Validations #:nodoc:
|
||||
|
||||
def read_attribute_for_validation_with_localization(attr)
|
||||
if fields[attr.to_s] && fields[attr.to_s].localized?
|
||||
send(attr.to_sym)
|
||||
@ -46,30 +52,10 @@ module Mongoid#:nodoc:
|
||||
alias_method_chain :read_attribute_for_validation, :localization
|
||||
|
||||
class PresenceValidator < ActiveModel::EachValidator
|
||||
|
||||
def validate_each(document, attribute, value)
|
||||
document.errors.add(attribute, :blank, options) if value.blank?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
#
|
||||
# class UniquenessValidator < ActiveModel::EachValidator
|
||||
#
|
||||
# protected
|
||||
#
|
||||
# def criterion_with_localization(document, attribute, value)
|
||||
# field = document.fields[attribute.to_s]
|
||||
# if field && field.localized? && !value.blank?
|
||||
# value = document.send(attribute.to_sym)
|
||||
# end
|
||||
#
|
||||
# criterion_without_localization(document, attribute, value)
|
||||
# end
|
||||
#
|
||||
# alias_method_chain :criterion, :localization
|
||||
#
|
||||
# end
|
||||
#
|
||||
# end
|
||||
end
|
||||
|
@ -17,6 +17,10 @@ module Locomotive
|
||||
|
||||
output = @page.render(locomotive_context)
|
||||
|
||||
# puts "======================"
|
||||
# puts output.inspect
|
||||
# puts "======================"
|
||||
|
||||
self.prepare_and_set_response(output)
|
||||
end
|
||||
end
|
||||
|
@ -4,6 +4,7 @@
|
||||
# instead of editing this one. Cucumber will automatically load all features/**/*.rb
|
||||
# files.
|
||||
|
||||
require 'rails'
|
||||
|
||||
unless ARGV.any? {|a| a =~ /^gems/} # Don't load anything when running the gems:* tasks
|
||||
|
||||
@ -14,19 +15,19 @@ begin
|
||||
require 'cucumber/rake/task'
|
||||
|
||||
namespace :cucumber do
|
||||
Cucumber::Rake::Task.new(:ok, 'Run features that should pass') do |t|
|
||||
Cucumber::Rake::Task.new({:ok => 'db:test:prepare'}, 'Run features that should pass') do |t|
|
||||
t.binary = vendored_cucumber_bin # If nil, the gem's binary is used.
|
||||
t.fork = true # You may get faster startup if you set this to false
|
||||
t.profile = 'default'
|
||||
end
|
||||
|
||||
Cucumber::Rake::Task.new(:wip, 'Run features that are being worked on') do |t|
|
||||
Cucumber::Rake::Task.new({:wip => 'db:test:prepare'}, 'Run features that are being worked on') do |t|
|
||||
t.binary = vendored_cucumber_bin
|
||||
t.fork = true # You may get faster startup if you set this to false
|
||||
t.profile = 'wip'
|
||||
end
|
||||
|
||||
Cucumber::Rake::Task.new(:rerun, 'Record failing features and run only them if any exist') do |t|
|
||||
Cucumber::Rake::Task.new({:rerun => 'db:test:prepare'}, 'Record failing features and run only them if any exist') do |t|
|
||||
t.binary = vendored_cucumber_bin
|
||||
t.fork = true # You may get faster startup if you set this to false
|
||||
t.profile = 'rerun'
|
||||
@ -50,6 +51,10 @@ begin
|
||||
STDERR.puts "*** The 'features' task is deprecated. See rake -T cucumber ***"
|
||||
end
|
||||
|
||||
# In case we don't have ActiveRecord, append a no-op task that we can depend upon.
|
||||
task 'db:test:prepare' do
|
||||
end
|
||||
|
||||
task :stats => 'cucumber:statsetup'
|
||||
rescue LoadError
|
||||
desc 'cucumber rake task not available (cucumber not installed)'
|
||||
|
Loading…
Reference in New Issue
Block a user