Skip to content

Conversation

@shmax
Copy link
Contributor

@shmax shmax commented Sep 10, 2023

Description

This is a first pass at aligning more closely with modern Active Record, based on this PR by @ipundit

The broad strokes are that you can now chain relational commands together:

$book = Book::where(['title = ?", "Green Eggs and Ham"])->order("title")->first();
$books = Book::first([1,2,3]);
$books = Book::all()->to_a();
$book = Book::select('name')->find(1);
$book = Book::take();

There are a number of major breaking API changes. Briefly:

  • find_all_by_... -style magic methods have been removed.
  • find no longer takes an options array. The only valid arguments now are primary keys, or arrays of primary keys ("first" and "last" arguments are also no longer supported).
  • count_by_...-style magic methods have been removed.

Other changes:

  • renamed Expression to WhereClause
  • Did a pass at setting up Generics (via PHPStan), so Relation can properly return whatever subclass of Model it is working with. Same for Table.
  • Encoded rules for dynamic return types (ie first, last, find) into PHPStan extensions.

TODO

  • Relation needs to implement iterable, so we can use it with foreach
  • need to flesh out select, include, group, etc
  • need to do another pass on documentation
  • not sure if there are or will be any methods that allow a user to type out a big options object, eg:
      $res = Book::everything([
       "order" => "title,
       "limit" => 4,
       "conditions" => [
        "title" => "Walden"
       ]
      ]).to_array();

Is that a thing? If it is, I'll need to be careful about how I'm handling "conditions" (internally, I push instances of WhereClause).

ipundit added 30 commits August 31, 2023 18:10
…n 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.
…n 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.
…cord

# Conflicts:
#	test/ActiveRecordTest.php
#	test/models/Book.php
…Disable it so that regression does not timeout.
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
…cord

# Conflicts:
#	composer.json
#	scripts/TestCommand.php
…cord into RubyLikeFind

# Conflicts:
#	composer.json
#	scripts/TestCommand.php
@ipundit
Copy link
Contributor

ipundit commented Sep 11, 2023

I've done a quick review of this large PR. Good job! That was a lot of work. A spec issue that comes to mind is when clauses are repeated. Should:

Author::select('A')->select('B')->find

select only B (this is what currently happens), throw an error, or select columns A and B?

But repeated where clauses act differently:

Author::where('A')->where('B')->find

it does where('A and B'). But why the inconsistency with select which replaces A with B? This should be specified in the documentation.

A similar reasoning and documentation exercise would have to be done for having, group, include, from, and all the other $VALID_OPTIONs that we have.

@ipundit
Copy link
Contributor

ipundit commented Sep 11, 2023

I think that we should also put into the readme.md file that the goal of this project is to implement Ruby on Rails version v as faithfully as possible with exceptions a, b, c, d, etc... What is v? I think it's version 4, but am unsure. It depends how far you want to go before releasing this time around.

@shmax
Copy link
Contributor Author

shmax commented Sep 12, 2023

select only B (this is what currently happens), throw an error, or select columns A and B?

Great question. I checked out Rails in the debugger, and it definitely collects multiple select statements, and also supports arrays of field names, so I made the same change, here: aaf8c0d

We should probably also support doing variadic lists, like:

Book::select("name", "publisher)->take();

But let's revisit that kind of thing in a future PR.

@shmax
Copy link
Contributor Author

shmax commented Sep 12, 2023

A similar reasoning and documentation exercise would have to be done for having, group, include, from, and all the other $VALID_OPTIONs that we have.

If you're ready to get back to coding, it would be great if you could help out with that effort. I think most of our implementations of these features are a bit undercooked, and I just don't have the energy to go through them all right now.

@shmax
Copy link
Contributor Author

shmax commented Sep 12, 2023

Implemented Relation::not: 8113e26

@shmax shmax merged commit d59e14a into master Sep 12, 2023
@shmax shmax deleted the refinement branch September 12, 2023 15:51
@shmax
Copy link
Contributor Author

shmax commented Sep 12, 2023

@ipundit Thank you so much for all the great review comments.

I know you still have a few ideas about how to do things, but rather than circle around this PR forever I went ahead and merged it so you can resume making your own direct contributions.

There are a number of TODO items:

  • revisit some of the new chaining methods (select, include, limit, group, etc), make them a bit more robust and inline with RoR, and improve documentation
  • continue work on tests (I think the DatabaseTest ones are broken, in that setUp doesn't seem to do anything)
  • implement iterator support for Relation (I'm working on that one now)
  • start testing this out in real world code (maybe draft an RC release?)

Or whatever you like. Thanks again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants