active_record_or 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.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/README.md +32 -0
- data/Rakefile +1 -0
- data/active_record_or.gemspec +24 -0
- data/lib/active_record_or/version.rb +3 -0
- data/lib/active_record_or.rb +23 -0
- data/test/active_record_or_test.rb +52 -0
- data/test/test_helper.rb +12 -0
- metadata +56 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
ActiveRecord OR
|
|
2
|
+
===============
|
|
3
|
+
|
|
4
|
+
Let's say you were trying to implement a SOPA enforcement tool:
|
|
5
|
+
|
|
6
|
+
class Blog < ActiveRecord::Base
|
|
7
|
+
has_one :author
|
|
8
|
+
...
|
|
9
|
+
scope :infringing, where("artist_mentions_count > 0")
|
|
10
|
+
scope :main_competition, where("competition_rank > 7")
|
|
11
|
+
scope :generally_disliked, where("subjective_dislike_rating > 3")
|
|
12
|
+
...
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
This would let you write handy things like
|
|
16
|
+
|
|
17
|
+
to_blacklist = Blog.infringing.or.main_competition.or.generally_disliked
|
|
18
|
+
to_harass = Blog.joins(:author).where('authors.name' => 'Julian')\
|
|
19
|
+
.or.generally_disliked
|
|
20
|
+
|
|
21
|
+
The end.
|
|
22
|
+
|
|
23
|
+
Credits
|
|
24
|
+
=======
|
|
25
|
+
|
|
26
|
+
Gem extracted from (i.e. mostly sponsored by) http://www.hfa3.org/
|
|
27
|
+
|
|
28
|
+
TODO
|
|
29
|
+
====
|
|
30
|
+
|
|
31
|
+
Dispite the name of the gem, I'll probably add `not` logic also. Seems
|
|
32
|
+
like `or` and `not` are really all that's missing from AR scopes.
|
data/Rakefile
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require "bundler/gem_tasks"
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
|
3
|
+
require "active_record_or/version"
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |s|
|
|
6
|
+
s.name = "active_record_or"
|
|
7
|
+
s.version = ActiveRecordOr::VERSION
|
|
8
|
+
s.authors = ["Woody Peterson"]
|
|
9
|
+
s.email = ["woody.peterson@gmail.com"]
|
|
10
|
+
s.homepage = ""
|
|
11
|
+
s.summary = %q{Chain scopes with 'or'}
|
|
12
|
+
s.description = %q{Adds OR logic to ActiveRecord}
|
|
13
|
+
|
|
14
|
+
s.rubyforge_project = "active_record_or"
|
|
15
|
+
|
|
16
|
+
s.files = `git ls-files`.split("\n")
|
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
|
19
|
+
s.require_paths = ["lib"]
|
|
20
|
+
|
|
21
|
+
# specify any dependencies here; for example:
|
|
22
|
+
# s.add_development_dependency "rspec"
|
|
23
|
+
# s.add_runtime_dependency "rest-client"
|
|
24
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require "active_record_or/version"
|
|
2
|
+
|
|
3
|
+
module ActiveRecordOr
|
|
4
|
+
class Or
|
|
5
|
+
def initialize(left)
|
|
6
|
+
@left = left
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def method_missing(method, *args, &block)
|
|
10
|
+
raw_right = @left.unscoped.send(method, *args, &block)
|
|
11
|
+
or_based_constraints = @left.constraints.last.or(raw_right.constraints.last)
|
|
12
|
+
right = @left.send(method, *args, &block)
|
|
13
|
+
right.where_values = [or_based_constraints]
|
|
14
|
+
right
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def or
|
|
19
|
+
Or.new(self)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
ActiveRecord::Relation.send(:include, ActiveRecordOr)
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
require_relative 'test_helper'
|
|
2
|
+
|
|
3
|
+
ActiveRecord::Base.silence_stream(STDOUT) do
|
|
4
|
+
ActiveRecord::Schema.define do
|
|
5
|
+
|
|
6
|
+
create_table :authors do |t|
|
|
7
|
+
t.string :name
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
create_table :blogs do |t|
|
|
11
|
+
t.string :name
|
|
12
|
+
t.integer :artist_mentions_count
|
|
13
|
+
t.integer :competition_rank
|
|
14
|
+
t.integer :subjective_dislike_rating
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
class Blog < ActiveRecord::Base
|
|
21
|
+
belongs_to :author
|
|
22
|
+
|
|
23
|
+
scope :infringing, where("artist_mentions_count > 0")
|
|
24
|
+
scope :main_competition, where("competition_rank > 7")
|
|
25
|
+
scope :generally_disliked, where("subjective_dislike_rating > 3")
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
class Author < ActiveRecord::Base
|
|
29
|
+
has_many :blogs
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
describe ActiveRecord::Relation do
|
|
33
|
+
describe '#or' do
|
|
34
|
+
it 'can combine conditions with OR' do
|
|
35
|
+
to_blacklist = Blog.infringing.or.main_competition.or.generally_disliked
|
|
36
|
+
# don't know what's up with all the extra parens, but I can't see how they
|
|
37
|
+
# hurt anything other than my eyes
|
|
38
|
+
to_blacklist.where_sql.must_equal(
|
|
39
|
+
"WHERE (((((artist_mentions_count > 0)"\
|
|
40
|
+
" OR (competition_rank > 7)))"\
|
|
41
|
+
" OR (subjective_dislike_rating > 3)))")
|
|
42
|
+
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it 'preserves joins' do
|
|
46
|
+
to_harass = Blog.joins(:author).where(:name => 'Julian')\
|
|
47
|
+
.or.generally_disliked
|
|
48
|
+
to_harass.join_sql.must_equal(
|
|
49
|
+
%(INNER JOIN "authors" ON "authors"."id" = "blogs"."author_id") )
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
data/test/test_helper.rb
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'active_record'
|
|
3
|
+
|
|
4
|
+
$:.unshift File.expand_path("lib")
|
|
5
|
+
require 'active_record_or'
|
|
6
|
+
|
|
7
|
+
gem 'minitest'
|
|
8
|
+
require 'minitest/autorun'
|
|
9
|
+
|
|
10
|
+
ActiveRecord::Base.establish_connection(
|
|
11
|
+
:adapter => 'sqlite3',
|
|
12
|
+
:database => ':memory:' )
|
metadata
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: active_record_or
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
prerelease:
|
|
6
|
+
platform: ruby
|
|
7
|
+
authors:
|
|
8
|
+
- Woody Peterson
|
|
9
|
+
autorequire:
|
|
10
|
+
bindir: bin
|
|
11
|
+
cert_chain: []
|
|
12
|
+
date: 2012-01-25 00:00:00.000000000 Z
|
|
13
|
+
dependencies: []
|
|
14
|
+
description: Adds OR logic to ActiveRecord
|
|
15
|
+
email:
|
|
16
|
+
- woody.peterson@gmail.com
|
|
17
|
+
executables: []
|
|
18
|
+
extensions: []
|
|
19
|
+
extra_rdoc_files: []
|
|
20
|
+
files:
|
|
21
|
+
- .gitignore
|
|
22
|
+
- Gemfile
|
|
23
|
+
- README.md
|
|
24
|
+
- Rakefile
|
|
25
|
+
- active_record_or.gemspec
|
|
26
|
+
- lib/active_record_or.rb
|
|
27
|
+
- lib/active_record_or/version.rb
|
|
28
|
+
- test/active_record_or_test.rb
|
|
29
|
+
- test/test_helper.rb
|
|
30
|
+
homepage: ''
|
|
31
|
+
licenses: []
|
|
32
|
+
post_install_message:
|
|
33
|
+
rdoc_options: []
|
|
34
|
+
require_paths:
|
|
35
|
+
- lib
|
|
36
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
37
|
+
none: false
|
|
38
|
+
requirements:
|
|
39
|
+
- - ! '>='
|
|
40
|
+
- !ruby/object:Gem::Version
|
|
41
|
+
version: '0'
|
|
42
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
43
|
+
none: false
|
|
44
|
+
requirements:
|
|
45
|
+
- - ! '>='
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '0'
|
|
48
|
+
requirements: []
|
|
49
|
+
rubyforge_project: active_record_or
|
|
50
|
+
rubygems_version: 1.8.10
|
|
51
|
+
signing_key:
|
|
52
|
+
specification_version: 3
|
|
53
|
+
summary: Chain scopes with 'or'
|
|
54
|
+
test_files:
|
|
55
|
+
- test/active_record_or_test.rb
|
|
56
|
+
- test/test_helper.rb
|