Skip to content
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

added query macro, tests, and docs #215

Merged
merged 4 commits into from
Jun 6, 2018

Conversation

noahlh
Copy link
Contributor

@noahlh noahlh commented May 23, 2018

This PR (#184 & #200) allows you to customize the SQL used in the SELECT portion of the query (or the entire query if necessary) by adding the query macro.

The major limitation is that when using a highly-modified query, the save/update functionality of the model will likely break. In the issue @drujensen suggested taking a more complete View Model approach, and I agree with that entirely, but wanted to start with a slightly narrower scope. So this is "View Model Lite". Baby steps. Likewise, find may also break depending on how the query is modified.

Also, naming is hard. I'm not wedded to any of the names used, and particularly with things like Query, Select, etc., things might get complex.

(PS - Please feel free to rip to shreds :) I'm new to this type of contribution so am eager to learn & improve in both style and substance. Happy to make as many changes as needed.)

Copy link
Member

@robacarp robacarp left a comment

Choose a reason for hiding this comment

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

Good start, I like the idea of supporting a viewmodel. I wonder if it should be a subclass of Base instead of a dedicated base class itself?

@@ -0,0 +1,21 @@
module Granite::Select
struct Container
Copy link
Member

Choose a reason for hiding this comment

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

Could this be called a fieldset?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's not so much a set of fields as it is a (loose) container for the query (or SELECT) statement. Granite::Query is used in your new query builder, so I tried to capture this as simply as possible. I don't love Granite::Select::Container though. Open to ideas.

Copy link
Member

Choose a reason for hiding this comment

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

Sure Container is a little vague, but is it going to show up in an Amber devs code? If not, I don't think it's important to be 100% on target for merging this.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Makes sense. No, the only dev interface is the query macro, so not a big deal here.

module Granite::Select
struct Container
property custom
getter table_name, fields
Copy link
Member

Choose a reason for hiding this comment

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

Since you’re target is to support multiple tables, shouldn’t each field have a paired table?

Copy link
Member

@drujensen drujensen May 28, 2018

Choose a reason for hiding this comment

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

@robacarp there may be no tables or they may be fields that are calculated. When this is a custom query, the table_name will not have any meaning.

What I think may be a bigger issue is all of the transactional methods are still included when a custom query is provided. These methods should be excluded like save and destroy or at least throw runtime exceptions if you attempt to use them. But it would be better to catch these at compile time.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@drujensen Agreed. I think the next step (and I'll write up an issue to discuss this) is to go with your original suggestion in #184 and fully break this out into a ViewModel, which will eliminate the transactional methods (and, hence, no need for compiler check).

stmt << " FROM #{quote(table_name)}"
stmt << " WHERE #{quote(field)}=:id LIMIT 1"
def select_one(query : Granite::Select::Container, field, id, &block)
if query.custom.size > 0
Copy link
Member

Choose a reason for hiding this comment

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

change custom to a nil-able property and do not initialize it to "". property custom : String? Then check for nil here instead of size

Copy link
Member

Choose a reason for hiding this comment

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

I think you can get rid of the if blocks with initial_statement = query.custom || String.build do |stmt|

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Great - thank you for suggestions. Done and done.

Copy link
Member

@drujensen drujensen left a comment

Choose a reason for hiding this comment

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

Excellent PR. 👍 Some minor corrections requested.

@robacarp robacarp dismissed drujensen’s stale review June 6, 2018 20:56

@drujensen I believe your concerns were addressed

Copy link
Member

@drujensen drujensen left a comment

Choose a reason for hiding this comment

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

💯

@drujensen drujensen merged commit 757140b into amberframework:master Jun 6, 2018
@faustinoaq faustinoaq removed the pr:wip label Jun 6, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants