Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .env.local
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DATABASE_URL="mysql2://root:@mysql/"
6 changes: 3 additions & 3 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ jobs:
strategy:
matrix:
ruby:
- '2.7'
- '3.0'
- '3.1'
- '3.2'
- '3.3'
rails:
- '6.0'
- '6.1'

- '7.0'
- '7.1'
runs-on: ubuntu-latest

name: RSpec (Rails ${{ matrix.rails }}) (Ruby ${{ matrix.ruby }})
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@
.rspec_status

gemfiles/*.lock
.env.local
15 changes: 7 additions & 8 deletions Appraisals
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
appraise "rails-6.0" do
gem "rails", "~> 6.0.0"
appraise "rails-6.1" do
gem "rails", "~> 6.1"
end

appraise "rails-6.1" do
gem "rails", "~> 6.1.0"
appraise "rails-7.0" do
gem "rails", "~> 7.0"
end

# Rails 7.0 doesn't work yet
# appraise "rails-7.0" do
# gem "rails", "~> 7.0"
# end
appraise "rails-7.1" do
gem "rails", "~> 7.1"
end
3 changes: 2 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ RUN mkdir -p lib/sql_enum gemfiles
COPY lib/sql_enum/version.rb ./lib/sql_enum/
COPY gemfiles/*.gemfile gemfiles/
COPY sql_enum.gemspec Gemfile Gemfile.lock Appraisals ./
RUN bundle install && exec appraisal install
RUN bundle install && \
bundle exec appraisal install
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
source "https://rubygems.org"

git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }

# Specify your gem's dependencies in sql_enum.gemspec
gemspec
52 changes: 29 additions & 23 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,43 +1,48 @@
PATH
remote: .
specs:
sql_enum (0.4.0)
activerecord (>= 6.0, < 7.0)
activesupport (>= 6.0, < 7.0)
sql_enum (1.0.0)
activerecord (>= 6.1.0)
activesupport (>= 6.1.0)
mysql2

GEM
remote: https://rubygems.org/
specs:
activemodel (6.1.7.6)
activesupport (= 6.1.7.6)
activerecord (6.1.7.6)
activemodel (= 6.1.7.6)
activesupport (= 6.1.7.6)
activesupport (6.1.7.6)
activemodel (7.0.8)
activesupport (= 7.0.8)
activerecord (7.0.8)
activemodel (= 7.0.8)
activesupport (= 7.0.8)
activesupport (7.0.8)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
tzinfo (~> 2.0)
zeitwerk (~> 2.3)
appraisal (2.5.0)
bundler
rake
thor (>= 0.14.0)
concurrent-ruby (1.2.2)
debug (1.8.0)
irb (>= 1.5.0)
reline (>= 0.3.1)
awesome_print (1.9.2)
concurrent-ruby (1.2.3)
debug (1.9.1)
irb (~> 1.10)
reline (>= 0.3.8)
diff-lcs (1.5.0)
i18n (1.14.1)
concurrent-ruby (~> 1.0)
io-console (0.6.0)
irb (1.7.4)
reline (>= 0.3.6)
minitest (5.19.0)
io-console (0.7.2)
irb (1.11.1)
rdoc
reline (>= 0.4.2)
minitest (5.21.2)
mysql2 (0.5.5)
rake (13.0.6)
reline (0.3.8)
psych (5.1.2)
stringio
rake (13.1.0)
rdoc (6.6.2)
psych (>= 4.0.0)
reline (0.4.2)
io-console (~> 0.5)
rspec (3.12.0)
rspec-core (~> 3.12.0)
Expand All @@ -52,22 +57,23 @@ GEM
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.12.0)
rspec-support (3.12.1)
thor (1.2.2)
stringio (3.1.0)
thor (1.3.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
zeitwerk (2.6.11)

PLATFORMS
ruby
x86_64-linux

DEPENDENCIES
appraisal
awesome_print
bundler
debug
rake (~> 13.0)
rspec (~> 3.0)
sql_enum!

BUNDLED WITH
2.2.30
2.5.5
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

Enables usage of native sql enums with ActiveRecord

## NOTE

Version 1.0 of this is compatible with Rails 7 and above.

For Rails versions below Rails 7, use version 0.4

## Installation

Add this line to your application's Gemfile:
Expand Down
3 changes: 2 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@ services:

mysql:
image: mysql:5.7
platform: linux/amd64
environment:
- MYSQL_ALLOW_EMPTY_PASSWORD=yes
- MYSQL_DATABASE
- MYSQL_USER
- MYSQL_PASSWORD
healthcheck:
test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"]
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
timeout: 20s
retries: 10
7 changes: 0 additions & 7 deletions gemfiles/rails_5.2.gemfile

This file was deleted.

7 changes: 0 additions & 7 deletions gemfiles/rails_6.0.gemfile

This file was deleted.

2 changes: 1 addition & 1 deletion gemfiles/rails_6.1.gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

source "https://rubygems.org"

gem "rails", "~> 6.1.0"
gem "rails", "~> 6.1"

gemspec path: "../"
2 changes: 1 addition & 1 deletion gemfiles/rails_7.0.gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

source "https://rubygems.org"

gem "rails", "~> 7.0.0"
gem "rails", "~> 7.0"

gemspec path: "../"
2 changes: 1 addition & 1 deletion gemfiles/rails_5.1.gemfile → gemfiles/rails_7.1.gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

source "https://rubygems.org"

gem "rails", "~> 5.1.0"
gem "rails", "~> 7.1"

gemspec path: "../"
47 changes: 36 additions & 11 deletions lib/active_record/connection_adapters/abstract_mysql.rb
Original file line number Diff line number Diff line change
@@ -1,21 +1,46 @@
# This module fails in Rails 7.0 becuase the method being modified has been
# changed to a class method.

module ActiveRecord
module ConnectionAdapters
class AbstractMysqlAdapter
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is reopening the original adapter, is that right? Is that because there are effectively no hooks we could use? Or would this potentially be a good time to move to a proper initializer that hooks the adapter at that point?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if maybe the thing to do is keep the register_enum_type method here (there are other, similar methods in the adapter already) and move the call of it to a Railtie or something

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My inclination is to get this PR in and then try to mess with that separately?

def initialize_type_map_with_enum(m = type_map)
initialize_without_enum(m)
register_enum_type(m)
class << self
def register_enum_type(mapping)
mapping.register_type(%r(enum)i) do |sql_type|
Type::Enum.new(limit: sql_type.to_s.scan(/'(.*?)'/).flatten)
end
end
end

alias_method :initialize_without_enum, :initialize_type_map
alias_method :initialize_type_map, :initialize_type_map_with_enum
# In Rails 6.1, registering the enum type is an instance method and is
# done on initialization, In Rails 7.0 it is a class method and
# the registration happens when the class is loaded. So, in Rails 6.1,
# we can override the `initialize_type_map` method to register the enum
# but in Rails 7.1, we need to call register_enum_type explicitly.

def register_enum_type(mapping)
mapping.register_type(%r(enum)i) do |sql_type|
Type::Enum.new(limit: sql_type.scan(/'(.*?)'/).flatten)
if SqlEnum.rails_version_match?("6.1")
module SqlEnumMapper
def initialize_type_map(m = type_map)
super(m)
AbstractMysqlAdapter.register_enum_type(m)
end
end

ActiveRecord::ConnectionAdapters::Mysql2Adapter.prepend(SqlEnumMapper)
end


if SqlEnum.rails_version_match?("7.0")
[
ActiveRecord::ConnectionAdapters::Mysql2Adapter::TYPE_MAP,
ActiveRecord::ConnectionAdapters::Mysql2Adapter::TYPE_MAP_WITH_BOOLEAN
].each do |m|
AbstractMysqlAdapter.register_enum_type(m)
end
end

# Rails 7.1 drops the TYPE_MAP_WITH_BOOLEAN constant
if SqlEnum.rails_version_match?("7.1")
AbstractMysqlAdapter.register_enum_type(
ActiveRecord::ConnectionAdapters::Mysql2Adapter::TYPE_MAP
)
end
end
end
Expand Down
4 changes: 4 additions & 0 deletions lib/sql_enum.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ def self.configure
self.configuration ||= Configuration.new
yield(configuration)
end

def self.rails_version_match?(version_string)
ActiveSupport.version.to_s.start_with?(version_string)
end
end

require 'active_record'
Expand Down
14 changes: 6 additions & 8 deletions lib/sql_enum/class_methods.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
module SqlEnum
module ClassMethods
def sql_enum(column_name, options = {})
# skip redefinitions
return if defined_enums.key?(column_name.to_s)

# Query values
enum_column = EnumColumn.new(table_name, column_name)
values_map = enum_column.values.to_h { |value| [value.to_sym, value.to_s] }
Expand All @@ -14,20 +17,15 @@ def sql_enum(column_name, options = {})

# Override reader to return symbols
type_definition = ->(subtype) { EnumType.new(attr, send(column_name.to_s.pluralize), subtype) }
case method(:decorate_attribute_type).arity
when 2 # Rails 5.1, 5.2, 6.0
decorate_attribute_type(column_name, :enum, &type_definition)
else
decorate_attribute_type(column_name, &type_definition)
end
attribute(column_name, &type_definition)

prefix_str = format_affix(column_name, prefix, suffix: '_')
suffix_str = format_affix(column_name, suffix, prefix: '_')

# Fix query methods to compare symbols to symbols
values_map.each_value do |value|
method_name = "#{prefix_str}#{value}#{suffix_str}"
define_method("#{method_name}?") { self[column_name] == value.to_sym }
method_name = "#{prefix_str}#{value}#{suffix_str}?"
define_method(method_name) { self[column_name] == value.to_sym }
end
end

Expand Down
2 changes: 1 addition & 1 deletion lib/sql_enum/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module SqlEnum
VERSION = "0.4.0"
VERSION = "1.0.0"
end
13 changes: 13 additions & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
require "sql_enum"

require 'debug'
require "awesome_print"

Dir['spec/support/**/*.rb'].each { |f| require File.expand_path(f) }

