-
Notifications
You must be signed in to change notification settings - Fork 88
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
Support custom field types #342
Conversation
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.
lgtm 💯
Ok. I’m fine with it the way it is.
… On Jun 16, 2019, at 10:22 AM, Blacksmoke16 ***@***.***> wrote:
@Blacksmoke16 commented on this pull request.
In src/granite/converters.cr:
> @@ -0,0 +1,11 @@
+module Granite::Converters
Hmm, I dunno. That seems like a lot more work than just adding a , converter: Granite::Converters::UuidConverter to the field.
—
You are receiving this because your review was requested.
Reply to this email directly, view it on GitHub, or mute the thread.
|
Currently planning on implementing the following converters:
Any others you think that would be helpful? |
@Blacksmoke16 Sounds like a good plan. We can always add more converters later. |
@drujensen What are your thoughts on how we should handle the different return values from each DB driver? I.e. PG returns I'm thinking we can:
Option 1 would have the most flexibility, but also the most converters. |
I’m leaning toward option 1. It seems the most flexible.
… On Jun 18, 2019, at 6:18 PM, Blacksmoke16 ***@***.***> wrote:
@drujensen What are your thoughts on how we should handle the different return values from each DB driver? I.e. PG returns JSON::Any for its JSON(B) types, but SQLite just returns a string, which messes up the read.
I'm thinking we can either:
Have global converters to handle each case, i.e. BinaryJson, StringJson, Json, for Bytes, String, and JSON::Any.
Namespace the converters by driver, which gets included when including that adapter. i.e. Granite::Converters::PG::Json.
Similar to 2, but only support driver specific types, i.e. for PG, only support JSON(B) types, and not String or BYTEA types; for SQLite support String/Blob.
Option 1 would have the most flexibility, but also the most converters.
Option 2 would mostly be 3 near identical sets based on option 1.
Option 3 would have the least amount of duplication, but also the least flexible.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.
|
Is there a way to get rid of the large case statement to perform type conversions using a set of converters?
… On Jun 18, 2019, at 6:27 PM, Dru Jensen ***@***.***> wrote:
I’m leaning toward option 1. It seems the most flexible.
> On Jun 18, 2019, at 6:18 PM, Blacksmoke16 ***@***.***> wrote:
>
> @drujensen What are your thoughts on how we should handle the different return values from each DB driver? I.e. PG returns JSON::Any for its JSON(B) types, but SQLite just returns a string, which messes up the read.
>
> I'm thinking we can either:
>
> Have global converters to handle each case, i.e. BinaryJson, StringJson, Json, for Bytes, String, and JSON::Any.
> Namespace the converters by driver, which gets included when including that adapter. i.e. Granite::Converters::PG::Json.
> Similar to 2, but only support driver specific types, i.e. for PG, only support JSON(B) types, and not String or BYTEA types; for SQLite support String/Blob.
> Option 1 would have the most flexibility, but also the most converters.
> Option 2 would mostly be 3 near identical sets based on option 1.
> Option 3 would have the least amount of duplication, but also the least flexible.
>
> —
> You are receiving this because you were mentioned.
> Reply to this email directly, view it on GitHub, or mute the thread.
|
Probably yea. But prob best for another PR. I'm thinking you would lose some flexibility though, but I'd be ok with that. I.e. you couldn't pass EDIT: Well maybe you could, have think about it more. |
@drujensen One thing I thought of that would help cut down on the amount of duplication, would be to have the user provide the type that should be read from the column.
Then you would have a singular module Json(T)
{% if T == String %}
# Add from_rs/to_db methods that go to/from a String
{% elsif T == JSON::Any %}
# Add from_rs/to_db methods that go to/from JSON::Any
{% elsif T == Bytes %}
# Add from_rs/to_db methods that go to/from Bytes
{% else %}
{% raise "#{{{@type.name}}} does not currently support #{T}" %}
{% end %}
end Is still going to be some duplication, but this would at least limit the total number of converters and keep the code centralized. |
@Blacksmoke16 Yes, good idea. Another option is having just one converter that supports a Union of |
Hmm, I'll have to try that how to see how it works with |
@drujensen I tested it out, it worked pretty good for the reading from the db, however you wouldn't really have a way to know what to do with the value on save. I.e. for an enum, should I call But as it seems, I don't have access to the generic type in macro land either :/ EDIT: module Enum(E, T)
extend self
def self.to_db(value : E?) : Granite::Fields::Type
return nil if value.nil?
{% if T <= Number %}
value.to_i
{% elsif T == String %}
value.to_s
{% else %}
{% raise "#{@type.name}#to_db does not support #{T} yet." %}
{% end %}
end
def self.from_rs(result : ::DB::ResultSet) : E?
value = result.read(T?)
return nil if value.nil?
{% if T <= Number %}
E.from_value? value
{% elsif T == String %}
E.parse? value
{% else %}
{% raise "#{@type.name}#from_rs does not support #{T} yet." %}
{% end %}
end
end This will work pretty good tho. |
Require the user to provide the type that should be read from the RS for each converter Add specs for each converter/driver
Add spec for to/from for each type
@drujensen @robacarp This should be good for final review. EDIT: Can review but I need to update docs first before merging if everything looks good. EDIT2: Docs are updated. |
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.
Nice! 💯
@amberframework/contributors Any other feedback? If not, I will merge. |
Initial pass at supporting custom DB types. Resolves #193 and resolves #152.
UUID
,Enum
,JSON
, andPG::Numeric
.PG::Numeric
intoFloat64
, or aString
into an actualUUID
object when saving/reading from the DB.TODO:
Update docs