From d0cb1837a1bb8cf68e2ac0247d0de26f5cede02d Mon Sep 17 00:00:00 2001 From: Akira Matsuda Date: Sun, 20 May 2012 23:30:19 +0900 Subject: [PATCH] refactor AR, DM, mongoid, and mongo_mapper specs extract model definitions for each ORM under spec/fake_app, and load them only if target ORM is loaded by this mechanism, all ORMs share a model name "User", and the other specs such as helper specs and request specs will run polymorphically --- spec/fake_app/active_record/config.rb | 3 + .../active_record/models.rb} | 45 +---------- spec/fake_app/data_mapper/config.rb | 1 + spec/fake_app/data_mapper/models.rb | 27 +++++++ spec/fake_app/fake_app.rb | 53 +++++++++++++ spec/fake_app/mongo_mapper/config.rb | 2 + spec/fake_app/mongo_mapper/models.rb | 9 +++ spec/fake_app/mongoid/config.rb | 16 ++++ spec/fake_app/mongoid/models.rb | 22 ++++++ spec/fake_gem.rb | 2 - spec/models/data_mapper/data_mapper_spec.rb | 74 ++++++------------- spec/models/mongo_mapper/mongo_mapper_spec.rb | 37 +++------- spec/models/mongoid/mongoid_spec.rb | 54 ++------------ spec/spec_helper.rb | 24 ++---- 14 files changed, 181 insertions(+), 188 deletions(-) create mode 100644 spec/fake_app/active_record/config.rb rename spec/{fake_app.rb => fake_app/active_record/models.rb} (62%) create mode 100644 spec/fake_app/data_mapper/config.rb create mode 100644 spec/fake_app/data_mapper/models.rb create mode 100644 spec/fake_app/fake_app.rb create mode 100644 spec/fake_app/mongo_mapper/config.rb create mode 100644 spec/fake_app/mongo_mapper/models.rb create mode 100644 spec/fake_app/mongoid/config.rb create mode 100644 spec/fake_app/mongoid/models.rb diff --git a/spec/fake_app/active_record/config.rb b/spec/fake_app/active_record/config.rb new file mode 100644 index 0000000..5758395 --- /dev/null +++ b/spec/fake_app/active_record/config.rb @@ -0,0 +1,3 @@ +# database +ActiveRecord::Base.configurations = {'test' => {:adapter => 'sqlite3', :database => ':memory:'}} +ActiveRecord::Base.establish_connection('test') diff --git a/spec/fake_app.rb b/spec/fake_app/active_record/models.rb similarity index 62% rename from spec/fake_app.rb rename to spec/fake_app/active_record/models.rb index a3757c0..f8686b8 100644 --- a/spec/fake_app.rb +++ b/spec/fake_app/active_record/models.rb @@ -1,23 +1,3 @@ -require 'active_record' -require 'action_controller/railtie' -require 'action_view/railtie' - -# database -ActiveRecord::Base.configurations = {'test' => {:adapter => 'sqlite3', :database => ':memory:'}} -ActiveRecord::Base.establish_connection('test') - -# config -app = Class.new(Rails::Application) -app.config.secret_token = "3b7cd727ee24e8444053437c36cc66c4" -app.config.session_store :cookie_store, :key => "_myapp_session" -app.config.active_support.deprecation = :log -app.initialize! - -# routes -app.routes.draw do - resources :users -end - # models class User < ActiveRecord::Base has_many :authorships @@ -62,30 +42,6 @@ class User::Address < ActiveRecord::Base belongs_to :user end -# controllers -class ApplicationController < ActionController::Base; end -class UsersController < ApplicationController - def index - @users = User.page params[:page] - render :inline => <<-ERB -<%= @users.map(&:name).join("\n") %> -<%= paginate @users %> -ERB - end -end -class AddressesController < ApplicationController - def index - @addresses = User::Address.page params[:page] - render :inline => <<-ERB -<%= @addresses.map(&:street).join("\n") %> -<%= paginate @addresses %> -ERB - end -end - -# helpers -Object.const_set(:ApplicationHelper, Module.new) - #migrations class CreateAllTables < ActiveRecord::Migration def self.up @@ -97,3 +53,4 @@ class CreateAllTables < ActiveRecord::Migration create_table(:user_addresses) {|t| t.string :street; t.integer :user_id } end end +CreateAllTables.up diff --git a/spec/fake_app/data_mapper/config.rb b/spec/fake_app/data_mapper/config.rb new file mode 100644 index 0000000..f81a281 --- /dev/null +++ b/spec/fake_app/data_mapper/config.rb @@ -0,0 +1 @@ +DataMapper.setup(:default, 'sqlite::memory:') diff --git a/spec/fake_app/data_mapper/models.rb b/spec/fake_app/data_mapper/models.rb new file mode 100644 index 0000000..a4d8fdd --- /dev/null +++ b/spec/fake_app/data_mapper/models.rb @@ -0,0 +1,27 @@ +class User + include ::DataMapper::Resource + + property :id, Serial + property :name, String, :required => true + property :age, Integer + + has n, :projects, :through => Resource +end + +class User::Address + include ::DataMapper::Resource + + property :id, Serial +end + +class Project + include ::DataMapper::Resource + + property :id, Serial + property :name, String, :required => true + + has n, :users, :through => Resource +end + +DataMapper.finalize +DataMapper.auto_migrate! diff --git a/spec/fake_app/fake_app.rb b/spec/fake_app/fake_app.rb new file mode 100644 index 0000000..261beca --- /dev/null +++ b/spec/fake_app/fake_app.rb @@ -0,0 +1,53 @@ +# require 'rails/all' +require 'action_controller/railtie' +require 'action_view/railtie' + +require 'fake_app/active_record/config' if defined? ActiveRecord +require 'fake_app/data_mapper/config' if defined? DataMapper +require 'fake_app/mongoid/config' if defined? Mongoid +require 'fake_app/mongo_mapper/config' if defined? MongoMapper +# config +app = Class.new(Rails::Application) +app.config.secret_token = '3b7cd727ee24e8444053437c36cc66c4' +app.config.session_store :cookie_store, :key => '_myapp_session' +app.config.active_support.deprecation = :log +Rails.backtrace_cleaner.remove_silencers! +app.initialize! + +# routes +app.routes.draw do + resources :users +end + +#models +require 'fake_app/active_record/models' if defined? ActiveRecord +require 'fake_app/data_mapper/models' if defined? DataMapper +require 'fake_app/mongoid/models' if defined? Mongoid +require 'fake_app/mongo_mapper/models' if defined? MongoMapper + +# controllers +class ApplicationController < ActionController::Base; end +class UsersController < ApplicationController + def index + @users = User.page params[:page] + render :inline => <<-ERB +<%= @users.map(&:name).join("\n") %> +<%= paginate @users %> +ERB + end +end + +if defined? ActiveRecord + class AddressesController < ApplicationController + def index + @addresses = User::Address.page params[:page] + render :inline => <<-ERB + <%= @addresses.map(&:street).join("\n") %> + <%= paginate @addresses %> + ERB + end + end +end + +# helpers +Object.const_set(:ApplicationHelper, Module.new) diff --git a/spec/fake_app/mongo_mapper/config.rb b/spec/fake_app/mongo_mapper/config.rb new file mode 100644 index 0000000..ef00915 --- /dev/null +++ b/spec/fake_app/mongo_mapper/config.rb @@ -0,0 +1,2 @@ +MongoMapper.connection = Mongo::Connection.new 'localhost', 27017 +MongoMapper.database = 'kaminari_test' diff --git a/spec/fake_app/mongo_mapper/models.rb b/spec/fake_app/mongo_mapper/models.rb new file mode 100644 index 0000000..95e5062 --- /dev/null +++ b/spec/fake_app/mongo_mapper/models.rb @@ -0,0 +1,9 @@ +class User + include ::MongoMapper::Document + key :name, String + key :age, Integer +end + +class User::Address + include ::MongoMapper::Document +end diff --git a/spec/fake_app/mongoid/config.rb b/spec/fake_app/mongoid/config.rb new file mode 100644 index 0000000..2c53097 --- /dev/null +++ b/spec/fake_app/mongoid/config.rb @@ -0,0 +1,16 @@ +# Ensure we use 'syck' instead of 'psych' in 1.9.2 +# RubyGems >= 1.5.0 uses 'psych' on 1.9.2, but +# Psych does not yet support YAML 1.1 merge keys. +# Merge keys is often used in mongoid.yml +# See: http://redmine.ruby-lang.org/issues/show/4300 +if RUBY_VERSION >= '1.9.2' + YAML::ENGINE.yamler = 'syck' +end + +Mongoid.configure do |config| + if Mongoid::VERSION =~ /^3/ + config.sessions = {default: {hosts: ['localhost:27017'], database: 'kaminari_test'}} + else + config.master = Mongo::Connection.new.db('kaminari_test') + end +end diff --git a/spec/fake_app/mongoid/models.rb b/spec/fake_app/mongoid/models.rb new file mode 100644 index 0000000..7d65da7 --- /dev/null +++ b/spec/fake_app/mongoid/models.rb @@ -0,0 +1,22 @@ +class User + include ::Mongoid::Document + field :name, :type => String + field :age, :type => Integer +end + +class User::Address + include ::Mongoid::Document +end + +class MongoMongoidExtensionDeveloper + include ::Mongoid::Document + field :salary, :type => Integer + embeds_many :frameworks +end + +class Framework + include ::Mongoid::Document + field :name, :type => String + field :language, :type => String + embedded_in :mongo_mongoid_extension_developer +end diff --git a/spec/fake_gem.rb b/spec/fake_gem.rb index a142811..fa3a1c2 100644 --- a/spec/fake_gem.rb +++ b/spec/fake_gem.rb @@ -1,6 +1,4 @@ # Simulate a gem providing a subclass of ActiveRecord::Base before the Railtie is loaded. -require 'active_record' - class GemDefinedModel < ActiveRecord::Base end diff --git a/spec/models/data_mapper/data_mapper_spec.rb b/spec/models/data_mapper/data_mapper_spec.rb index 93d1aea..db70414 100644 --- a/spec/models/data_mapper/data_mapper_spec.rb +++ b/spec/models/data_mapper/data_mapper_spec.rb @@ -1,41 +1,13 @@ require 'spec_helper' if defined? DataMapper - require 'kaminari/models/data_mapper_extension' - describe Kaminari::DataMapperExtension do - before :all do - DataMapper.setup(:default, 'sqlite::memory:') - - class Worker - include ::DataMapper::Resource - - property :id, Serial - property :name, String, :required => true - property :age, Integer, :required => true - - has n, :projects, :through => Resource - end - - class Project - include ::DataMapper::Resource - - property :id, Serial - property :name, String, :required => true - - has n, :workers, :through => Resource - end - - DataMapper.finalize - DataMapper.auto_migrate! - end - before do 300.times do |i| - Worker.create(:name => "Worker#{i}", :age => i) + User.create(:name => "User#{i}", :age => i) end - worker0 = Worker[0] + worker0 = User[0] 50.times do |i| worker0.projects << Project.create(:name => "Project#{i}") end @@ -43,13 +15,13 @@ if defined? DataMapper end describe 'Collection' do - subject{ Worker.all } + subject{ User.all } it { should respond_to(:page) } it { should_not respond_to(:per) } end describe 'Model' do - subject{ Worker } + subject{ User } it { should respond_to(:page) } it { should respond_to(:default_per_page) } it { should_not respond_to(:per) } @@ -57,17 +29,17 @@ if defined? DataMapper describe '#page' do context 'page 0' do - subject { Worker.all(:age.gte => 200).page 0 } + subject { User.all(:age.gte => 200).page 0 } it { should be_a DataMapper::Collection } its(:current_page) { should == 1 } its('query.limit') { should == 25 } its('query.offset') { should == 0 } - its(:total_count) { should == Worker.count(:age.gte => 200) } + its(:total_count) { should == User.count(:age.gte => 200) } its(:num_pages) { should == 4 } end context 'page 1' do - subject { Worker.all(:age.gte => 0).page 1 } + subject { User.all(:age.gte => 0).page 1 } it { should be_a DataMapper::Collection } its(:current_page) { should == 1 } its('query.limit') { should == 25 } @@ -77,7 +49,7 @@ if defined? DataMapper end context 'page 2' do - subject { Worker.page 2 } + subject { User.page 2 } it { should be_a DataMapper::Collection } its(:current_page) { should == 2 } its(:limit_value) { should == 25 } @@ -88,7 +60,7 @@ if defined? DataMapper end context 'page "foobar"' do - subject { Worker.page 'foobar' } + subject { User.page 'foobar' } it { should be_a DataMapper::Collection } its(:current_page) { should == 1 } its('query.limit') { should == 25 } @@ -98,29 +70,29 @@ if defined? DataMapper end context 'with criteria before' do - subject { Worker.all(:age.gt => 100).page 2 } + subject { User.all(:age.gt => 100).page 2 } it { should be_a DataMapper::Collection } its(:current_page) { should == 2 } its('query.limit') { should == 25 } its('query.offset') { should == 25 } - its(:total_count) { should == Worker.count(:age.gt => 100) } + its(:total_count) { should == User.count(:age.gt => 100) } its(:num_pages) { should == 8 } end context 'with criteria after' do - subject { Worker.page(2).all(:age.gt => 100) } + subject { User.page(2).all(:age.gt => 100) } it { should be_a DataMapper::Collection } its(:current_page) { should == 2 } its('query.limit') { should == 25 } its('query.offset') { should == 25 } - its(:total_count) { should == Worker.count(:age.gt => 100) } + its(:total_count) { should == User.count(:age.gt => 100) } its(:num_pages) { should == 8 } end end describe '#per' do context 'on simple query' do - subject { Worker.page(2).per(10) } + subject { User.page(2).per(10) } it { should be_a DataMapper::Collection } its(:current_page) { should == 2 } its('query.limit') { should == 10 } @@ -131,7 +103,7 @@ if defined? DataMapper end context 'on query with condition' do - subject { Worker.page(5).all(:age.lte => 100).per(13) } + subject { User.page(5).all(:age.lte => 100).per(13) } its(:current_page) { should == 5 } its('query.limit') { should == 13 } its('query.offset') { should == 52 } @@ -140,11 +112,11 @@ if defined? DataMapper end context 'on query with order' do - subject { Worker.page(5).all(:age.lte => 100, :order => [:age.asc]).per(13) } - it('includes worker with age 52') { should include(Worker.first(:age => 52)) } - it('does not include worker with age 51') { should_not include(Worker.first(:age => 51)) } - it('includes worker with age 52') { should include(Worker.first(:age => 64)) } - it('does not include worker with age 51') { should_not include(Worker.first(:age => 65)) } + subject { User.page(5).all(:age.lte => 100, :order => [:age.asc]).per(13) } + it('includes worker with age 52') { should include(User.first(:age => 52)) } + it('does not include worker with age 51') { should_not include(User.first(:age => 51)) } + it('includes worker with age 52') { should include(User.first(:age => 64)) } + it('does not include worker with age 51') { should_not include(User.first(:age => 65)) } its(:current_page) { should == 5 } its('query.limit') { should == 13 } its('query.offset') { should == 52 } @@ -153,7 +125,7 @@ if defined? DataMapper end context 'on chained queries' do - subject { Worker.all(:age.gte => 50).page(3).all(:age.lte => 100).per(13) } + subject { User.all(:age.gte => 50).page(3).all(:age.lte => 100).per(13) } its(:current_page) { should == 3 } its('query.limit') { should == 13 } its('query.offset') { should == 26 } @@ -162,7 +134,7 @@ if defined? DataMapper end context 'on query on association' do - subject { Worker[0].projects.page(3).all(:name.like => 'Project%').per(5) } + subject { User[0].projects.page(3).all(:name.like => 'Project%').per(5) } its(:current_page) { should == 3 } its('query.limit') { should == 5 } its('query.offset') { should == 10 } @@ -171,7 +143,7 @@ if defined? DataMapper end context 'on query with association conditions' do - subject { Worker.page(3).all(:projects => Project.all).per(5) } + subject { User.page(3).all(:projects => Project.all).per(5) } its(:current_page) { should == 3 } its('query.limit') { should == 5 } its('query.offset') { should == 10 } diff --git a/spec/models/mongo_mapper/mongo_mapper_spec.rb b/spec/models/mongo_mapper/mongo_mapper_spec.rb index bac679e..cd1f814 100644 --- a/spec/models/mongo_mapper/mongo_mapper_spec.rb +++ b/spec/models/mongo_mapper/mongo_mapper_spec.rb @@ -1,32 +1,15 @@ require 'spec_helper' if defined? MongoMapper - require 'mongo_mapper' - require 'kaminari/models/mongo_mapper_extension' - describe Kaminari::MongoMapperExtension do - - before do - begin - MongoMapper.connection = Mongo::Connection.new('localhost', 27017) - MongoMapper.database = "kaminari_test" - class MongoMapperExtensionDeveloper - include ::MongoMapper::Document - key :salary, Integer - end - rescue Mongo::ConnectionFailure - pending 'can not connect to MongoDB' - end - end - before(:each) do - MongoMapperExtensionDeveloper.destroy_all - 41.times { MongoMapperExtensionDeveloper.create!({:salary => 1}) } + User.destroy_all + 41.times { User.create!({:salary => 1}) } end describe '#page' do context 'page 1' do - subject { MongoMapperExtensionDeveloper.page(1) } + subject { User.page(1) } it { should be_a Plucky::Query } its(:current_page) { should == 1 } its(:limit_value) { should == 25 } @@ -35,7 +18,7 @@ if defined? MongoMapper end context 'page 2' do - subject { MongoMapperExtensionDeveloper.page 2 } + subject { User.page 2 } it { should be_a Plucky::Query } its(:current_page) { should == 2 } its(:limit_value) { should == 25 } @@ -44,7 +27,7 @@ if defined? MongoMapper end context 'page "foobar"' do - subject { MongoMapperExtensionDeveloper.page 'foobar' } + subject { User.page 'foobar' } it { should be_a Plucky::Query } its(:current_page) { should == 1 } its(:limit_value) { should == 25 } @@ -54,10 +37,10 @@ if defined? MongoMapper context 'with criteria before' do it "should have the proper criteria source" do - MongoMapperExtensionDeveloper.where(:salary => 1).page(2).criteria.source.should == {:salary => 1} + User.where(:salary => 1).page(2).criteria.source.should == {:salary => 1} end - subject { MongoMapperExtensionDeveloper.where(:salary => 1).page 2 } + subject { User.where(:salary => 1).page 2 } its(:current_page) { should == 2 } its(:limit_value) { should == 25 } its(:num_pages) { should == 2 } @@ -66,10 +49,10 @@ if defined? MongoMapper context 'with criteria after' do it "should have the proper criteria source" do - MongoMapperExtensionDeveloper.where(:salary => 1).page(2).criteria.source.should == {:salary => 1} + User.where(:salary => 1).page(2).criteria.source.should == {:salary => 1} end - subject { MongoMapperExtensionDeveloper.page(2).where(:salary => 1) } + subject { User.page(2).where(:salary => 1) } its(:current_page) { should == 2 } its(:limit_value) { should == 25 } its(:num_pages) { should == 2 } @@ -78,7 +61,7 @@ if defined? MongoMapper end describe '#per' do - subject { MongoMapperExtensionDeveloper.page(2).per(10) } + subject { User.page(2).per(10) } it { should be_a Plucky::Query } its(:current_page) { should == 2 } its(:limit_value) { should == 10 } diff --git a/spec/models/mongoid/mongoid_spec.rb b/spec/models/mongoid/mongoid_spec.rb index a78bcfe..c27bb00 100644 --- a/spec/models/mongoid/mongoid_spec.rb +++ b/spec/models/mongoid/mongoid_spec.rb @@ -1,40 +1,17 @@ require 'spec_helper' if defined? Mongoid - require 'mongoid' - require 'kaminari/models/mongoid_extension' - describe Kaminari::MongoidExtension do - - before do - begin - Mongoid.configure do |config| - if Mongoid::VERSION =~ /^3/ - config.sessions = { default: { hosts: [ "localhost:27017" ], database: 'kaminari_test' }} - else - config.master = Mongo::Connection.new.db("kaminari_test") - end - end - class MongoidExtensionDeveloper - include ::Mongoid::Document - field :salary, :type => Integer - end - rescue Mongo::ConnectionFailure - pending 'can not connect to MongoDB' - end - end - before(:each) do - MongoidExtensionDeveloper.all.destroy 41.times do - MongoidExtensionDeveloper.create!({:salary => 1}) + User.create!({:salary => 1}) end end describe '#page' do context 'page 1' do - subject { MongoidExtensionDeveloper.page 1 } + subject { User.page 1 } it { should be_a Mongoid::Criteria } its(:current_page) { should == 1 } its(:limit_value) { should == 25 } @@ -43,7 +20,7 @@ if defined? Mongoid end context 'page 2' do - subject { MongoidExtensionDeveloper.page 2 } + subject { User.page 2 } it { should be_a Mongoid::Criteria } its(:current_page) { should == 2 } its(:limit_value) { should == 25 } @@ -52,7 +29,7 @@ if defined? Mongoid end context 'page "foobar"' do - subject { MongoidExtensionDeveloper.page 'foobar' } + subject { User.page 'foobar' } it { should be_a Mongoid::Criteria } its(:current_page) { should == 1 } its(:limit_value) { should == 25 } @@ -73,18 +50,18 @@ if defined? Mongoid end context 'with criteria before' do - subject { MongoidExtensionDeveloper.where(:salary => 1).page 2 } + subject { User.where(:salary => 1).page 2 } it_should_behave_like 'complete valid pagination' end context 'with criteria after' do - subject { MongoidExtensionDeveloper.page(2).where(:salary => 1) } + subject { User.page(2).where(:salary => 1) } it_should_behave_like 'complete valid pagination' end end describe '#per' do - subject { MongoidExtensionDeveloper.page(2).per(10) } + subject { User.page(2).per(10) } it { should be_a Mongoid::Criteria } its(:current_page) { should == 2 } its(:limit_value) { should == 10 } @@ -93,22 +70,7 @@ if defined? Mongoid end describe '#page in embedded documents' do - before :all do - class MongoMongoidExtensionDeveloper - include ::Mongoid::Document - field :salary, :type => Integer - embeds_many :frameworks - end - - class Framework - include ::Mongoid::Document - field :name, :type => String - field :language, :type => String - embedded_in :mongo_mongoid_extension_developer - end - end - - before :all do + before do @mongo_developer = MongoMongoidExtensionDeveloper.new @mongo_developer.frameworks.new(:name => "rails", :language => "ruby") @mongo_developer.frameworks.new(:name => "merb", :language => "ruby") diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 861c5b4..3df1b79 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,24 +1,16 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) $LOAD_PATH.unshift(File.dirname(__FILE__)) +require 'rails' require 'bundler/setup' Bundler.require -require 'rails' -require 'mongoid' -require 'dm-core' -require 'kaminari' require 'database_cleaner' -# Ensure we use 'syck' instead of 'psych' in 1.9.2 -# RubyGems >= 1.5.0 uses 'psych' on 1.9.2, but -# Psych does not yet support YAML 1.1 merge keys. -# Merge keys is often used in mongoid.yml -# See: http://redmine.ruby-lang.org/issues/show/4300 -if RUBY_VERSION >= '1.9.2' - YAML::ENGINE.yamler = 'syck' -end -require 'fake_gem' -require 'fake_app' + +# Simulate a gem providing a subclass of ActiveRecord::Base before the Railtie is loaded. +require 'fake_gem' if defined? ActiveRecord + +require 'fake_app/fake_app' require 'rspec/rails' # Requires supporting files with custom matchers and macros, etc, @@ -27,8 +19,4 @@ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f} RSpec.configure do |config| config.mock_with :rr - config.before :all do -# ActiveRecord::Base.connection.execute 'CREATE TABLE "users" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar(255))' unless ActiveRecord::Base.connection.table_exists? 'users' - CreateAllTables.up unless ActiveRecord::Base.connection.table_exists? 'users' - end end