activerecord-refined 0.3.1 → 0.3.3
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/.github/workflows/push_gem.yml +45 -0
- data/.github/workflows/test.yml +23 -0
- data/.gitignore +2 -0
- data/Gemfile +8 -0
- data/README.md +141 -8
- data/Rakefile +17 -0
- data/examples/aggregations.rb +91 -0
- data/examples/complex_joins.rb +69 -0
- data/lib/active_record/refined/ast.rb +275 -54
- data/lib/active_record/refined.rb +5 -7
- data/lib/activerecord-refined/version.rb +1 -1
- data/test/test_block_syntax.rb +370 -72
- data/test/test_helper.rb +94 -3
- metadata +5 -1
data/test/test_helper.rb
CHANGED
|
@@ -5,9 +5,93 @@ require 'minitest/autorun'
|
|
|
5
5
|
Bundler.require
|
|
6
6
|
|
|
7
7
|
require 'active_record'
|
|
8
|
+
require 'etc'
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
# Which database to generate SQL for. The tests only build queries, so any
|
|
11
|
+
# server reachable without further setup will do; the devcontainer runs
|
|
12
|
+
# PostgreSQL and MariaDB on localhost with a passwordless account named after
|
|
13
|
+
# the container user.
|
|
14
|
+
#
|
|
15
|
+
# rake test # sqlite3
|
|
16
|
+
# ADAPTER=postgresql rake test
|
|
17
|
+
# ADAPTER=mysql2 rake test
|
|
18
|
+
# rake test:all # all three in turn
|
|
19
|
+
ADAPTER = ENV.fetch('ADAPTER', 'sqlite3')
|
|
20
|
+
|
|
21
|
+
DATABASE_NAME = 'activerecord_refined_test'.freeze
|
|
22
|
+
|
|
23
|
+
DATABASE_CONFIG =
|
|
24
|
+
case ADAPTER
|
|
25
|
+
when 'sqlite3'
|
|
26
|
+
{adapter: 'sqlite3', database: ':memory:'}
|
|
27
|
+
when 'postgresql', 'mysql2'
|
|
28
|
+
{
|
|
29
|
+
adapter: ADAPTER,
|
|
30
|
+
host: ENV.fetch('DB_HOST', '127.0.0.1'),
|
|
31
|
+
username: ENV.fetch('DB_USERNAME') { Etc.getlogin },
|
|
32
|
+
password: ENV['DB_PASSWORD'],
|
|
33
|
+
database: DATABASE_NAME,
|
|
34
|
+
}
|
|
35
|
+
else
|
|
36
|
+
raise ArgumentError, "unknown ADAPTER: #{ADAPTER}"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# The server databases persist between runs, so create one on first use.
|
|
40
|
+
unless ADAPTER == 'sqlite3'
|
|
41
|
+
maintenance_database = ADAPTER == 'postgresql' ? 'postgres' : 'mysql'
|
|
42
|
+
ActiveRecord::Base.establish_connection(
|
|
43
|
+
DATABASE_CONFIG.merge(database: maintenance_database))
|
|
44
|
+
begin
|
|
45
|
+
ActiveRecord::Base.lease_connection.create_database(DATABASE_NAME)
|
|
46
|
+
rescue ActiveRecord::DatabaseAlreadyExists
|
|
47
|
+
end
|
|
48
|
+
ActiveRecord::Base.remove_connection
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
ActiveRecord::Base.establish_connection(DATABASE_CONFIG)
|
|
52
|
+
|
|
53
|
+
module SqlAssertions
|
|
54
|
+
# Arel spells the regexp match differently per adapter, and raises on the
|
|
55
|
+
# ones missing from this list.
|
|
56
|
+
REGEXP_OPERATORS = {
|
|
57
|
+
'postgresql' => ['~', '!~'],
|
|
58
|
+
'mysql2' => ['REGEXP', 'NOT REGEXP'],
|
|
59
|
+
}.freeze
|
|
60
|
+
|
|
61
|
+
def skip_without_regexp_support
|
|
62
|
+
skip "#{ADAPTER} has no regexp operator" unless REGEXP_OPERATORS.key?(ADAPTER)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def skip_without_array_columns
|
|
66
|
+
skip "#{ADAPTER} has no array columns" unless ADAPTER == 'postgresql'
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def regexp_operator
|
|
70
|
+
Regexp.escape(REGEXP_OPERATORS.fetch(ADAPTER).first)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def not_regexp_operator
|
|
74
|
+
Regexp.escape(REGEXP_OPERATORS.fetch(ADAPTER).last)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# MySQL quotes identifiers with backticks instead of double quotes, and
|
|
78
|
+
# doubles the backslashes inside string literals because backslash is itself
|
|
79
|
+
# an escape character there. Normalising both lets a single expectation
|
|
80
|
+
# cover every adapter.
|
|
81
|
+
def normalize_sql(sql)
|
|
82
|
+
sql.tr('`', '"').gsub("\\\\") { "\\" }
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Takes a relation or the SQL string of one.
|
|
86
|
+
def assert_sql(pattern, relation_or_sql)
|
|
87
|
+
sql = relation_or_sql.respond_to?(:to_sql) ? relation_or_sql.to_sql : relation_or_sql
|
|
88
|
+
assert_match(pattern, normalize_sql(sql))
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
class Minitest::Test
|
|
93
|
+
include SqlAssertions
|
|
94
|
+
end
|
|
11
95
|
|
|
12
96
|
class User < ActiveRecord::Base
|
|
13
97
|
end
|
|
@@ -22,7 +106,14 @@ end
|
|
|
22
106
|
|
|
23
107
|
class CreateAllTables < ActiveRecord::Migration[8.1]
|
|
24
108
|
def up
|
|
25
|
-
|
|
109
|
+
drop_table(:users, if_exists: true)
|
|
110
|
+
drop_table(:authors, if_exists: true)
|
|
111
|
+
drop_table(:posts, if_exists: true)
|
|
112
|
+
create_table(:users) do |t|
|
|
113
|
+
t.string :name
|
|
114
|
+
t.integer :age
|
|
115
|
+
t.string :tags, array: true if ADAPTER == 'postgresql'
|
|
116
|
+
end
|
|
26
117
|
create_table(:authors) {|t| t.string :name}
|
|
27
118
|
create_table(:posts) {|t| t.string :title; t.integer :author_id}
|
|
28
119
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: activerecord-refined
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Shugo Maeda
|
|
@@ -80,12 +80,16 @@ executables: []
|
|
|
80
80
|
extensions: []
|
|
81
81
|
extra_rdoc_files: []
|
|
82
82
|
files:
|
|
83
|
+
- .github/workflows/push_gem.yml
|
|
84
|
+
- .github/workflows/test.yml
|
|
83
85
|
- .gitignore
|
|
84
86
|
- Gemfile
|
|
85
87
|
- LICENSE.txt
|
|
86
88
|
- README.md
|
|
87
89
|
- Rakefile
|
|
88
90
|
- activerecord-refined.gemspec
|
|
91
|
+
- examples/aggregations.rb
|
|
92
|
+
- examples/complex_joins.rb
|
|
89
93
|
- lib/active_record/refined.rb
|
|
90
94
|
- lib/active_record/refined/ast.rb
|
|
91
95
|
- lib/activerecord-refined.rb
|