set_builder 1.1.0 → 1.2.0.beta1
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.
- checksums.yaml +4 -4
- data/.travis.yml +6 -0
- data/README.md +13 -17
- data/lib/set_builder/constraint.rb +2 -1
- data/lib/set_builder/set.rb +9 -19
- data/lib/set_builder/version.rb +1 -1
- data/lib/set_builder.rb +6 -1
- data/set_builder.gemspec +1 -1
- data/test/set_test.rb +2 -8
- data/test/test_helper.rb +14 -35
- metadata +10 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7bf1d04e0fd591ff37671dbd2dc1ce2cede2a540
|
4
|
+
data.tar.gz: eef6f337c4eb113547e4ff748756bb5df09d8aaa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 792157510a3bf947bf29af2666c5fd7f25d931a42d7d81742975b7eb85efdf7335c774342dc4bb9e2f38674bf34aac4ecaeaa981d8ecfd301c44957b39944964
|
7
|
+
data.tar.gz: b143d8b08ea3115b14135fefff0bb3ca0c4210b6843317aacbe7385fba1adc775f7c403dcb0a6fae884ac47422189b750f0e72adc8d7a16ddd93c03a53eec229
|
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -1,35 +1,31 @@
|
|
1
|
-
SetBuilder
|
2
|
-
==========
|
1
|
+
# SetBuilder
|
3
2
|
|
4
|
-
|
3
|
+
[](https://travis-ci.org/boblail/set_builder)
|
4
|
+
[](https://codeclimate.com/github/boblail/set_builder)
|
5
5
|
|
6
|
+
SetBuilder is a library for:
|
6
7
|
|
7
|
-
|
8
|
-
|
8
|
+
* Describing a set of constraints in a simple data structure that can easily be serialized
|
9
|
+
* Presenting that data structure in natural language
|
10
|
+
* Performing the set of constraints as a SQL query
|
9
11
|
|
10
|
-
|
12
|
+
|
13
|
+
|
14
|
+
### Example
|
15
|
+
|
16
|
+
The following Set describes a group of people:
|
11
17
|
|
12
18
|
[[:awesome],
|
13
19
|
[:attended, "school"],
|
14
20
|
[:died, :not],
|
15
21
|
[:name, {:is => "Jerome"}]]
|
16
22
|
|
17
|
-
SetBuilder can render this
|
23
|
+
SetBuilder can render this Set in plain English:
|
18
24
|
|
19
25
|
[Everyone] who is awesome, who attended school, who has not died, and whose name is Jerome.
|
20
26
|
|
21
27
|
It can also generate a NamedScope on an ActiveRecord model to fetch the people who fit in this set.
|
22
28
|
|
23
29
|
|
24
|
-
Usage
|
25
|
-
=====
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
Roadmap
|
30
|
-
=======
|
31
|
-
|
32
|
-
Right now SetBuilder uses ActiveRecord::NamedScope::Scope internally, but it shouldn't be hard to refactor it to use DataMapper's composable queries instead.
|
33
|
-
|
34
30
|
|
35
31
|
Copyright (c) 2010 Bob Lail, released under the MIT license
|
@@ -22,6 +22,7 @@ module SetBuilder
|
|
22
22
|
|
23
23
|
|
24
24
|
attr_reader :trait, :direct_object, :modifiers, :negative
|
25
|
+
alias :negative? :negative
|
25
26
|
|
26
27
|
|
27
28
|
|
@@ -58,7 +59,7 @@ module SetBuilder
|
|
58
59
|
|
59
60
|
|
60
61
|
def perform(scope)
|
61
|
-
|
62
|
+
@block.call(self, scope)
|
62
63
|
end
|
63
64
|
|
64
65
|
|
data/lib/set_builder/set.rb
CHANGED
@@ -3,14 +3,15 @@ module SetBuilder
|
|
3
3
|
|
4
4
|
|
5
5
|
|
6
|
-
def initialize(
|
7
|
-
@model
|
6
|
+
def initialize(model, scope, raw_data)
|
7
|
+
@model = model
|
8
|
+
@scope = scope
|
8
9
|
@set = raw_data
|
9
10
|
end
|
10
11
|
|
11
12
|
|
12
13
|
|
13
|
-
attr_reader :model
|
14
|
+
attr_reader :model, :scope
|
14
15
|
|
15
16
|
|
16
17
|
|
@@ -43,7 +44,7 @@ module SetBuilder
|
|
43
44
|
# which can fetch the objects which belong to this set
|
44
45
|
#
|
45
46
|
def perform
|
46
|
-
constraints.inject(
|
47
|
+
constraints.inject(scope) { |scope, constraint| constraint.perform(scope) }
|
47
48
|
end
|
48
49
|
|
49
50
|
|
@@ -52,8 +53,10 @@ module SetBuilder
|
|
52
53
|
|
53
54
|
|
54
55
|
|
56
|
+
attr_reader :set
|
57
|
+
|
55
58
|
def get_constraints
|
56
|
-
|
59
|
+
set.inject([]) do |constraints, line|
|
57
60
|
negate, trait_name, args = false, line.first.to_s, line[1..-1]
|
58
61
|
trait_name, negate = trait_name[1..-1], true if (trait_name[0..0] == "!")
|
59
62
|
trait = model.traits[trait_name]
|
@@ -64,18 +67,5 @@ module SetBuilder
|
|
64
67
|
|
65
68
|
|
66
69
|
|
67
|
-
# !todo: this can be overriden or factored out to allow SetBuilder
|
68
|
-
# to be used with other ORMs like DataMapper
|
69
|
-
def get_model_and_scope(model_or_scope)
|
70
|
-
if defined?(ActiveRecord::NamedScope::Scope) && model_or_scope.is_a?(ActiveRecord::NamedScope::Scope)
|
71
|
-
[model_or_scope.proxy_scope, model_or_scope]
|
72
|
-
else
|
73
|
-
# [model_or_scope, model_or_scope.scoped({})]
|
74
|
-
[model_or_scope, model_or_scope.scoped]
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
|
79
|
-
|
80
70
|
end
|
81
|
-
end
|
71
|
+
end
|
data/lib/set_builder/version.rb
CHANGED
data/lib/set_builder.rb
CHANGED
data/set_builder.gemspec
CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
spec.add_dependency "rails"
|
21
|
+
spec.add_dependency "rails"
|
22
22
|
spec.add_development_dependency "bundler", "~> 1.3"
|
23
23
|
spec.add_development_dependency "rake"
|
24
24
|
spec.add_development_dependency "turn"
|
data/test/set_test.rb
CHANGED
@@ -4,10 +4,6 @@ class SetTest < ActiveSupport::TestCase
|
|
4
4
|
|
5
5
|
|
6
6
|
|
7
|
-
test "FakeScope" do
|
8
|
-
assert_equal [5, 4, 3, 2], FakeScope.new(5).scoped(4).scoped(3).scoped(2).composed_scope
|
9
|
-
end
|
10
|
-
|
11
7
|
test "set data struture" do
|
12
8
|
data = [
|
13
9
|
[:awesome],
|
@@ -63,8 +59,7 @@ class SetTest < ActiveSupport::TestCase
|
|
63
59
|
set = Friend.that_belong_to(data)
|
64
60
|
|
65
61
|
expected_results = [{:conditions => {:awesome => true}}]
|
66
|
-
|
67
|
-
assert_equal expected_results, set.perform.composed_scope
|
62
|
+
assert_equal expected_results, set.perform
|
68
63
|
end
|
69
64
|
|
70
65
|
test "complex perform" do
|
@@ -81,8 +76,7 @@ class SetTest < ActiveSupport::TestCase
|
|
81
76
|
{:conditions => {:alive => false}},
|
82
77
|
{:conditions => ["friends.name LIKE ?", "Jerome%"]}
|
83
78
|
]
|
84
|
-
|
85
|
-
assert_equal expected_results, set.perform.composed_scope
|
79
|
+
assert_equal expected_results, set.perform
|
86
80
|
end
|
87
81
|
|
88
82
|
test "invalid set" do
|
data/test/test_helper.rb
CHANGED
@@ -7,27 +7,6 @@ require 'set_builder'
|
|
7
7
|
|
8
8
|
|
9
9
|
|
10
|
-
# Mocks NamedScope so that composed scoping can be tested
|
11
|
-
|
12
|
-
class FakeScope
|
13
|
-
|
14
|
-
def initialize(args)
|
15
|
-
args = [args] unless args.is_a?(Array)
|
16
|
-
@composed_scope = args
|
17
|
-
end
|
18
|
-
|
19
|
-
def scoped(args)
|
20
|
-
FakeScope.new(@composed_scope + [args])
|
21
|
-
end
|
22
|
-
|
23
|
-
def composed_scope
|
24
|
-
@composed_scope
|
25
|
-
end
|
26
|
-
|
27
|
-
end
|
28
|
-
|
29
|
-
|
30
|
-
|
31
10
|
# Sample class used by tests
|
32
11
|
|
33
12
|
SetBuilder::ValueMap.register(:school, [[1, "Concordia"], [2, "McKendree"]])
|
@@ -36,26 +15,26 @@ class Friend
|
|
36
15
|
extend SetBuilder
|
37
16
|
|
38
17
|
|
39
|
-
trait(:is, "awesome") do |query|
|
40
|
-
{:conditions => {:awesome => true}}
|
18
|
+
trait(:is, "awesome") do |query, scope|
|
19
|
+
scope << {:conditions => {:awesome => true}}
|
41
20
|
end
|
42
21
|
|
43
|
-
trait(nil, "died") do |query|
|
44
|
-
{:conditions => {:alive => false}}
|
22
|
+
trait(nil, "died") do |query, scope|
|
23
|
+
scope << {:conditions => {:alive => false}}
|
45
24
|
end
|
46
25
|
|
47
26
|
# this trait accepts modifiers --- an adverbial clause
|
48
|
-
trait(:was, "born", :date) do |query|
|
49
|
-
{:conditions => query.modifiers[0].build_conditions_for("friends.birthday")}
|
27
|
+
trait(:was, "born", :date) do |query, scope|
|
28
|
+
scope << {:conditions => query.modifiers[0].build_conditions_for("friends.birthday")}
|
50
29
|
end
|
51
30
|
|
52
|
-
trait(:whose, "age", :number) do |query|
|
53
|
-
{:conditions => query.modifiers[0].build_conditions_for("friends.age")}
|
31
|
+
trait(:whose, "age", :number) do |query, scope|
|
32
|
+
scope << {:conditions => query.modifiers[0].build_conditions_for("friends.age")}
|
54
33
|
end
|
55
34
|
|
56
35
|
# this trait has a direct object
|
57
|
-
trait(:has, {"attended" => :school}) do |query|
|
58
|
-
{
|
36
|
+
trait(:has, {"attended" => :school}) do |query, scope|
|
37
|
+
scope << {
|
59
38
|
:joins => "INNER JOIN schools ON friends.school_id=schools.id",
|
60
39
|
:conditions => {"schools.id" => query.direct_object}
|
61
40
|
}
|
@@ -63,15 +42,15 @@ class Friend
|
|
63
42
|
|
64
43
|
# this trait is a noun
|
65
44
|
# also modifiers can be classes
|
66
|
-
trait(:whose, "name", StringModifier) do |query|
|
67
|
-
{:conditions => query.modifiers[0].build_conditions_for("friends.name")}
|
45
|
+
trait(:whose, "name", StringModifier) do |query, scope|
|
46
|
+
scope << {:conditions => query.modifiers[0].build_conditions_for("friends.name")}
|
68
47
|
end
|
69
48
|
|
70
49
|
|
71
50
|
|
72
51
|
# by stubbing out scoped, we can unit test the `performed` features
|
73
|
-
def self.
|
74
|
-
|
52
|
+
def self.to_scope
|
53
|
+
[]
|
75
54
|
end
|
76
55
|
|
77
56
|
|
metadata
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: set_builder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0.beta1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bob Lail
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2014-01-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - '>='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - '>='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -74,6 +74,7 @@ extensions: []
|
|
74
74
|
extra_rdoc_files: []
|
75
75
|
files:
|
76
76
|
- .gitignore
|
77
|
+
- .travis.yml
|
77
78
|
- Gemfile
|
78
79
|
- MIT-LICENSE
|
79
80
|
- README.md
|
@@ -147,12 +148,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
147
148
|
version: '0'
|
148
149
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
149
150
|
requirements:
|
150
|
-
- - '
|
151
|
+
- - '>'
|
151
152
|
- !ruby/object:Gem::Version
|
152
|
-
version:
|
153
|
+
version: 1.3.1
|
153
154
|
requirements: []
|
154
155
|
rubyforge_project:
|
155
|
-
rubygems_version: 2.
|
156
|
+
rubygems_version: 2.2.1
|
156
157
|
signing_key:
|
157
158
|
specification_version: 4
|
158
159
|
summary: Define traits on a model, create sets that constrain those traits, and generate
|