Expand All @@ -15,4 +16,16 @@
config.expect_with :rspec do |c|
c.syntax = :expect
end

# allow "fit" examples
config.filter_run_when_matching :focus
config.include DefineConstantMacros

config.before(:all) do
ActiveRecord::Base.establish_connection(ENV.fetch('DATABASE_URL'))
end

config.after do
clear_generated_tables
end
end
4 changes: 1 addition & 3 deletions spec/sql_enum_spec.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
require 'spec_helper'

RSpec.describe SqlEnum do
it "has a version number" do
expect(SqlEnum::VERSION).not_to be_nil
Expand All @@ -11,12 +9,12 @@

before do
SqlEnum.configure { |config| config.default_prefix = true }

define_model('Task',
status: [:enum, limit: statuses, default: 'pending'],
priority: [:enum, limit: priorities]) do
sql_enum :status
sql_enum :priority, _prefix: false, _suffix: true
sql_enum :status # duplicate should be no-op
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a way to directly test that this is in fact a no-op? I'm worried about the possibility of someone re-declaring using different options, then not understanding why their declaration doesn't work.

In fact, should this raise?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Open to suggestions, this was from @dpep's PR, so maybe he wants to opine...

end
end

Expand Down
12 changes: 0 additions & 12 deletions spec/support/macros/define_constant.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,3 @@ def created_tables
@created_tables ||= []
end
end

RSpec.configure do |config|
config.include DefineConstantMacros

config.before(:all) do
ActiveRecord::Base.establish_connection(ENV.fetch('DATABASE_URL'))
end

config.after do
clear_generated_tables
end
end
Loading