RejectedSoftware Forums

Sign up

Pages: 1 2

Re: How to organize a large router and corresponding functions

On Mon, 13 Jul 2015 07:32:17 GMT, Taylor Gronka wrote:

source/views/user.d:

module bolt.views.user;
class UserViews {
	protected void register(HTTPServerRequest req, HTTPServerResponse res)
	{
        bks.addUser(req.form);
        res.render!("user/register.dt", req);
}

bolt.d:

module bolt.bolt;
import bolt.views.user;
class Bolt {
    private {
        auto USER = new UserViews;
        bks = new CassaClient("127.0.0.1", 9042, "bolt");
    }
...
    void register(URLRouter router) {
        router.get("register", $USER.register);
    }
}

Oh wait so.. this doesn't work.. I kind of didn't think it would. But I ran a test and got good results. Now I think I'm getting what I originally expected.. I must have made it mistake that made it look good.

Guess it's time to try threadlocal.

Re: How to organize a large router and corresponding functions

On Mon, 13 Jul 2015 04:40:20 GMT, Taylor Gronka wrote:

I didn't realize the chain of restrictions involving global/const/immutable, so I think that option is out.

I tried using the delegate function you recommended. Your example with passing a string worked. Then I tried to mass my custom struct RequestPass, stored in m_pass. These lines of code:

m_pass.bks = new CassaClient("127.0.0.1", 9042, "bolt");

router.get(m_subPath ~ "register", (req, res) => bolt.views.user.register(req, res, m_pass));

yielded this error:

source/bolt/bolt.d(77): Error: need 'this' for 'm_pass' of type 'RequestPass'

Replacing m_pass with this.m_pass yielded the exact same error. I'm not sure what to do differently. I thought it might be clever to try this

auto pass = &m_pass;
router.get(m_subPath ~ "register", (req, res) => bolt.views.user.register(req, res, *pass));

Which left me with this error.

source/bolt/bolt.d(80): Error: function bolt.bolt.Bolt.register.__lambda2 cannot access frame of function bolt.bolt.Bolt.register

Creating closures can sometimes indeed be tricky when nested scopes are involved, but I have troubles reproducing the errors above. What I have is this: http://dpaste.dzfl.pl/0804d5dbb52f

Is there anything structurally different from what you had?

I've tried many of times to write a delegate function out, but I keep failing. I feel like I need something like the following:

void delegate() dg = bolt.views.user.register(req, res, m_pass);

, or

auto dg = &bolt.views.user.register;

But my Bolt class has no access to req or res, so far as I can tell.. and my register function requires req and res.. so I've dropped that for the time being.

If you wanted to explicitly write it out, you could write this:

HTTPServerRequestDelegate dg =
    (req, res) => bolt.views.user.register(req, res);

But as you already noted, the req/res parameters still need to be passed through, because they differ for each call.

Now, I happened across a thing such as mixin(import("user.d")) which is less elegant, but would work great for me. But I'm getting this error for relative and absolute paths to files:

source/bolt/bolt.d(109): Error: file "user.d" cannot be found or not in a path specified with -J

If you just want to mix in code to your class, a slightly cleaner approach would be to use a mixin template:

// user.d
mixin template UserMethods() {
    void register(HTTPServerRequest req, HTTPServerResponse res)
    {
        // can use m_pass here
    }
}

// bolt.d
class Bolt {
    import bolt.views.user;
    mixin UserMethods!();

    void registerRoutes(URLRouter router)
    {
        router.get("/register", &this.register);
    }
}

Re: How to organize a large router and corresponding functions

On Mon, 13 Jul 2015 08:01:08 GMT, Sönke Ludwig wrote:

Creating closures can sometimes indeed be tricky when nested scopes are involved, but I have troubles reproducing the errors above. What I have is this: http://dpaste.dzfl.pl/0804d5dbb52f

Is there anything structurally different from what you had?

I adapted your code snippet into a simple vibe project called test:
dub init test vibe.d

In dub.json, seems to be using vibe-d 0.7.19

Here is app.d
https://gist.github.com/gronka/f16b52641de6e481caba

I'm getting the same error when I try to compile

source/app.d(35): Error: need 'this' for 'm_pass' of type 'RequestPass'

If you just want to mix in code to your class, a slightly cleaner approach would be to use a mixin template:

// user.d
mixin template UserMethods() {
    void register(HTTPServerRequest req, HTTPServerResponse res)
    {
        // can use m_pass here
    }
}

// bolt.d
class Bolt {
    import bolt.views.user;
    mixin UserMethods!();

    void registerRoutes(URLRouter router)
    {
        router.get("/register", &this.register);
    }
}

Oh - that actually looks great. What I didn't like about mixin(import()) is that I'm pretty sure it would become a huge pain to track down compiling/dependency errors.

Re: How to organize a large router and corresponding functions

On Mon, 13 Jul 2015 08:53:18 GMT, Taylor Gronka wrote:

On Mon, 13 Jul 2015 08:01:08 GMT, Sönke Ludwig wrote:

Creating closures can sometimes indeed be tricky when nested scopes are involved, but I have troubles reproducing the errors above. What I have is this: http://dpaste.dzfl.pl/0804d5dbb52f

Is there anything structurally different from what you had?

I adapted your code snippet into a simple vibe project called test:
dub init test vibe.d

In dub.json, seems to be using vibe-d 0.7.19

Here is app.d
https://gist.github.com/gronka/f16b52641de6e481caba

I'm getting the same error when I try to compile

source/app.d(35): Error: need 'this' for 'm_pass' of type 'RequestPass'

Interesting, seems like this may be a compiler bug where it tries to create a function instead of a delegate. When using any explicit "delegate" syntax, it suddenly works:

HTTPServerRequestDelegate del = (req, res) => doRegister(req, res, m_pass);
router.get("/register", del);
router.get("/register", delegate (req, res) { doRegister(req, res, m_pass); });

Maybe partial is the nicer syntax alternative, though.

Reduced case: http://dpaste.dzfl.pl/3d196916b8e3

Swapping the order of the two get overloads also fixes the issue. I'll search the D bug tracker for an existing bug report later.

Pages: 1 2