microscope 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in microscope.gemspec
4
+ gemspec
@@ -0,0 +1,26 @@
1
+ Copyright (c) 2013, Mirego
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+
7
+ - Redistributions of source code must retain the above copyright notice,
8
+ this list of conditions and the following disclaimer.
9
+ - Redistributions in binary form must reproduce the above copyright notice,
10
+ this list of conditions and the following disclaimer in the documentation
11
+ and/or other materials provided with the distribution.
12
+ - Neither the name of the Mirego nor the names of its contributors may
13
+ be used to endorse or promote products derived from this software without
14
+ specific prior written permission.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26
+ POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,55 @@
1
+ # Microscope
2
+
3
+ Microscope adds useful scopes targeting ActiveRecord boolean and datetime fields.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'microscope'
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ```ruby
16
+ create_table "events" do |t|
17
+ t.string "name"
18
+ t.boolean "special"
19
+ t.datetime "expired_at"
20
+ end
21
+
22
+ class Event < ActiveRecord::Base
23
+ acts_as_microscope
24
+ end
25
+
26
+ Event.special
27
+ # SELECT * FROM `events` where `events`.`special` = 1
28
+
29
+ Event.not_special
30
+ # SELECT * FROM `events` where `events`.`special` = 0
31
+
32
+ Time.now
33
+ # => 2013-07-05 15:43:42
34
+
35
+ Event.expired_before(2.months.ago)
36
+ # SELECT * FROM `events` where `events`.`expired_at` > '2013-05-05 15:43:42'
37
+
38
+ Event.expired_before_now
39
+ # SELECT * FROM `events` where `events`.`expired_at` > '2013-07-05 15:43:42'
40
+
41
+ Event.expired_after_or_at(2.months.from_now)
42
+ # SELECT * FROM `events` where `events`.`expired_at` >= '2013-09-05 15:43:42'
43
+
44
+ Event.expired_between(2.months.go..1.month.from_now)
45
+ # SELECT * FROM `events` where `events`.`expired_at` BETWEEN '2013-05-05 15:43:42' AND '2013-08-05 15:43:42'
46
+ ```
47
+
48
+ ## License
49
+
50
+ `Microscope` is © 2013 [Mirego](http://www.mirego.com) and may be freely distributed under the [New BSD license](http://opensource.org/licenses/BSD-3-Clause). See the [`LICENSE.md`](https://github.com/mirego/microscope/blob/master/LICENSE.md) file.
51
+
52
+ ## About Mirego
53
+
54
+ Mirego is a team of passionate people who believe that work is a place where you can innovate and have fun.
55
+ We proudly built mobile applications for [iPhone](http://mirego.com/en/iphone-app-development/ "iPhone application development"), [iPad](http://mirego.com/en/ipad-app-development/ "iPad application development"), [Android](http://mirego.com/en/android-app-development/ "Android application development"), [Blackberry](http://mirego.com/en/blackberry-app-development/ "Blackberry application development"), [Windows Phone](http://mirego.com/en/windows-phone-app-development/ "Windows Phone application development") and [Windows 8](http://mirego.com/en/windows-8-app-development/ "Windows 8 application development").
@@ -0,0 +1,11 @@
1
+ require 'bundler'
2
+ require 'rake'
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+
6
+ task default: :spec
7
+
8
+ desc 'Run all specs'
9
+ RSpec::Core::RakeTask.new(:spec) do |task|
10
+ task.pattern = 'spec/**/*_spec.rb'
11
+ end
@@ -0,0 +1,18 @@
1
+ require "microscope/version"
2
+
3
+ require 'active_record'
4
+ require 'active_support'
5
+
6
+ require "microscope/mixin"
7
+
8
+ module Microscope
9
+ def self.inject_into_active_record
10
+ @inject_into_active_record ||= Proc.new do
11
+ def self.acts_as_microscope
12
+ self.send :include, Microscope::Mixin
13
+ end
14
+ end
15
+ end
16
+ end
17
+
18
+ require 'microscope/railtie' if defined?(Rails) && Rails::VERSION::MAJOR >= 3
@@ -0,0 +1,40 @@
1
+ module Microscope
2
+ module Mixin
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ define_microscrope_scopes
7
+ end
8
+
9
+ module ClassMethods
10
+ def define_microscrope_scopes
11
+ model_columns = self.columns.dup
12
+
13
+ boolean_fields = model_columns.select { |c| c.type == :boolean }.map(&:name)
14
+ class_eval do
15
+ boolean_fields.each do |field|
16
+ scope field, where(field => true)
17
+ scope "not_#{field}", where(field => false)
18
+ end
19
+ end
20
+
21
+ datetime_fields = model_columns.select { |c| c.type == :datetime }.map(&:name)
22
+ class_eval do
23
+ datetime_fields.each do |field|
24
+ cropped_field = field.gsub(/_at$/, '')
25
+
26
+ scope "#{cropped_field}_before", lambda { |time| where(["#{field} < ?", time]) }
27
+ scope "#{cropped_field}_before_or_at", lambda { |time| where(["#{field} <= ?", time]) }
28
+ scope "#{cropped_field}_before_now", lambda { where(["#{field} < ?", Time.now]) }
29
+
30
+ scope "#{cropped_field}_after", lambda { |time| where(["#{field} > ?", time]) }
31
+ scope "#{cropped_field}_after_or_at", lambda { |time| where(["#{field} >= ?", time]) }
32
+ scope "#{cropped_field}_after_now", lambda { where(["#{field} > ?", Time.now]) }
33
+
34
+ scope "#{cropped_field}_between", lambda { |range| where(field => range) }
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,10 @@
1
+ require 'microscope'
2
+ require 'rails'
3
+
4
+ module Microscope
5
+ class Railtie < Rails::Railtie
6
+ initializer 'microscope.active_record' do |app|
7
+ ActiveSupport.on_load :active_record, {}, &Microscope.inject_into_active_record
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,3 @@
1
+ module Microscope
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'microscope/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'microscope'
8
+ spec.version = Microscope::VERSION
9
+ spec.authors = ["Simon Prévost", "Rémi Prévost"]
10
+ spec.email = ["sprevost@mirego.com", "rprevost@mirego.com"]
11
+ spec.description = 'Microscope adds useful scopes targeting ActiveRecord boolean and datetime fields.'
12
+ spec.summary = 'Microscope adds useful scopes targeting ActiveRecord boolean and datetime fields.'
13
+ spec.homepage = 'https://github.com/mirego/microscope'
14
+ spec.license = 'BSD 3-Clause'
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency 'activesupport', '>= 3.0.0'
22
+ spec.add_dependency 'activerecord', '>= 3.0.0'
23
+
24
+ spec.add_development_dependency 'bundler', '~> 1.3'
25
+ spec.add_development_dependency 'rake'
26
+ spec.add_development_dependency 'rspec'
27
+ spec.add_development_dependency 'sqlite3'
28
+ end
@@ -0,0 +1,93 @@
1
+ require 'spec_helper'
2
+
3
+ describe Microscope::Mixin do
4
+ describe 'Boolean scopes' do
5
+ subject { User }
6
+
7
+ before do
8
+ run_migration do
9
+ create_table(:users, force: true) do |t|
10
+ t.boolean :active, default: false
11
+ end
12
+ end
13
+
14
+ microscope 'User'
15
+ end
16
+
17
+ describe 'positive scope' do
18
+ before { @user1 = User.create(active: true) }
19
+
20
+ its(:active) { should have(1).items }
21
+ its(:active) { should include(@user1) }
22
+ its(:not_active) { should be_empty }
23
+ end
24
+
25
+ describe 'negative scope' do
26
+ before { @user1 = User.create(active: false) }
27
+
28
+ its(:not_active) { should have(1).items }
29
+ its(:not_active) { should include(@user1) }
30
+ its(:active) { should be_empty }
31
+ end
32
+ end
33
+
34
+ describe 'DateTime scopes' do
35
+ subject { Event }
36
+
37
+ before do
38
+ run_migration do
39
+ create_table(:events, force: true) do |t|
40
+ t.datetime :started_at, default: false
41
+ end
42
+ end
43
+
44
+ microscope 'Event'
45
+ end
46
+
47
+ describe 'before scope' do
48
+ before do
49
+ @event = Event.create(started_at: 2.months.ago)
50
+ Event.create(started_at: 1.month.from_now)
51
+ end
52
+
53
+ it { expect(Event.started_before(1.month.ago).to_a).to eql [@event] }
54
+ end
55
+
56
+ describe 'before_now scope' do
57
+ before do
58
+ @event = Event.create(started_at: 2.months.ago)
59
+ Event.create(started_at: 1.month.from_now)
60
+ end
61
+
62
+ it { expect(Event.started_before_now.to_a).to eql [@event] }
63
+ end
64
+
65
+ describe 'after scope' do
66
+ before do
67
+ @event = Event.create(started_at: 2.months.from_now)
68
+ Event.create(started_at: 1.month.ago)
69
+ end
70
+
71
+ it { expect(Event.started_after(1.month.from_now).to_a).to eql [@event] }
72
+ end
73
+
74
+ describe 'after_now scope' do
75
+ before do
76
+ @event = Event.create(started_at: 2.months.from_now)
77
+ Event.create(started_at: 1.month.ago)
78
+ end
79
+
80
+ it { expect(Event.started_after_now.to_a).to eql [@event] }
81
+ end
82
+
83
+ describe 'between scope' do
84
+ before do
85
+ Event.create(started_at: 1.month.ago)
86
+ @event = Event.create(started_at: 3.months.ago)
87
+ Event.create(started_at: 5.month.ago)
88
+ end
89
+
90
+ it { expect(Event.started_between(4.months.ago..2.months.ago).to_a).to eql [@event] }
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,28 @@
1
+ $:.unshift File.expand_path('../lib', __FILE__)
2
+
3
+ require 'rspec'
4
+ require 'sqlite3'
5
+
6
+ require 'microscope'
7
+
8
+ # Require our macros and extensions
9
+ Dir[File.expand_path('../../spec/support/macros/*.rb', __FILE__)].map(&method(:require))
10
+
11
+ # Inject our methods into ActiveRecord (like our railtie does)
12
+ ActiveRecord::Base.class_eval(&Microscope.inject_into_active_record)
13
+
14
+ RSpec.configure do |config|
15
+ # Include our macros
16
+ config.include DatabaseMacros
17
+ config.include ModelMacros
18
+
19
+ config.before(:each) do
20
+ # Create the SQLite database
21
+ setup_database
22
+ end
23
+
24
+ config.after(:each) do
25
+ # Make sure we remove our test database file
26
+ cleanup_database
27
+ end
28
+ end
@@ -0,0 +1,33 @@
1
+ module DatabaseMacros
2
+ # Run migrations in the test database
3
+ def run_migration(&block)
4
+ # Create a new migration class
5
+ klass = Class.new(ActiveRecord::Migration)
6
+
7
+ # Create a new `up` that executes the argument
8
+ klass.send(:define_method, :up) { self.instance_exec(&block) }
9
+
10
+ # Create a new instance of it and execute its `up` method
11
+ klass.new.up
12
+ end
13
+
14
+ def self.database_file
15
+ @database_file || File.expand_path('../test.db', __FILE__)
16
+ end
17
+
18
+ def setup_database
19
+ # Make sure the test database file is gone
20
+ cleanup_database
21
+
22
+ # Establish the connection
23
+ SQLite3::Database.new FileUtils.touch(DatabaseMacros.database_file).first
24
+ ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: DatabaseMacros.database_file)
25
+
26
+ # Silence everything
27
+ ActiveRecord::Base.logger = ActiveRecord::Migration.verbose = false
28
+ end
29
+
30
+ def cleanup_database
31
+ FileUtils.rm(DatabaseMacros.database_file) if File.exists?(DatabaseMacros.database_file)
32
+ end
33
+ end
@@ -0,0 +1,18 @@
1
+ module ModelMacros
2
+ # Create a new microscope model
3
+ def microscope(klass_name, &block)
4
+ spawn_model klass_name, ActiveRecord::Base do
5
+ acts_as_microscope
6
+ instance_exec(&block) if block
7
+ end
8
+ end
9
+
10
+ protected
11
+
12
+ # Create a new model class
13
+ def spawn_model(klass_name, parent_klass, &block)
14
+ Object.instance_eval { remove_const klass_name } if Object.const_defined?(klass_name)
15
+ Object.const_set(klass_name, Class.new(parent_klass))
16
+ Object.const_get(klass_name).class_eval(&block) if block_given?
17
+ end
18
+ end
metadata ADDED
@@ -0,0 +1,171 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: microscope
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Simon Prévost
9
+ - Rémi Prévost
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2013-07-05 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: activesupport
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: 3.0.0
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ! '>='
29
+ - !ruby/object:Gem::Version
30
+ version: 3.0.0
31
+ - !ruby/object:Gem::Dependency
32
+ name: activerecord
33
+ requirement: !ruby/object:Gem::Requirement
34
+ none: false
35
+ requirements:
36
+ - - ! '>='
37
+ - !ruby/object:Gem::Version
38
+ version: 3.0.0
39
+ type: :runtime
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: 3.0.0
47
+ - !ruby/object:Gem::Dependency
48
+ name: bundler
49
+ requirement: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '1.3'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ~>
61
+ - !ruby/object:Gem::Version
62
+ version: '1.3'
63
+ - !ruby/object:Gem::Dependency
64
+ name: rake
65
+ requirement: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ! '>='
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ type: :development
72
+ prerelease: false
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ! '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ - !ruby/object:Gem::Dependency
80
+ name: rspec
81
+ requirement: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ! '>='
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ type: :development
88
+ prerelease: false
89
+ version_requirements: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ! '>='
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ - !ruby/object:Gem::Dependency
96
+ name: sqlite3
97
+ requirement: !ruby/object:Gem::Requirement
98
+ none: false
99
+ requirements:
100
+ - - ! '>='
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ type: :development
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ! '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: Microscope adds useful scopes targeting ActiveRecord boolean and datetime
112
+ fields.
113
+ email:
114
+ - sprevost@mirego.com
115
+ - rprevost@mirego.com
116
+ executables: []
117
+ extensions: []
118
+ extra_rdoc_files: []
119
+ files:
120
+ - .gitignore
121
+ - .rspec
122
+ - Gemfile
123
+ - LICENSE.md
124
+ - README.md
125
+ - Rakefile
126
+ - lib/microscope.rb
127
+ - lib/microscope/mixin.rb
128
+ - lib/microscope/railtie.rb
129
+ - lib/microscope/version.rb
130
+ - microscope.gemspec
131
+ - spec/microscope/mixin_spec.rb
132
+ - spec/spec_helper.rb
133
+ - spec/support/macros/database_macros.rb
134
+ - spec/support/macros/model_macros.rb
135
+ homepage: https://github.com/mirego/microscope
136
+ licenses:
137
+ - BSD 3-Clause
138
+ post_install_message:
139
+ rdoc_options: []
140
+ require_paths:
141
+ - lib
142
+ required_ruby_version: !ruby/object:Gem::Requirement
143
+ none: false
144
+ requirements:
145
+ - - ! '>='
146
+ - !ruby/object:Gem::Version
147
+ version: '0'
148
+ segments:
149
+ - 0
150
+ hash: 533199632649490219
151
+ required_rubygems_version: !ruby/object:Gem::Requirement
152
+ none: false
153
+ requirements:
154
+ - - ! '>='
155
+ - !ruby/object:Gem::Version
156
+ version: '0'
157
+ segments:
158
+ - 0
159
+ hash: 533199632649490219
160
+ requirements: []
161
+ rubyforge_project:
162
+ rubygems_version: 1.8.23
163
+ signing_key:
164
+ specification_version: 3
165
+ summary: Microscope adds useful scopes targeting ActiveRecord boolean and datetime
166
+ fields.
167
+ test_files:
168
+ - spec/microscope/mixin_spec.rb
169
+ - spec/spec_helper.rb
170
+ - spec/support/macros/database_macros.rb
171
+ - spec/support/macros/model_macros.rb