-
Notifications
You must be signed in to change notification settings - Fork 13
Fixed select(), implemented pluck(), ids(), reselect(), none() #69
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
Fixed select(), implemented pluck(), ids(), reselect(), none() #69
Conversation
…at capitalization for attribute names are retained. So the short form for New York is now NY instead of ny. test/model/Author, Book, and Venue now have those strtoupper() workarounds in getter/setter methods removed as it's done in Model.php
…rcased in Model.php in order to be case insensitive.
…at capitalization for attribute names are retained. So the short form for New York is now NY instead of ny. test/model/Author, Book, and Venue now have those strtoupper() workarounds in getter/setter methods removed as it's done in Model.php
…rcased in Model.php in order to be case insensitive.
# Conflicts: # lib/Model.php
…cord # Conflicts: # test/ActiveRecordTest.php # test/models/Book.php
…Disable it so that regression does not timeout.
…d#35: Authors table now has a column that is camel cased: firstName Added tests that demonstrate case insensitivity when accessing this firstName column
- Correct link to contributing.md
…vity() is enough.
…cord # Conflicts: # composer.json # scripts/TestCommand.php
test/RelationTest.php
Outdated
|
||
public function testSelectChainedSelects() | ||
{ | ||
$relation = Author::select('name,name')->select('author_id'); |
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.
Looking at this test, it's not clear to me what the bug is you're fixing. I'm not saying you're wrong, just that it's not clear. For starters, using reflection to dip into internals as proof that there is a problem is sort of breaking the rules. If you want to show a problem, do it with publicly available means. For instance:
$author = Author::select('name,name')->take();
$this->assertEquals(['name' => 'Tito'], $author->attributes() );
This is why I suggested starting with a failing test case for us to look at before diving in. Recommend starting a new branch that has a single failing test case, preferably performed without the kind of introspection you're doing here. Once we understand the situation better, we can talk about what the fix is.
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.
Hopefully the new commit explains things better. It prevents:
SELECT name, name
FROM Author
and
SELECT name, *
FROM Author
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.
Okie-doke, then 👍
…cord into RelationMagicFunctionsAndSelectFix # Conflicts: # lib/Model.php # lib/Relation.php
- Implemented testReselect
…Test.php and ActiveRecordFindTest.php
- Fixed select() gets clobbered by count()
Codecov Report
@@ Coverage Diff @@
## master #69 +/- ##
============================================
+ Coverage 96.17% 96.26% +0.09%
- Complexity 936 962 +26
============================================
Files 33 33
Lines 2274 2330 +56
============================================
+ Hits 2187 2243 +56
Misses 87 87
📣 We’re building smart automated test selection to slash your CI/CD build times. 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.
Looking pretty good. 👍
lib/Model.php
Outdated
@@ -1751,7 +1774,14 @@ protected static function Relation(array $options = []): Relation | |||
*/ | |||
public static function count(/* ... */): int | |||
{ | |||
return static::Relation()->count(...func_get_args()); | |||
$relation = static::Relation(); |
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.
If you're going to do any work, please delegate to Relation
, like we do everywhere else.
And didn't we remove support for passing conditions to count
? I don't see any mention of that in the modern rails documentation:
https://apidock.com/rails/v5.2.3/ActiveRecord/Calculations/count
What prompted this change?
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.
Backwards compatibility for version 1. What I had in my original PR was Model::find()
would have the complex support for version 1 parameters, and Relation::find()
would only support what's in modern Ruby. If you want to break every single user of version 1 (ie: all of us) in version 2, then this is no longer necessary. The users of version 2 would do Model::where(complex input stuff)->count()
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.
if someone wants to start a 1.x legacy branch and start back-porting fixes then that's up to them, but otherwise I'm not interested in bc; this API is confusing enough without muddying things further. Once we have our shiny new 2.x line, we will be more careful going forward.
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.
Oh, so that's why you removed all those version 1 tests and threw away the code I wrote in my original PR to be version 1 compatible. If that's not a design goal, then that simplifies implementation, but will probably upset the entire version 1 user base as everybody will need to change their code. But that's the meaning of going from version 1 to 2. It was possible to keep backwards compatibility like I showed for count(). Anyway, removed backwards compatibility.
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.
Yeah, sorry about that, but even if we did keep passing where clauses to find
and count
it still wouldn't make v2.0 compatible with 1.x (because, for example, I moved us away from mixed-array association configurations in the interest of static checking). I guess what we could do is find the earliest point in the commit history where all the tests pass and tag it with 1.2, or something, but we would have to revert the config changes, and I just don't have the energy. Feel free to volunteer, though.
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.
We could look at cc36507 as a potential 1.2 release. I'll try it out in my own codebase at some point and see what happens.
* | ||
* @param string $propertyName Supports only first|last|take | ||
* Returns a blank Relation and fires no queries. Any subsequent call to find(), to_a(), last(), first() returns [] | ||
*/ |
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.
Return 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.
It's there, but put in doc block too now
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 think you want one of these:
* @returns Relation<TModel>
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.
Bump.
$this->options['select'] = array_merge((array) $this->options['select'], (array) $arg); | ||
$columns = array_merge((array) $this->options['select'], $columns); | ||
|
||
return $this->reselect($columns); |
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'm not sure what you mean here. The performance hit one way or another for manipulating short arrays in memory pales in comparison to the actual database hit. So, if performance is concern here, this is not likely going to make a visible difference when using this library. Turning SQL statements would make a much more important improvement in speed.
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 saying you can't collapse the SELECT statements, I'm saying you should do it in the same place the rest of this kind of work happens, in Table::options_to_sql
. Then it's all in one place, and people working with the debugger will be less likely to fall victim to the principle of least surprise. And no, it probably won't amount to much of a performance savings, but that's not exactly a reason not to do it.
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.
If you're still not convinced we don't have to let it hold up this PR, but be warned that I will likely move things around soon after.
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 gone for the weekend, so please feel free to do that. I'm glad we could get this merged before I leave.
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.
Fixed in #77
test/ActiveRecordSelectTest.php
Outdated
$this->expectException(UndefinedPropertyException::class); | ||
$author = Author::select('name')->reselect('author_id')->first(); | ||
$author->name; | ||
$this->fail('expected ActiveRecord\UndefinedPropertyExecption'); |
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 don't think you need this line; as a matter of fact, I think they can likely all be removed.
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've copied and pasted $this->fail('expected ActiveRecord\UndefinedPropertyExecption');
from other tests, but didn't know what they were there for. Removed.
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.
Yeah, that's my fault, I added all those expectException
lines, but didn't catch all the fail
calls. Thanks much.
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.
Thanks for clarifying.
I tracked the other extraneous $this->fail() functions and removed them in the latest commit
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.
Thanks much.
Awesome, thanks! |
Fixed bugs in
select()
related to repeated column names. SeeRelationTest::testSelectChainedSelects()
for more details.Implemented magic getters for
Relation->last
,first
, andtake
so that you don't have to use parentheses like$relation->last()
. Ruby on Rails supports this syntax, and now so do we.Unfortunately,
Model::last
cannot be implemented because PHP has not implemented a__getStatic($name)
magic function yet, only__get($name)
, so this is one example where we cannot by fully compliant to the RoR spec because of differences between PHP and Ruby.