squeel 1.0.18 → 1.1.0
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/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +2 -7
- data/CHANGELOG.md +9 -0
- data/Gemfile +2 -2
- data/README.md +223 -147
- data/lib/generators/templates/squeel.rb +1 -1
- data/lib/squeel/adapters/active_record.rb +1 -1
- data/lib/squeel/adapters/active_record/4.0/compat.rb +17 -0
- data/lib/squeel/adapters/active_record/4.0/context.rb +1 -0
- data/lib/squeel/adapters/active_record/4.0/preloader_extensions.rb +1 -0
- data/lib/squeel/adapters/active_record/4.0/relation_extensions.rb +126 -0
- data/lib/squeel/adapters/active_record/base_extensions.rb +1 -1
- data/lib/squeel/adapters/active_record/context.rb +10 -10
- data/lib/squeel/adapters/active_record/relation_extensions.rb +24 -16
- data/lib/squeel/configuration.rb +1 -0
- data/lib/squeel/constants.rb +2 -2
- data/lib/squeel/context.rb +2 -2
- data/lib/squeel/dsl.rb +1 -1
- data/lib/squeel/nodes.rb +2 -0
- data/lib/squeel/nodes/binary.rb +1 -1
- data/lib/squeel/nodes/function.rb +5 -5
- data/lib/squeel/nodes/join.rb +2 -2
- data/lib/squeel/nodes/key_path.rb +10 -5
- data/lib/squeel/nodes/literal.rb +1 -1
- data/lib/squeel/nodes/nary.rb +5 -7
- data/lib/squeel/nodes/node.rb +6 -0
- data/lib/squeel/nodes/operation.rb +1 -1
- data/lib/squeel/nodes/order.rb +1 -1
- data/lib/squeel/nodes/predicate.rb +5 -5
- data/lib/squeel/nodes/predicate_methods.rb +11 -2
- data/lib/squeel/nodes/sifter.rb +2 -2
- data/lib/squeel/nodes/stub.rb +2 -2
- data/lib/squeel/nodes/unary.rb +1 -1
- data/lib/squeel/version.rb +1 -1
- data/lib/squeel/visitors/predicate_visitation.rb +6 -6
- data/lib/squeel/visitors/predicate_visitor.rb +1 -1
- data/lib/squeel/visitors/visitor.rb +20 -20
- data/spec/spec_helper.rb +6 -4
- data/spec/squeel/adapters/active_record/base_extensions_spec.rb +6 -6
- data/spec/squeel/adapters/active_record/relation_extensions_spec.rb +55 -24
- data/spec/squeel/core_ext/symbol_spec.rb +2 -2
- data/spec/squeel/nodes/key_path_spec.rb +3 -3
- data/spec/squeel/nodes/predicate_operators_spec.rb +4 -4
- data/spec/squeel/visitors/predicate_visitor_spec.rb +11 -11
- data/spec/squeel/visitors/visitor_spec.rb +9 -9
- data/spec/support/models.rb +25 -7
- data/spec/support/schema.rb +1 -1
- data/squeel.gemspec +4 -4
- metadata +19 -12
@@ -23,7 +23,7 @@ describe Symbol do
|
|
23
23
|
it 'creates a function node' do
|
24
24
|
function = :blah.func('foo')
|
25
25
|
function.should be_a Squeel::Nodes::Function
|
26
|
-
function.
|
26
|
+
function.function_name.should eq :blah
|
27
27
|
function.args.should eq ['foo']
|
28
28
|
end
|
29
29
|
end
|
@@ -55,4 +55,4 @@ describe Symbol do
|
|
55
55
|
join._klass.should eq Person
|
56
56
|
end
|
57
57
|
end
|
58
|
-
end
|
58
|
+
end
|
@@ -46,7 +46,7 @@ module Squeel
|
|
46
46
|
it 'creates a named function at its endpoint' do
|
47
47
|
@k.third.fourth.fifth.max(1,2,3)
|
48
48
|
@k.endpoint.should be_a Function
|
49
|
-
@k.endpoint.
|
49
|
+
@k.endpoint.function_name.should eq :max
|
50
50
|
@k.endpoint.args.should eq [1,2,3]
|
51
51
|
end
|
52
52
|
|
@@ -77,7 +77,7 @@ module Squeel
|
|
77
77
|
it 'creates Or nodes with | if the endpoint responds to |' do
|
78
78
|
node = @k.third.fourth.eq('Bob') | Stub.new(:attr).eq('Joe')
|
79
79
|
node.should be_a Or
|
80
|
-
node.left.should
|
80
|
+
node.left.should eql @k
|
81
81
|
node.right.should eql Stub.new(:attr).eq('Joe')
|
82
82
|
end
|
83
83
|
|
@@ -99,7 +99,7 @@ module Squeel
|
|
99
99
|
it 'creates NOT nodes with -@ if the endpoint responds to -@' do
|
100
100
|
node = - @k.third.fourth.eq('Bob')
|
101
101
|
node.should be_a Not
|
102
|
-
node.expr.should
|
102
|
+
node.expr.should eql @k
|
103
103
|
end
|
104
104
|
|
105
105
|
it 'raises NoMethodError with -@ if the endpoint does not respond to -@' do
|
@@ -21,13 +21,13 @@ module Squeel
|
|
21
21
|
n.children.should eq [left, right]
|
22
22
|
end
|
23
23
|
|
24
|
-
it '
|
24
|
+
it 'creates And nodes by appending a new child' do
|
25
25
|
left = :name.matches % 'J%' & :name.matches % '%e'
|
26
26
|
right = :id.gt % 0
|
27
27
|
expected = left.children + [right]
|
28
|
-
left & right
|
29
|
-
|
30
|
-
|
28
|
+
new_and = left & right
|
29
|
+
new_and.should be_a And
|
30
|
+
new_and.children.should eq expected
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
@@ -327,7 +327,7 @@ module Squeel
|
|
327
327
|
predicate.to_sql.should be_like '"people"."id" IN (SELECT "people"."id" FROM "people" ORDER BY "people"."id" DESC LIMIT 3)'
|
328
328
|
end
|
329
329
|
|
330
|
-
it 'converts ActiveRecord::Relation values in function arguments to their
|
330
|
+
it 'converts ActiveRecord::Relation values in function arguments to their Arel AST' do
|
331
331
|
predicate = @v.accept(dsl{exists(Person.where{name == 'Aric Smith'})})
|
332
332
|
predicate.should be_a Arel::Nodes::NamedFunction
|
333
333
|
predicate.expressions.first.should be_a Arel::Nodes::SelectStatement
|
@@ -386,7 +386,7 @@ module Squeel
|
|
386
386
|
predicate.right.should eq 'Joe'
|
387
387
|
end
|
388
388
|
|
389
|
-
it 'creates an
|
389
|
+
it 'creates an Arel Grouping node containing an Or node for Or nodes' do
|
390
390
|
left = :name.matches % 'Joe%'
|
391
391
|
right = :id.gt % 1
|
392
392
|
predicate = @v.accept(left | right)
|
@@ -396,23 +396,23 @@ module Squeel
|
|
396
396
|
predicate.expr.right.should be_a Arel::Nodes::GreaterThan
|
397
397
|
end
|
398
398
|
|
399
|
-
it 'creates an
|
399
|
+
it 'creates an Arel Not node for a Not node' do
|
400
400
|
expr = -(:name.matches % 'Joe%')
|
401
401
|
predicate = @v.accept(expr)
|
402
402
|
predicate.should be_a Arel::Nodes::Not
|
403
403
|
end
|
404
404
|
|
405
|
-
it 'creates an
|
405
|
+
it 'creates an Arel NamedFunction node for a Function node' do
|
406
406
|
function = @v.accept(:find_in_set.func())
|
407
407
|
function.should be_a Arel::Nodes::NamedFunction
|
408
408
|
end
|
409
409
|
|
410
|
-
it 'maps symbols in Function args to
|
410
|
+
it 'maps symbols in Function args to Arel attributes' do
|
411
411
|
function = @v.accept(:find_in_set.func(:id, '1,2,3'))
|
412
412
|
function.to_sql.should match /"people"."id"/
|
413
413
|
end
|
414
414
|
|
415
|
-
it 'sets the alias on the
|
415
|
+
it 'sets the alias on the Arel NamedFunction from the Function alias' do
|
416
416
|
function = @v.accept(:find_in_set.func(:id, '1,2,3').as('newname'))
|
417
417
|
function.to_sql.should match /newname/
|
418
418
|
end
|
@@ -427,27 +427,27 @@ module Squeel
|
|
427
427
|
as.to_sql.should match /"people"."name" AS other_name/
|
428
428
|
end
|
429
429
|
|
430
|
-
it 'creates an
|
430
|
+
it 'creates an Arel Addition node for an Operation node with + as operator' do
|
431
431
|
operation = @v.accept(dsl{id + 1})
|
432
432
|
operation.should be_a Arel::Nodes::Addition
|
433
433
|
end
|
434
434
|
|
435
|
-
it 'creates an
|
435
|
+
it 'creates an Arel Subtraction node for an Operation node with - as operator' do
|
436
436
|
operation = @v.accept(dsl{id - 1})
|
437
437
|
operation.should be_a Arel::Nodes::Subtraction
|
438
438
|
end
|
439
439
|
|
440
|
-
it 'creates an
|
440
|
+
it 'creates an Arel Multiplication node for an Operation node with * as operator' do
|
441
441
|
operation = @v.accept(dsl{id * 1})
|
442
442
|
operation.should be_a Arel::Nodes::Multiplication
|
443
443
|
end
|
444
444
|
|
445
|
-
it 'creates an
|
445
|
+
it 'creates an Arel Division node for an Operation node with / as operator' do
|
446
446
|
operation = @v.accept(dsl{id / 1})
|
447
447
|
operation.should be_a Arel::Nodes::Division
|
448
448
|
end
|
449
449
|
|
450
|
-
it 'creates an
|
450
|
+
it 'creates an Arel InfixOperation node for an Operation with a custom operator' do
|
451
451
|
operation = @v.accept(dsl{id.op(:blah, 1)})
|
452
452
|
operation.should be_a Arel::Nodes::InfixOperation
|
453
453
|
end
|
@@ -16,7 +16,7 @@ module Squeel
|
|
16
16
|
@v = Visitor.new(@c)
|
17
17
|
end
|
18
18
|
|
19
|
-
it 'creates a bare
|
19
|
+
it 'creates a bare Arel attribute given a symbol with no asc/desc' do
|
20
20
|
attribute = @v.accept(:name)
|
21
21
|
attribute.should be_a Arel::Attribute
|
22
22
|
attribute.name.should eq :name
|
@@ -71,12 +71,12 @@ module Squeel
|
|
71
71
|
node.to_sql.should be_like "(SELECT \"people\".\"id\" FROM \"people\" WHERE \"people\".\"name\" = 'Aric Smith') aric"
|
72
72
|
end
|
73
73
|
|
74
|
-
it 'creates an
|
74
|
+
it 'creates an Arel NamedFunction node for a Function node' do
|
75
75
|
function = @v.accept(:find_in_set.func())
|
76
76
|
function.should be_a Arel::Nodes::NamedFunction
|
77
77
|
end
|
78
78
|
|
79
|
-
it 'maps symbols in Function args to
|
79
|
+
it 'maps symbols in Function args to Arel attributes' do
|
80
80
|
function = @v.accept(:find_in_set.func(:id, '1,2,3'))
|
81
81
|
function.to_sql.should match /find_in_set\("people"."id", '1,2,3'\)/
|
82
82
|
end
|
@@ -86,7 +86,7 @@ module Squeel
|
|
86
86
|
function.to_sql.should match /find_in_set\("children_people_2"."id", '1,2,3'\)/
|
87
87
|
end
|
88
88
|
|
89
|
-
it 'sets the alias on the
|
89
|
+
it 'sets the alias on the Arel NamedFunction from the Function alias' do
|
90
90
|
function = @v.accept(:find_in_set.func(:id, '1,2,3').as('newname'))
|
91
91
|
function.to_sql.should match /newname/
|
92
92
|
end
|
@@ -106,27 +106,27 @@ module Squeel
|
|
106
106
|
as.to_sql.should match /"children_people"."name" AS other_name/
|
107
107
|
end
|
108
108
|
|
109
|
-
it 'creates an
|
109
|
+
it 'creates an Arel Grouping node for a Squeel Grouping node' do
|
110
110
|
grouping = @v.accept(dsl{_(id)})
|
111
111
|
grouping.should be_a Arel::Nodes::Grouping
|
112
112
|
end
|
113
113
|
|
114
|
-
it 'creates an
|
114
|
+
it 'creates an Arel Addition node for an Operation node with + as operator' do
|
115
115
|
operation = @v.accept(dsl{id + 1})
|
116
116
|
operation.should be_a Arel::Nodes::Addition
|
117
117
|
end
|
118
118
|
|
119
|
-
it 'creates an
|
119
|
+
it 'creates an Arel Subtraction node for an Operation node with - as operator' do
|
120
120
|
operation = @v.accept(dsl{id - 1})
|
121
121
|
operation.should be_a Arel::Nodes::Subtraction
|
122
122
|
end
|
123
123
|
|
124
|
-
it 'creates an
|
124
|
+
it 'creates an Arel Multiplication node for an Operation node with * as operator' do
|
125
125
|
operation = @v.accept(dsl{id * 1})
|
126
126
|
operation.should be_a Arel::Nodes::Multiplication
|
127
127
|
end
|
128
128
|
|
129
|
-
it 'creates an
|
129
|
+
it 'creates an Arel Division node for an Operation node with / as operator' do
|
130
130
|
operation = @v.accept(dsl{id / 1})
|
131
131
|
operation.should be_a Arel::Nodes::Division
|
132
132
|
end
|
data/spec/support/models.rb
CHANGED
@@ -2,10 +2,24 @@ class Person < ActiveRecord::Base
|
|
2
2
|
belongs_to :parent, :class_name => 'Person', :foreign_key => :parent_id
|
3
3
|
has_many :children, :class_name => 'Person', :foreign_key => :parent_id
|
4
4
|
has_many :articles
|
5
|
-
has_many :articles_with_condition, :class_name => 'Article', :conditions => {:title => 'Condition'}
|
6
5
|
has_many :comments
|
6
|
+
if ActiveRecord::VERSION::MAJOR == 4
|
7
|
+
has_many :articles_with_condition, lambda { where :title => 'Condition' },
|
8
|
+
:class_name => 'Article'
|
9
|
+
has_many :article_comments_with_first_post,
|
10
|
+
lambda { where :body => 'first post' },
|
11
|
+
:through => :articles, :source => :comments
|
12
|
+
else
|
13
|
+
has_many :articles_with_condition, :conditions => {:title => 'Condition'},
|
14
|
+
:class_name => 'Article'
|
15
|
+
has_many :article_comments_with_first_post,
|
16
|
+
:conditions => { :body => 'first post' },
|
17
|
+
:through => :articles, :source => :comments
|
18
|
+
end
|
7
19
|
has_many :condition_article_comments, :through => :articles_with_condition, :source => :comments
|
8
|
-
|
20
|
+
if ActiveRecord::VERSION::MAJOR == 4
|
21
|
+
else
|
22
|
+
end
|
9
23
|
has_many :authored_article_comments, :through => :articles,
|
10
24
|
:source => :comments
|
11
25
|
has_many :notes, :as => :notable
|
@@ -28,18 +42,22 @@ class Person < ActiveRecord::Base
|
|
28
42
|
end
|
29
43
|
|
30
44
|
class PersonWithNamePrimaryKey < ActiveRecord::Base
|
31
|
-
|
45
|
+
self.primary_key = 'name'
|
32
46
|
# Set this second, because I'm lazy and don't want to populate another table,
|
33
47
|
# and also don't want to clobber the AR connection's primary_key cache.
|
34
|
-
|
48
|
+
self.table_name = 'people'
|
35
49
|
end
|
36
50
|
|
37
51
|
class PersonNamedBill < ActiveRecord::Base
|
38
52
|
self.table_name = 'people'
|
39
53
|
belongs_to :parent, :class_name => 'Person', :foreign_key => :parent_id
|
40
|
-
|
41
|
-
|
42
|
-
|
54
|
+
if ActiveRecord::VERSION::MAJOR > 3 || ActiveRecord::VERSION::MINOR > 0
|
55
|
+
default_scope lambda { where{name == 'Bill'}.order{id} }
|
56
|
+
else # 3.0 doesn't support callables for default_scope
|
57
|
+
default_scope where{name == 'Bill'}.order{id}
|
58
|
+
end
|
59
|
+
scope :highly_compensated, lambda { where {salary > 200000} }
|
60
|
+
scope :ending_with_ill, lambda { where{name =~ '%ill'} }
|
43
61
|
scope :with_salary_equal_to, lambda { |value| where{abs(salary) == value} }
|
44
62
|
end
|
45
63
|
|
data/spec/support/schema.rb
CHANGED
data/squeel.gemspec
CHANGED
@@ -11,16 +11,16 @@ Gem::Specification.new do |s|
|
|
11
11
|
s.homepage = "http://erniemiller.org/projects/squeel"
|
12
12
|
s.summary = %q{Active Record 3, improved.}
|
13
13
|
s.description = %q{
|
14
|
-
Squeel unlocks the power of
|
14
|
+
Squeel unlocks the power of Arel in your Rails 3 application with
|
15
15
|
a handy block-based syntax. You can write subqueries, access named
|
16
16
|
functions provided by your RDBMS, and more, all without writing
|
17
17
|
SQL strings.
|
18
18
|
}
|
19
19
|
s.rubyforge_project = "squeel"
|
20
20
|
|
21
|
-
s.add_dependency 'activerecord', '
|
22
|
-
s.add_dependency 'activesupport', '
|
23
|
-
s.add_dependency 'polyamorous', '~> 0.
|
21
|
+
s.add_dependency 'activerecord', '>= 3.0'
|
22
|
+
s.add_dependency 'activesupport', '>= 3.0'
|
23
|
+
s.add_dependency 'polyamorous', '~> 0.6.0'
|
24
24
|
s.add_development_dependency 'rspec', '~> 2.6.0'
|
25
25
|
s.add_development_dependency 'machinist', '~> 1.0.6'
|
26
26
|
s.add_development_dependency 'faker', '~> 0.9.5'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: squeel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,14 +9,14 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-07-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
|
-
- -
|
19
|
+
- - ! '>='
|
20
20
|
- !ruby/object:Gem::Version
|
21
21
|
version: '3.0'
|
22
22
|
type: :runtime
|
@@ -24,7 +24,7 @@ dependencies:
|
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
25
|
none: false
|
26
26
|
requirements:
|
27
|
-
- -
|
27
|
+
- - ! '>='
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: '3.0'
|
30
30
|
- !ruby/object:Gem::Dependency
|
@@ -32,7 +32,7 @@ dependencies:
|
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
33
33
|
none: false
|
34
34
|
requirements:
|
35
|
-
- -
|
35
|
+
- - ! '>='
|
36
36
|
- !ruby/object:Gem::Version
|
37
37
|
version: '3.0'
|
38
38
|
type: :runtime
|
@@ -40,7 +40,7 @@ dependencies:
|
|
40
40
|
version_requirements: !ruby/object:Gem::Requirement
|
41
41
|
none: false
|
42
42
|
requirements:
|
43
|
-
- -
|
43
|
+
- - ! '>='
|
44
44
|
- !ruby/object:Gem::Version
|
45
45
|
version: '3.0'
|
46
46
|
- !ruby/object:Gem::Dependency
|
@@ -50,7 +50,7 @@ dependencies:
|
|
50
50
|
requirements:
|
51
51
|
- - ~>
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version: 0.
|
53
|
+
version: 0.6.0
|
54
54
|
type: :runtime
|
55
55
|
prerelease: false
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -58,7 +58,7 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - ~>
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: 0.
|
61
|
+
version: 0.6.0
|
62
62
|
- !ruby/object:Gem::Dependency
|
63
63
|
name: rspec
|
64
64
|
requirement: !ruby/object:Gem::Requirement
|
@@ -123,7 +123,7 @@ dependencies:
|
|
123
123
|
- - ~>
|
124
124
|
- !ruby/object:Gem::Version
|
125
125
|
version: 1.3.3
|
126
|
-
description: ! "\n Squeel unlocks the power of
|
126
|
+
description: ! "\n Squeel unlocks the power of Arel in your Rails 3 application
|
127
127
|
with\n a handy block-based syntax. You can write subqueries, access named\n
|
128
128
|
\ functions provided by your RDBMS, and more, all without writing\n SQL
|
129
129
|
strings.\n "
|
@@ -134,6 +134,8 @@ extensions: []
|
|
134
134
|
extra_rdoc_files: []
|
135
135
|
files:
|
136
136
|
- .gitignore
|
137
|
+
- .ruby-gemset
|
138
|
+
- .ruby-version
|
137
139
|
- .travis.yml
|
138
140
|
- .yardopts
|
139
141
|
- CHANGELOG.md
|
@@ -157,6 +159,10 @@ files:
|
|
157
159
|
- lib/squeel/adapters/active_record/3.2/context.rb
|
158
160
|
- lib/squeel/adapters/active_record/3.2/preloader_extensions.rb
|
159
161
|
- lib/squeel/adapters/active_record/3.2/relation_extensions.rb
|
162
|
+
- lib/squeel/adapters/active_record/4.0/compat.rb
|
163
|
+
- lib/squeel/adapters/active_record/4.0/context.rb
|
164
|
+
- lib/squeel/adapters/active_record/4.0/preloader_extensions.rb
|
165
|
+
- lib/squeel/adapters/active_record/4.0/relation_extensions.rb
|
160
166
|
- lib/squeel/adapters/active_record/base_extensions.rb
|
161
167
|
- lib/squeel/adapters/active_record/compat.rb
|
162
168
|
- lib/squeel/adapters/active_record/context.rb
|
@@ -180,6 +186,7 @@ files:
|
|
180
186
|
- lib/squeel/nodes/key_path.rb
|
181
187
|
- lib/squeel/nodes/literal.rb
|
182
188
|
- lib/squeel/nodes/nary.rb
|
189
|
+
- lib/squeel/nodes/node.rb
|
183
190
|
- lib/squeel/nodes/not.rb
|
184
191
|
- lib/squeel/nodes/operation.rb
|
185
192
|
- lib/squeel/nodes/operators.rb
|
@@ -255,7 +262,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
255
262
|
version: '0'
|
256
263
|
segments:
|
257
264
|
- 0
|
258
|
-
hash:
|
265
|
+
hash: 3013172818139711392
|
259
266
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
260
267
|
none: false
|
261
268
|
requirements:
|
@@ -264,10 +271,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
264
271
|
version: '0'
|
265
272
|
segments:
|
266
273
|
- 0
|
267
|
-
hash:
|
274
|
+
hash: 3013172818139711392
|
268
275
|
requirements: []
|
269
276
|
rubyforge_project: squeel
|
270
|
-
rubygems_version: 1.8.
|
277
|
+
rubygems_version: 1.8.25
|
271
278
|
signing_key:
|
272
279
|
specification_version: 3
|
273
280
|
summary: Active Record 3, improved.
|