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

argument constraints and coercions #77

Open
jjn1056 opened this issue Jan 8, 2015 · 5 comments
Open

argument constraints and coercions #77

jjn1056 opened this issue Jan 8, 2015 · 5 comments
Labels
Milestone

Comments

@jjn1056
Copy link
Member

jjn1056 commented Jan 8, 2015

more later

@jjn1056
Copy link
Member Author

jjn1056 commented Jan 8, 2015

So the idea right now is something like (for the simple case)

Package MyApp::Controller::Root;

sub myaction :Local Args(Int) {
my ($self, $c, $int) = @_
}

and the arg would not match if it was not an Int.

This would probably use types registered into moose, or into a project namespace (being able to do with with Type::Tiny would be ideal). Furthermore which could allow that a constraint has coercions in the what that Moose and Type::Tiny allow so that the following would also work:

package MyApp::Controller::Root;

sub myaction :Local Args(User) {
my ($self, $c, $user) = @_;
}

where $user is a MyApp::Schema::Result::User (a row in the database basically)

the idea is that we allow Catalyst to register Types (instances or classes of the defined models) and add coercions to them so that you could coerce an Integer to a DBIC::Result. In this case if the coerce failed to produce the expected type, the action would not match.

Would remove a lot of boilerplate I think and possible advance the conversation on how we are going to improve Catalyst IOC and related features.

Since the coercions could be more complex than one arg we'd probably need a syntax like Args(User{2},...)

In the above case if the coerce fails that would mean the action does not match. so you'd do like

sub found :Path(user) Args(User) {
my ($self, $c, $user) = @_;
}

sub not_found :Path(user) Args(Id) {
my ($self, $c, $id) = @_;

handle not found the $id in the DB

}

the question is the best approach to handle the coercions. Would it be enough to have a ->coerce_from or similar method on the model or should we define a type of 'type library and coercion library' (see type::tiny and all the related moose stuff.

I don't want this to get too complex but I do want people to keep in mind I'd like to see something like this workable for query and post params as well, and possible even in the body response (return a DBIC row, coerce it to a string body, for example. That's down the road but its good to keep in mind.

@jjn1056 jjn1056 added this to the australorp milestone Jan 8, 2015
@jjn1056
Copy link
Member Author

jjn1056 commented Jan 8, 2015

another thing this could be used to provide people with 'regexp' style Args, to stop the complaining since we removed Regexp!

@jjn1056 jjn1056 changed the title argument constraints and coercsion argument constraints and coercions Jan 8, 2015
@jjn1056
Copy link
Member Author

jjn1056 commented Jan 8, 2015

So for another take on this, it was suggested to skip the subroutine attributes approach and use a keyword (or keyword + method) signature approach (see Kavorka, Moops).

concepts /examples

action myaction under(..) args(Int $id, Date $date) {
$c->log->debug($id, $date);
}

such that would match .../100/01-jan-2014 for example

2:33 PM and if you don't want them put into @_, args(Int $, Date $)

method myaction(User $user) under(...) args(int $, Date $) {
my ($self, $user) = @_;
}

2:38 PM not sure what 'User $user' would do, but assuming that's the DI (Dependency Injection, sic) trigger
t2:39 PM yeah User $user would be like my $user = $c->model('User')
2:40 PM and we'd allow for a MyApp::Model::User that did ACCEPT_CONTEXT and declare its initialization argument types so that we'd attempt to to DI from existing models.
2:40 PM it would be a small addition to Catalyst::Component to declare the dependencies I think

Concerns I have with the approach include that after reviewing the examples on CPAN it feels like a lot more effort and additional would require dependencies that don't have a solid pass rate (for example Kavorka use Keyword::Parse which is marked deprecated with known issues and has a fail to pass it own test rate of >5% In general we aim for 99%+ pass rate on Catalyst tests. Upsides include a definitive step away from subroutine attributes (which are widely despised) and the possibility of a more concise and elegant syntax.

@jjn1056
Copy link
Member Author

jjn1056 commented Mar 2, 2015

some notes from chat

1:24 PM @mst what I reckon you could do is
1:24 PM @mst :Query(foo, bar, baz) # required params
1:25 PM @mst :Query(foo, bar, baz => Optional) # duh
1:25 PM @mst now you can do
1:25 PM @mst :Query(foo => Str, bar => Int)
1:25 PM @mst once you've got that
1:25 PM ⇐ @abraxxa quit (~[email protected]) Quit: Leaving.
1:25 PM @mst :Posted(object => UserHashRef) comes basically for free
1:25 PM @mst and the userHashRef is probably re-used anyway
1:27 PM where UserHashRef would be a custom Type::Tiny created and registered with the TT registry?
1:29 PM @mst I'd have it being something in a MyApp::Types
1:29 PM I'd probably would like, just to be consistent, to allow Arg(Int, Str) / CaptureArgs(Int, Str) and maybe even Args( Int, *)
1:29 PM @mst remember TT is MX::Types-like to start with
1:29 PM @mst rather than doing the global registry crap
1:30 PM right, actually I was thinking MyApp::Types would be looked for to load and install custom application types
1:30 PM and there could possibly be a Catalyst::Types for global ones
1:30 PM if needed
1:32 PM the only reason I was thinking about the type registry is I'd eventually like to be able to create type constraints automatically when a model is created, although perhaps I can have that without resorting to the registry
1:33 PM because for my long term plan I'd like to have types associated with for example DBIC result sources that get loaded via the common Catalyst DBIC model
1:34 PM @mst ok but that's orthogonal, don't get it all over designing this bit :)

@jjn1056
Copy link
Member Author

jjn1056 commented Jul 8, 2015

completed for Args and CaptureArgs. the rest is on hold

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant