-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow Invalid Values to be Converted to nil (optional) #46
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -133,6 +133,60 @@ Migrating shouldn't be that difficult though. `UUIDTools::UUID` implements | |
by default. But it's good to be aware of this in case you're running into | ||
weirdness. | ||
|
||
## Invalid Values | ||
|
||
By default, this will raise an exception if an invalid value is attempted to be stored. | ||
However, the PostgreSQL driver nils invalid UUID values. | ||
To get PG-friendly behavior, pass in the option `:nil_invalid_values => true` when creating the attribute. | ||
|
||
Additionally, as a convenience function, you can add the following to `ApplicationRecord` to get parity between PG and MySQL: | ||
|
||
``` | ||
def self.uuid_fields(*fields) | ||
if ActiveRecord::Base.connection.adapter_name.downcase.starts_with?("mysql") | ||
fields.each do |fld| | ||
attribute fld, MySQLBinUUID::Type.new(:nil_invalid_values => true) | ||
end | ||
end | ||
end | ||
``` | ||
|
||
Then, in your models, just begin them by marking the fields which are UUIDs. | ||
|
||
## UUID Type in migrations | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would like to leave this out as it was intentionally not included with this gem. It's nice of you though to inform people how they could achieve this. I'd propose moving the example code you wrote into a Gist, and link to it in a new final line of the
|
||
|
||
To get a UUID type in a migration, add the following to your initializers (Rails 7 specific): | ||
|
||
``` | ||
require "active_record" | ||
require "active_record/connection_adapters/mysql2_adapter" | ||
require "active_record/type_caster/map" | ||
|
||
module ActiveRecord | ||
module ConnectionAdapters | ||
module MySQL | ||
module ColumnMethods | ||
def uuid(*args, **options) | ||
# http://dba.stackexchange.com/questions/904/mysql-data-type-for-128-bit-integers | ||
# http://dev.mysql.com/doc/refman/5.7/en/binary-varbinary.html | ||
args.each { |name| column(name, "varbinary(16)", **options.merge(limit: 16)) } | ||
end | ||
end | ||
module SchemaStatements | ||
def type_to_sql(type, limit: nil, precision: nil, scale: nil, size: limit_to_size(limit, type), unsigned: nil, **) | ||
if type.to_s == "uuid" | ||
return "varbinary(16)" | ||
else | ||
super | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end | ||
|
||
ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter::NATIVE_DATABASE_TYPES[:uuid] = {:name => "varbinary", :limit => 16} | ||
``` | ||
|
||
# Known issues | ||
* With Rails 5.0 in combination with uniqueness validations, ActiveRecord | ||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -2,6 +2,12 @@ module MySQLBinUUID | |||||||||||||||||||||||||||||||||
class InvalidUUID < StandardError; end | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
class Type < ActiveModel::Type::Binary | ||||||||||||||||||||||||||||||||||
attr_accessor :options | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
def initialize(opts = {}) | ||||||||||||||||||||||||||||||||||
self.options = opts | ||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||
Comment on lines
+5
to
+9
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I really like to have default options available, also as an opportunity to see which options there are and what their default values are.
Suggested change
|
||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
def type | ||||||||||||||||||||||||||||||||||
:uuid | ||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||
|
@@ -34,6 +40,7 @@ def serialize(value) | |||||||||||||||||||||||||||||||||
# does not explicity escape the Binary data type. escaping is implicit as | ||||||||||||||||||||||||||||||||||
# the Binary data type always converts its value to a hex string. | ||||||||||||||||||||||||||||||||||
unless valid_undashed_uuid?(undashed_uuid) | ||||||||||||||||||||||||||||||||||
return nil if options[:nil_invalid_values] | ||||||||||||||||||||||||||||||||||
raise MySQLBinUUID::InvalidUUID, "#{value} is not a valid UUID" | ||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you move this to as a section under
# Usage
(after## Tell your model how to handle..
) please? I think we could just describe the options there, but don't need to specifically mention parity between Postgres and MySQL: