Skip to content

Commit f670e21

Browse files
authored
feat: mysql support (#43)
* chore(docker-compose): add mysql container * chore: pg and pg_search are optional * fix(tests): passing for both mysql and pg * chore: bump to 3.0.0 Breaking change: The gem no longer depends directly on the `pg_search` gem. This means models using `pg_search_scope` must be updated to explicitly `include PgSearch::Model`. * fix(ci): use a real mysql image * fix(deps): gemfile.lock updated * fix(ci): configurable encoding * fix(ci): mysql initialization
1 parent 565d5d2 commit f670e21

File tree

10 files changed

+69
-39
lines changed

10 files changed

+69
-39
lines changed

.github/workflows/rspec-tests.yml

+39-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ name: Tests
33
on: [push]
44

55
jobs:
6-
build:
7-
name: RSpec
6+
rspec_postgres:
7+
name: RSpec (Postgres)
88
runs-on: ubuntu-latest
99

1010
services:
@@ -38,3 +38,40 @@ jobs:
3838
with:
3939
name: rspec-screenshots
4040
path: tmp/screenshots
41+
rspec_mysql:
42+
name: RSpec (MySQL)
43+
runs-on: ubuntu-latest
44+
45+
services:
46+
mysql:
47+
image: mysql:8.2
48+
ports: ["3306:3306"]
49+
env:
50+
MYSQL_ROOT_PASSWORD: password
51+
MYSQL_DATABASE: sn_filterable_test
52+
53+
steps:
54+
- uses: actions/checkout@v4
55+
- name: Set up Ruby
56+
uses: ruby/setup-ruby@v1
57+
with:
58+
ruby-version: 3.2
59+
bundler-cache: true
60+
- name: Setup Database
61+
env:
62+
RAILS_ENV: test
63+
DATABASE_URL: mysql2://root:[email protected]:3306/sn_filterable_test
64+
DATABASE_ENCODING: utf8mb4
65+
run: cd spec/dummy && bin/rails db:schema:load
66+
- name: Test with rspec
67+
env:
68+
RAILS_ENV: test
69+
DATABASE_URL: mysql2://root:[email protected]:3306/sn_filterable_test
70+
DATABASE_ENCODING: utf8mb4
71+
run: bundle exec rspec
72+
- name: Archive RSpec screenshots
73+
if: always()
74+
uses: actions/upload-artifact@v3
75+
with:
76+
name: rspec-screenshots
77+
path: tmp/screenshots

Gemfile.lock

+5-7
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
PATH
22
remote: .
33
specs:
4-
sn_filterable (2.0.0)
4+
sn_filterable (3.0.0)
55
heroicon (~> 1)
66
kaminari (~> 1)
7-
pg (~> 1)
8-
pg_search (~> 2)
97
tailwindcss-rails (~> 2)
108
turbo-rails (~> 2)
119
view_component (~> 2)
@@ -144,6 +142,7 @@ GEM
144142
mini_portile2 (2.8.5)
145143
minitest (5.21.2)
146144
mutex_m (0.2.0)
145+
mysql2 (0.5.6)
147146
net-imap (0.4.9.1)
148147
date
149148
net-protocol
@@ -161,10 +160,7 @@ GEM
161160
parser (3.3.0.5)
162161
ast (~> 2.4.1)
163162
racc
164-
pg (1.5.4)
165-
pg_search (2.3.6)
166-
activerecord (>= 5.2)
167-
activesupport (>= 5.2)
163+
pg (1.5.6)
168164
psych (5.1.2)
169165
stringio
170166
racc (1.7.3)
@@ -295,6 +291,8 @@ PLATFORMS
295291
DEPENDENCIES
296292
factory_bot_rails (~> 6)
297293
faker (~> 3)
294+
mysql2 (~> 0.5)
295+
pg (~> 1)
298296
rake (~> 13)
299297
rspec-rails (~> 6)
300298
rubocop-github (~> 0)

docker-compose.yml

+8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
version: "3"
22
services:
3+
mysql:
4+
image: mysql:8.2
5+
environment:
6+
- "MYSQL_ROOT_PASSWORD=password"
7+
- "MYSQL_DATABASE=sn_filterable_test"
8+
ports:
9+
- 3306:3306
10+
311
postgres:
412
image: postgres:14-alpine
513
ports:

lib/sn_filterable/filterable.rb

-2
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,10 @@
1414
# `DEFAULT_SORT`: Optional, sets the default sort of the items when no sorting parameter is set. Can be either a [String], which returns the sorting name or an [Array], where the first item is the sorting name and the second item is the sort direction (either `:asc` or `:desc`).
1515
#
1616
# @see Filtered
17-
require "pg_search"
1817

1918
module SnFilterable
2019
module Filterable
2120
extend ActiveSupport::Concern
22-
include PgSearch::Model
2321

2422
class_methods do
2523
# Filters and sorts the model's items.

lib/sn_filterable/version.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# frozen_string_literal: true
22

33
module SnFilterable
4-
VERSION = "2.0.0"
4+
VERSION = "3.0.0"
55
end

sn_filterable.gemspec

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,12 @@ Gem::Specification.new do |spec|
2929
# Uncomment to register a new dependency of your gem
3030
spec.add_dependency "heroicon", "~> 1"
3131
spec.add_dependency "kaminari", "~> 1"
32-
spec.add_dependency "pg", "~> 1"
33-
spec.add_dependency "pg_search", "~> 2"
3432
spec.add_dependency "tailwindcss-rails", "~> 2"
3533
spec.add_dependency "turbo-rails", "~> 2"
3634
spec.add_dependency "view_component", "~> 2"
3735

36+
spec.add_development_dependency "pg", "~> 1"
37+
spec.add_development_dependency "mysql2", "~> 0.5"
3838
spec.add_development_dependency "factory_bot_rails", "~> 6"
3939
spec.add_development_dependency "faker", "~> 3"
4040
spec.add_development_dependency "rake", "~> 13"

spec/dummy/config/database.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
#
1717
default: &default
1818
adapter: postgresql
19-
encoding: unicode
19+
encoding: <%= ENV["DATABASE_ENCODING"] || "unicode" %>
2020
# For details on connection pooling, see Rails configuration guide
2121
# https://guides.rubyonrails.org/configuring.html#database-pooling
2222
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>

spec/dummy/db/schema.rb

-4
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,6 @@
1212

1313
ActiveRecord::Schema.define(version: 2022_12_07_175021) do
1414

15-
# These are extensions that must be enabled in order to support this database
16-
enable_extension "plpgsql"
17-
enable_extension "unaccent"
18-
1915
create_table "dummy_models", force: :cascade do |t|
2016
t.datetime "created_at", precision: 6, null: false
2117
t.datetime "updated_at", precision: 6, null: false

spec/models/concerns/filterable_spec.rb

+12-19
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
BasicFilterableTestModel::FILTER_SCOPE_MAPPINGS = { # rubocop:disable RSpec/LeakyConstantDeclaration
1414
"name": :filter_by_name,
1515
"favorite_number": :filter_by_favorite_number,
16-
"search": :search_by_name_favorite_number
16+
"search": :search_by_name
1717
}.freeze
1818

1919
BasicFilterableTestModel::SORT_SCOPE_MAPPINGS = { # rubocop:disable RSpec/LeakyConstantDeclaration
@@ -26,13 +26,7 @@
2626

2727
scope :sort_by_name, -> { order :name }
2828
scope :sort_by_favorite_number, -> { order :favorite_number }
29-
30-
pg_search_scope :search_by_name_favorite_number,
31-
against: { name: "A", favorite_number: "B" },
32-
using: {
33-
tsearch: { prefix: true, dictionary: "english" }
34-
},
35-
ignoring: :accents
29+
scope :search_by_name, ->(search) { where("name like ?", "%#{search}%")}
3630
end
3731
end
3832

@@ -193,15 +187,6 @@
193187
expect(filtered.items.map(&:name)).to eq(expected_items)
194188
end
195189

196-
it "can search ignoring diacritics" do
197-
all_items = BasicFilterableTestModel.where(nil)
198-
expected_items = [all_items.first.name]
199-
200-
filtered = BasicFilterableTestModel.filter(params: ActionController::Parameters.new({ filter: { search: target_user.name.split(//).join("").tr("aeiouylszcn", "àèîôûÿłšżçñ") } }))
201-
202-
expect(filtered.items.map(&:name)).to eq(expected_items)
203-
end
204-
205190
it "can search with other params" do
206191
expected_items = []
207192

@@ -532,15 +517,23 @@ def generate_join_sql(model)
532517
polymorphic_association_id = "#{polymorphic_association}_id"
533518
polymorphic_association_type = "#{polymorphic_association}_type"
534519

535-
"LEFT OUTER JOIN \"#{first_model_table}\" ON \"#{first_model_table}\".id = \"#{base_model_table}\".\"#{polymorphic_association_id}\" AND \"#{base_model_table}\".\"#{polymorphic_association_type}\" = '#{first_model_name}'"
520+
if ActiveRecord::Base.connection_db_config.adapter == "mysql2"
521+
"LEFT OUTER JOIN `#{first_model_table}` ON `#{first_model_table}`.id = `#{base_model_table}`.`#{polymorphic_association_id}` AND `#{base_model_table}`.`#{polymorphic_association_type}` = '#{first_model_name}'"
522+
else
523+
"LEFT OUTER JOIN \"#{first_model_table}\" ON \"#{first_model_table}\".id = \"#{base_model_table}\".\"#{polymorphic_association_id}\" AND \"#{base_model_table}\".\"#{polymorphic_association_type}\" = '#{first_model_name}'"
524+
end
536525
end
537526
end
538527

539528
describe ".coalesce" do
540529
it "creates a valid function" do
541530
actual_output = described_class.coalesce([DummyModel], "some_column")
542531

543-
expect(actual_output).to eq("coalesce(\"dummy_models\".\"some_column\")")
532+
if ActiveRecord::Base.connection_db_config.adapter == "mysql2"
533+
expect(actual_output).to eq("coalesce(`dummy_models`.`some_column`)")
534+
else
535+
expect(actual_output).to eq("coalesce(\"dummy_models\".\"some_column\")")
536+
end
544537
end
545538
end
546539
end

spec/spec_helper.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
require_relative "dummy/app/models/dummy_model"
1111

1212
ActiveRecord::Base.establish_connection(
13-
"postgresql://postgres:password@localhost:5432/sn_filterable_test?schema=public&connection_limit=5"
13+
ENV["DATABASE_URL"] || "postgresql://postgres:password@localhost:5432/sn_filterable_test?schema=public&connection_limit=5"
1414
)
1515

1616
FactoryBot.reload

0 commit comments

Comments
 (0)