sauliusgrigaitis / Swifton

A Ruby on Rails inspired Web Framework for Swift that runs on Linux and OS X
MIT License
1.97k stars 70 forks source link

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

Open zmeyc opened 8 years ago

zmeyc commented 8 years ago

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?

sauliusgrigaitis commented 8 years ago

@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.

zmeyc commented 8 years ago

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

sauliusgrigaitis commented 8 years ago

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 commented 8 years ago

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.

joedaniels29 commented 8 years ago

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 commented 8 years ago

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
    }
sauliusgrigaitis commented 8 years ago

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.

joedaniels29 commented 8 years ago

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 commented 8 years ago

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.