Swifton icon indicating copy to clipboard operation
Swifton copied to clipboard

Using plain methods in controller instead of actions() with closures

Open zmeyc opened this issue 8 years ago • 9 comments

I was thinking if it's possible to map routes directly to methods of Controller. For example:

router.get("/", TodosController().index)
etc

Resources can be implemented by adopting protocols. I.e. TodosController adopts Resource protocol and implements some or all of the protocol's methods. router.resources() will expect a class which adopts that protocol.

Filtering can be implemented by looking up method names via reflection.

What do you think of this approach?

zmeyc avatar Apr 13 '16 18:04 zmeyc

@zmeyc, thanks. Last time I checked reflection it was possible to lookup only attributes. Please open PR with your experiments, I'm open to ideas that are both easy to use (API close to Rails) and has better compile time checking than it is current implementation.

sauliusgrigaitis avatar Apr 13 '16 18:04 sauliusgrigaitis

I've experimented a bit and it seems that it's impossible to obtain method name using reflection. I've found a reference to _stdlib_getDemangledTypeName which could work, but I wasn't able to compile it: http://stackoverflow.com/questions/27912078/where-are-stdlib-gettypename-stdlib-getdemangledtypename-declared

zmeyc avatar Apr 13 '16 22:04 zmeyc

Most of these dynamic features are actually from ObjectiveC runtime, not from pure Swift. Swift currently is very static language with almost no dynamic features, so it's definitely not easy to build some framework that is easy to use (think Rails) and at same time offers compile time checks.

Let's keep this issue opened, maybe somebody comes with great solution.

sauliusgrigaitis avatar Apr 14 '16 09:04 sauliusgrigaitis

Another more safe way I was experimenting with - assign closures to attributes and then pass those attributes to filters, but I didn't feel it was good enough.

sauliusgrigaitis avatar Apr 14 '16 11:04 sauliusgrigaitis

Well, whats seems confusing is that if you override the controller() method without calling super then am I correct in assuming that you loose access to any filters/actions that you declared in the ApplicationController? If so, whats the point in extending ApplicationController?

joedaniels29 avatar Jul 26 '16 13:07 joedaniels29

Further, as convenience methods, would pull requests be accepted adding

    func index (handle:(Request)->(Response) ) {
        actions["index"] = body
    }

to allow users to write

    index() { req in
       //response
    }

joedaniels29 avatar Jul 26 '16 13:07 joedaniels29

Hi @joedaniels29, thanks for comments. Looks like documentation isn't up to date , tests actually calls super. Please feel free to open PR with documentation fix.

Also feel free to experiment with your ideas. The only issue I see with your actions suggestion is that it makes inconsistent actions - most likely an application will have more actions than those standard actions. So extra actions will still need full definition.

sauliusgrigaitis avatar Jul 26 '16 14:07 sauliusgrigaitis

Yup, Agreed. Though, in the interest of dryness, I'd recommend it. It will be easy enough to just misspell the standard CRUD routes and then have to track down what you messed up. It would make standards typesafe

joedaniels29 avatar Jul 26 '16 17:07 joedaniels29

its worth noting that though other frameworks (ie. vapor) are allowing regular method names, they're adding an extra compilation step to make it all work.

joedaniels29 avatar Aug 04 '16 13:08 joedaniels29