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
Association improvements #375
Conversation
else | ||
nilable_method = name + "?" | ||
not_nil_method = name | ||
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.
I am finding this very confusing.
If I declare the type as nilable (using a question mark), then I get the default name
as nilable and an extra getter name!
as not nilable.
If I declare the type as not nilable (without a question mark), then I get the default option name
that is not nilable and a name?
that is nilable.
Is this what you would expect?
Maybe we always include a ?
option as nilable and a '!' as not nilable for both cases. The default would be based on the declaration, but you could override the default by using these options. wdyt?
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.
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.
I see, I agree they are redundant, but easy to remember. I guess if you get an error, you will remember that you declared it one way of the other.
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.
Related to #370. I'm fine with this for the mean time as it fits with the current setup. However, would like to reach a decision on that PR, which makes things more crystal like id argue versus having to do field!
for not nilable.
end | ||
@[JSON::Field(ignore: true)] | ||
@[YAML::Field(ignore: true)] | ||
@{{name}} : {{type}}? |
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.
I'm not sure how I feel about the caching side of this yet. I don't like that the ivar is hidden away and can't be altered, via annotations for example. I'm also not sure about this being the default behavior. I thought about caching a while ago and my thought was the query itself should be cached, so that an extra ivar doesn't have to be added to the model.
EDIT: I'd also like to see some sort of interface around how caching should be done, where this would be an implementation of that, like InMemoryCache
. Other examples could include like a Hash
, or Redis
, etc.
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.
@Blacksmoke16 Another purpose of this PR is to solve the N + 1 problem, which cannot be solved by caching the query.
There may be another better approach, but the best way I came up with is this.
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.
There may be another better approach, but the best way I came up with is this.
I'd rather hold off on this change and discuss alternative solutions. In its current state this PR would not play well with any third party serializer. If anything it should be an opt in feature via a module or something.
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.
@Blacksmoke16 I see your concern regarding serialization and agree that we should find another alternative approach.
@c910335 I am wondering if we need the parent query to include the children records. Would that solve the N+1 and allow the db to perform caching?
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.
@drujensen
Something like this.
SELECT * FROM `children` WHERE `children`.`parent_id` IN ('2', '3', '5', '7', '11');
Then assign each child to the instance variable of its parent in Crystal.
62cd978
to
eaf1834
Compare
Another benefit of this PR is that it can return deleted associations if you cache them before deleting. |
Just added |
I like the feature, but not the implementation:
|
support nilable like column cache parent
support nilable like column cache child
cache children
55dd999
to
e961a57
Compare
Closing this until a better alternative for caching is implemented. |
Breaking Changes
column
.getter
andgetter?
for not nil type;getter!
andgetter
for nilable typebelongs_to
andhas_one
(sincehas_many
simply returns empty collection if not found)#reload_{{name}}
to reload#{{name}}.reload
forhas_many