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

Router updates #299

Closed
wants to merge 15 commits into from
Closed

Router updates #299

wants to merge 15 commits into from

Conversation

j-mcnally
Copy link
Contributor

No description provided.

@j-mcnally
Copy link
Contributor Author

Updated this pull request to actually fix the router!

@lancejpollard
Copy link
Member

Hey, haven't been able to switch gears fully yet. I did pull the changes into a local branch but the client threw this error:

Uncaught Error: assertion failed: You must specify a target state for event 'indexPost' in order to link to it in the current state 'root.index'. 

I just generated a new app with the latest changes and a post model:

tower new app
cd app
npm link tower
npm install
# copy/paste the latest client dev into vendor/javascripts/tower.js
tower generate scaffold post title:string body:text
cake watch
node server

Will dig in further soon. Thanks for the PR!

@j-mcnally
Copy link
Contributor Author

I will look into this can u send me your routes coffee
On Sep 22, 2012 4:30 AM, "Lance Pollard" notifications@github.com wrote:

Hey, haven't been able to switch gears fully yet. I did pull the changes
into a local branch but the client threw this error:

Uncaught Error: assertion failed: You must specify a target state for event 'indexPost' in order to link to it in the current state 'root.index'.

I just generated a new app with the latest changes and a post model:

tower new app
cd app
npm link tower
npm install

copy/paste the latest client dev into vendor/javascripts/tower.js

tower generate scaffold post title:string body:text
cake watch
node server

Will dig in further soon. Thanks for the PR, makes things move fast!


Reply to this email directly or view it on GitHubhttps://github.com//pull/299#issuecomment-8787073.

@lancejpollard
Copy link
Member

# app/config/shared/routes.coffee
Tower.Route.draw ->
  @resources 'posts'
  # @match '(/*path)', to: 'application#index'
  @match '/', to: 'application#welcome'

@j-mcnally
Copy link
Contributor Author

@viatropos i think the issue is my router uses the name: attribute from the route to scaffold out

methodName = route.options.name
      Tower.router.root[methodName] = Ember.State.transitionTo(route.options.state)
      Tower.router.root.eventTransitions[methodName] = route.options.state

as methodName = 'posts'

but the view scaffold assumes "index#{many}" idk what we want to do. I think it makes more sense if all theses things key off of some definition. perferably the key given in the route. Let me know what you want to do. the simplest approach would be to modify the view generator, but we can always change the router around.

@j-mcnally
Copy link
Contributor Author

im a newb with git sorry i added some new stuff for evented object loading and i guess it got added here

@j-mcnally
Copy link
Contributor Author

you can check out that module here:

https://github.com/j-mcnally/node-obj-watch

@lancejpollard
Copy link
Member

Haven't forgotten about this :) been finishing up some installation bugs and getting some lower-level things working for demoing, then I'll be digging into the routing stuff. Hope all is well.

@matisojka
Copy link

I don't know if this is related to your pull request, but actually I have seen the code in the current master branch so I assume the bug may be also in the current npm version.

The thing is, I have just created two scaffolds for "classic" resources.
Then, I needed a view which is unique, so I created the controller and the views. The thing is, this controller's name is singular:

class App.PlanController extends Tower.Controller

In my router, I have this:

Tower.Route.draw ->

  @match '/plan', to: 'plan#index'

  @resources 'projects'

  # @match '(/*path)', to: 'application#index'
  @match '/', to: 'application#welcome'

Then, I have the typical _navigation.coffee view which tries to display the routes for the controllers:

a '{{action showRoot href=true}}', class: 'brand', -> t('title')

div class: 'nav-collapse', ->
  ul class: 'nav', ->
    li '{{bindAttr class="App.planController.isActive:active"}}', ->
      a '{{action indexPlan href=true}}', t('links.plans')
    li '{{bindAttr class="App.projectsController.isActive:active"}}', ->
      a '{{action indexProject href=true}}', t('links.projects')

And now, when I try to render the page, there is an error:

Error: assertion failed: You must specify a target state for event 'indexPlan' in order to link to it in the current state 'root.index'.

All other actions work if I comment out the affected line.

The question now is, how should I declare the action of the PlanController? I assumed I can have an index action only if it wasn't a really resource I am trying to connect to.

If there is a convention on have to call these actions, I'd like to find them somewhere, because it seems like a little bit "voodoo magic" to me right now.

BTW: Thank you guys for what you are trying to achieve, this project really feels great and I'm putting my hopes in it. I come from the Rails world and this is so much fun, even if you aren't a coffee/javascript expert.

@thehydroimpulse
Copy link
Member

@YAGoOaR Last time I heard singular routes weren't yet implemented, but that could have changed. I think the goal would be to have something like:

@resource "plan"

Just like what rails have.

@matisojka
Copy link

Thanks for the answer, @thehydroimpulse. I think it would be enough to define more clearly the connection between Tower routes and Ember routes so that it is clear how they are translated to make a proper use of them in the views.

@edubkendo
Copy link
Contributor

@viatropos I myself have been wondering lately how one accesses Ember's router and the connectOutlet's stuff from within a tower app. I will probably just dig into the source code , but thought I'd ask here just to see.

@lancejpollard
Copy link
Member

@edubkendo Ive been thinking a lot about this as well, haven't quite come to a good solution yet. We may want to think about making the routes.coffee more robust (so you can give them ember route/state objects for example) or have hooks in the controller. Still thinking... ideas welcome.

@edubkendo
Copy link
Contributor

I don't currently know enough about how the two are working together to say. Or what @j-mcnally did/attempted to do to address this in his patch.

I wonder if the best thing might be to split the two apart into two seperate files, like how they work in a rails/ember app. We could then still create a basic pattern that could be auto-generated when creating new apps and scaffolds and stuff, but it would be easy to change and manipulate for anyone who wants. Also, the ember router gives a lot of fine-grained control so it might make it easier for people wanting to route to additional pages and stuff that don't fall under the typical set of resources , without having to do a lot of extra work on the router itself. Basically, push all navigation onto the client-side ember router.

@edubkendo
Copy link
Contributor

Aha, so I've been playing around a bit. It's a little bit of work, and definitely wouldn't be at all intuitive to someone who hasn't worked with ember much, but you can get at all these stuffs from within your app. I'll give an example of how I did this stuff:

So first in routes.coffee I added:

@match '/login', to: 'application#login'

Then, in the application controller's

#server

  login: ->
    @render 'login'

# client

  login: ->
    connectOutlets: () ->
      router = App.router
      console.log "Connecting Outlets!"
      router.get('applicationController').connectOutlet('login')    

Now you just create a view and template and your good! Hopefully this will help some other people, and maybe we can think about how to make this a bit easier/simpler.

@edubkendo
Copy link
Contributor

@viatropos I think that you've really tapped into what was bothering us before, and come up with a very powerful solution. As far as moving away from the Rails model goes, Tower is more than Rails, because it's both client and server, so it makes sense that it will take some of its abstractions from Ember instead. This is the first time I've really been happy with the proposed solution since we started discussing this, but I could never come up with something better to offer. Damn, I'm excited.

@lancejpollard
Copy link
Member

Awesome! This is going to take some work but we're definitely going to have to move away from Rails in some spots.

@thehydroimpulse
Copy link
Member

How big is this on the list? Is this planned for the next version? It seems like a big refactor would need to take place, but I'm all for it. Also, would improving the client-side development (Tower Source) be more important, to streamline the development process? I'll be testing Resolve.js with Ember.js, and then with Tower to see how we'll it performs, and how well it improves the workflow. Cause right now, it's kinda a pain working on anything client-side.

@lancejpollard
Copy link
Member

I would like to make these big changes in one large swoop. There is nothing that really needs incremental improvement that is higher priority than making a better framework. We need to adjust everything in bulk.

I'm converting the test suite to JavaScript. After that I will convert the main codebase to plain JS and we'll talk about converting the default to JS. Even though I like coffee-script, I am now fairly convinced that it's not in the best interest of the node/js/tower community. More and more people I have talked to say they prefer using plain JS. I am slowly starting to agree. Looking back, a lot of the bottleneck/difficulty in getting started is in getting coffee-script compiling working.

@thehydroimpulse
Copy link
Member

Sounds Good!

I have a mixed feeling about coffee-script vs Javascript in node.js. Maybe it was the frameworks and methods used at the time, but Javascript felt ugly when modeled in a Ruby on Rails structure (That's before I learned Coffee-Script). After I've gone through and learned it, it made node.js very much more appealing, and plain, old Javascript was not fun to go back to. Now though, maybe because of Coffee-Script, Javascript feels so much better, and is super powerful. Maybe because I learned what Coffee-Script outputted and how good Javascript code was written.

I'd be willing to go both ways (coffeescript or js), but going with JavaScript would seem simpler, and would require less of a hurdle when using the framework.

@edubkendo
Copy link
Contributor

I really dislike javascript. Just putting that out there. Every semi-colon and bracket feels like, to quote @topfunky , a stab in the eye. And cleaner syntax is just the tiniest win that you get with coffee-script. I do understand the political motivations behind such a change. There is a lot of highly misplaced dislike of coffee-script within the Javascript community, but it IS misplaced, and seems to come solely from some silly idea that Coffee-scripters don't know Javascript and that because the javascript that's produced isn't the same as the javascript they would write by hand, it's somehow inferior. But it doesn't need to be the same, because it's not meant to be directly interacted with by humans.

Sure, you can say that one has to use the javascript for debugging, and that debugging coffee-script is difficult, but source-maps are here, the coffee-script 2 compiler is pretty much done, and it comes with source maps, which will make debugging the same for coffee-script as it is for js. Besides, I think anyone who really takes the time to get good at writing coffee-script code can tell you, most of the time, all this stuff about "being more difficult to debug" amounts to very little. Definitely nowhere near the enormous gains in productivity one gets from things like list comprehensions, or the simplicity of knowing your globals will automatically be scoped predictably for you, without needing to remember to use var.

I love coffee-script. It's the language I feel most at home in. Coffee-script brought me to Node, and node brought me to Tower. To see the code-base change to javascript, to see the default change to javascript, this makes me sad. I understand at least some of the motivation behind it, but I can't say that its a decision I agree with. I think Tower could be what pushes coffee-script to dominance, the way Rails pushed Ruby. More than that, though, I think coffee-script is a big part of Tower's identity and that identity is what made me fall in love with it, made me devote so much time to learning it, advocating it, and contributing to it.

To me, one of Tower's core principles has always seemed to be ease of development, and developer enjoyment. In the node.js community they have a saying: "JIFASNIF: Javascript is Fun and so Node is Fun" Except javascript is really not much fun, but coffee-script sure as hell is. Maybe it's the old fashioned syntax, or the many places where it disagrees with itself semantically (Just google "Wat Gary Bernhardt" if you want to see what I mean), maybe it's the weird way it does OO... I think it's the cumulative effect of all these things, but it makes reading and writing javascript boring and tedious... at least to me. Coffee-script eliminates many of these problems while retaining the things that ARE fun about the language: it's flexibility and simplicity.

We've spoken about this before, and I've never really voiced my full opinion about it, In fact, because I really do understand some of the motivation behind it, I had myself half-convinced that I was in agreement. But now that it's really here before us, and the change is underway, I've realized how strongly I feel. I may be wrong. This may be the right move for tower, this may be the only way forward for Tower, for all that I know. I certainly do not expect Tower to remain in cofffee-script, or with coffee-script as a default just because of my opinions. I think you need to make the changes you feel best serves Tower as a framework and the community as a whole. I'm ok with that.

And I may end up getting totally flamed for speaking so bluntly about javascript here. I'm ok with all that too.

What I wasn't ok with was letting this change go by without speaking up about it. I've done that now, so I'll try to let it go now. These are just my thoughts. I love Tower and want the very best for it, as we all do. Cheers.

@thehydroimpulse
Copy link
Member

@edubkendo Completely understandable. I still really do love coffee-script and there's something about Tower and coffee-script that just fits. I'm not sure what Tower with vanilla Javascript would look like, maybe having two versions would help decide which is better for the framework.

I'm not sure why people assume coffee-scripters don't know Javascript, it's a false view.

A Question, or two, though:

  • Wasn't there an issue with caching controllers for each user, because you'd have to use (request, response, next) in each controller?
    • Or has this been (theoretically) resolved, because of the router being cached as a whole within the Ember "world"?
  • Are controllers completely different now (going to be)? With the examples given here, it seems like postsController, for example, is just an alias to a cursor? Are we creating route controller's instead? or a mix of a new kind of controller (extremely slimmed down), and a route controller (not sure of what to call it).

So far, with my current understanding of this, seems to be extremely intuitive, though, it does bring some questions up.

@lancejpollard
Copy link
Member

Added Ember 1.0.0-pre.2 support to node, and the ember-application and ember-routing packages so we can start tinkering with the Ember.Router in node, excited!

emberjs/ember.js#771 (comment)

@thehydroimpulse
Copy link
Member

So is everything going to be based on Ember? Server and client? For example, is the server's router implementation going to become similar to the client without most of the state management?

@lancejpollard
Copy link
Member

@thehydroimpulse yes, pretty much.

@maedi
Copy link

maedi commented Nov 4, 2012

Hey @edubkendo just so you know you're heard. I agree. Though if Tower were to become more Ember-like I'd still prefer CoffeeScript to be the default.

@edubkendo
Copy link
Contributor

hey @maedi I'm actually 100% behind Tower's router becoming the Ember router, or more like the Ember router, or at least giving the developer access to the Ember router. Ember's router is amazing. It is a little weird at first, mostly because it was designed to tackle problems that just hadnt been tackled yet, at least, not tackled well, so it's full of new idioms. It doesn't take much time with it though, to realize how awesome and powerful it really is for controlling and manipulating Web UI's and State.

All I was disagreeing with was Tower's source and defaults being moved to javascript. I'll probably never agree with that, but I don't really want to get stuck on this either. If javascript defaults are the way forward for Tower, then they are, and like I said before, as long as I can continue using coffee-script, I'll continue using Tower. It's too awesome not to use just because I have to add a --use-coffeescripts or something at the command line. It probably will reduce my contributions to the source code, unfortunately, just because I really hate writing javascript that much. But I do plan to continue writing tutorials and articles into the foreseeable future, and THOSE will be in 100% coffee-script, so in that way I can continue to contribute to Tower's community, as well as answering questions, etc. I do wonder, though, if the kind of hardcore node people who hate coffeescript so much will ever actually use Tower or contribute to it anyways, since they all seem to slam frameworks, and rails, and Ember all the time too... =/

Anyways, I'm excited to see Tower move towards production-ready, so I can start using it in earnst. I've actually held off finishing my tutorial up because it seemed clear that there would be some api changes happening, and I wanted to wait for those before moving into the client-side code. Hope you are doing well @maedi. Let's not get too hung up on the javascript stuff, or stay too long on negativity. I don't want to make the same mistake I feel hardcore javascript people are, and write off an amazing framework just because I dont care for the language it's implemented in.

@thehydroimpulse
Copy link
Member

@edubkendo Well said. The main issue, as @viatropos mentioned, is the added complexity that coffee-script adds in the development of Tower. I'm personally one to go out of my way in terms of complexity if it gives me some benefit in the end. Nonetheless I feel like Ember is doing a great job creating an awesome Javascript API that doesn't try to make Javascript into something else, like rails, or ruby, with things like classes, constructors, etc... It, instead brings the Javascript way of doing things. Maybe that's why "majority" (I'll generalize here) of the nodejs community or Javascript community don't love coffeescript, as it's trying to turn Javascript into something it's not.

Ember, on the other hand, is trying, in my opinion, to embrace the Javascript idioms.

Though working with Ember inside coffeescript is a true pleasure, as it simplified the syntax a bit, using Javascript isn't that different and I'm getting to like it more as I use it. Sure the syntax is still C-like, but that's where my background comes from, so it's natural, I guess.

@thehydroimpulse
Copy link
Member

@viatropos Are you going to base the new router abstractions off of Ember's V1 routing or V2 (https://gist.github.com/3981133)? I guess a lot of people complained that the first implementation was too hard or something, not sure why, as it's fairly straightforward.

@edubkendo
Copy link
Contributor

lol,

Wow, this is almost entirely different. It actually looks like Ember is moving to an API a lot like the one we'd just decided to set aside in favor of their current API. I'm not even sure what I think tbh. I was really incredibly happy with the other Ember API. I don't understand why it was "hard" to use. It could be a bit verbose at times, depending on what you wanted to do, but it gave you exactly as much fine-grained control of what was happening as you wanted to take, with clever abstractions to remove muchc of that verbosity in the simpler case. Well, I guess the decisions we make depend a lot on Ember, and how easy/difficult it is to make the Tower api we choose work with whatever Ember is deciding on.

@thehydroimpulse
Copy link
Member

@edubkendo Tom Dale, one of the main Ember guys, said it would only become an option to use the new routing API. It's simply a semantic look that translates down to the current, so just an abstraction. Before I saw this, and before Tom tweeted it, people were freaking out, but both APIs will stay. One is just a more "bare bones" approach (Though it's not really complex, nor is it hard. It's basically a bunch of states, and connecting outlets most of the time), and the other is an abstraction on-top of the current system.

Not sure if you knew that or not, but I thought I'd clarify just to make sure.

I actually started trying to implement the new proposed Tower routing API against Emberjs and it's pretty easier to abstract Ember tbh. Though there is a lot of recursion and state management needed, I think it would be easier to build on top of the "bare bones" instead of the new one.

@edubkendo
Copy link
Contributor

no, actually hadnt had time enough to dig around for conversations on this and whatnot, so all i had done was scanned over that link you posted, so these were exactly the questions I had. This sounds good then. I agree the "bare bones" API definitely seems like it would be easier to build on top of.

@thehydroimpulse
Copy link
Member

@viatropos Any progress on plans or implementation of the new stuff (router, js api, etc...)?

@lancejpollard
Copy link
Member

Making progress on the JS API. It required a bit of refactoring but it's getting there. A lot of it came down to taking a fresh look at the directions Ember and Express (and Node.js in general) are taking for API's, and making sure it aligns well with both.

Express and most of the node stuff uses chainable api's for the most part, while Ember uses (don't know what they're called) "object" APIs. Chainable APIs are cleaner in my opinion, but it should support both (at least until we figure out best practices and what people prefer).

One example is in how validations are defined/stored. To make the validations API more extensible, I'm putting them into a global hash similar to how ember-data transforms are:

Tower.validators = {
  presence: function(object, key, value) {
    // ...
  }
}

But the way Express might do this would be:

Tower.validator('presence', function(object, key, value) {

});

It's taken a while to realize there are these two main ways of making APIs. The reason it's important is because the whole Tower app should have a consistent way of defining the different parts, which will make it easier to extend. So if express defines it's routes like app.post('/'), etc., while you define configuration like this: app.settings.title = x, then things aren't right. This is why express defines settings like this: app.set('title', x) for example. Also thinking about how to get this style to work with Ember.Router.

In getting the JS api for the models implemented, I've had to think of ways to define validations on the fields. Now realizing it boils down to these 2 main ways of defining APIs, it makes it easier to come to a final conclusion on how it should be:

// this stuff is working on my end
App.User = App.Model.extend({
    email: App.field().validate('presence').validate('uniqueness').validate('format')
    email: App.field().validate('presence', 'uniqueness', 'format', {if: 'x'}) // shared options
    email: App.field().validate('length', function(value) { return value.length > 3 })
});

The issue was, there could be potentially many more ways to pass arguments to that validate method, but by keeping it simliar to the express/chainable api it limits it in a predictable way (at least it's getting there).

Along the same lines of standardizing the APIs, this method has made it much clearer how to define serializers, param parsers, modifiers/operators for the database, and global app config, some ideas here:

As a side note, you're also going to be able to define models using a purely chainable API almost like CoffeeScript (this was just a side effect):

App.User = Tower.Model.extend()
  .field('email')
  .hasMany('posts')
  .validates('email', {presence: true})
  .classMethods({

  })
  .instanceMethods({

  })

So if you wanted to hack it together you could do that, but these will be the preferred approach:

App.User = Tower.Model.extend({
  email: Tower.field().validate('presence'),
  posts: Tower.hasMany()
})
class App.User extends Tower.Model
  @field 'email'
  @hasMany 'posts'

  @validates 'email', presence: true

Will let you know when it starts getting ready to merge.

@lancejpollard
Copy link
Member

I personally am spending more and more time purely on the server-side digging into the data. I would love someone to take charge of the client-side stuff, that would help a lot. I'll make sure the router and all the client stuff gets finished and is awesome and implements what we've been describing, but I'd like to focus more of my energy on the data. That will all of course be integrated into Tower in some pluggable way.

As a result, I'm defaulting to be more a fan of the node/express api's than ember's, but I see the validity in both and Tower will work to support both to see what works best and is preferred down the road.

Cheers.

@thehydroimpulse
Copy link
Member

Sweet, sounds good. I love the new ideas, especially with the consistency
in APIs.

For controllers, I tend to prefer the coffee script full classes (but in
JavaScript) instead of embers hash api. Mainly because the hash doesn't
exactly let you add custom things that are not properties but just some
method call, like @on or something. Again, I think this would be solved by
providing a streamlined api.

I'd like to volunteer for all the client-side stuff of Tower. I think if we
really split things up, well get things done a lot quicker and faster. I'm
working on a few things for the client side of tower, one of which is to
streamline the development environment, which I think is an important next
step to make things a little more efficient.

Then we could decide on a module system on the client side that works for
everyone, AMD, CommonJS, and other optimization techniques like local
storage, hybrid-string, etc...
On Nov 24, 2012 7:23 AM, "Lance Pollard" notifications@github.com wrote:

I personally am spending more and more time purely on the server-side
digging more into the data. I would love someone to take ownership of the
client-side stuff, that would help a lot. I'll make sure the router and all
the client stuff gets finished and is awesome and implements what we've
been describing, but I'd like to focus more of my energy on the data. That
will all of course be integrated into Tower in some pluggable way down the
road. Cheers.


Reply to this email directly or view it on GitHubhttps://github.com//pull/299#issuecomment-10678113.

@edubkendo
Copy link
Contributor

Interesting. @viatropos did you see @wycats latest gist ? It looks more and more like Ember's router is moving towards exactly what we are moving away from.

@thehydroimpulse
Copy link
Member

@edubkendo Looks interesting.... Not sure how I feel about the new radical changes in their API, though, again, it's just a semantic addition to the current router. It certainly looks easier to use then the current one, everything is in one place. I'd still prefer the proposed Tower router API then Ember's new one.

@maedi
Copy link

maedi commented Feb 7, 2013

So will Tower use v1 or v2?

@lancejpollard
Copy link
Member

The routing system is starting to become really awesome. Here are some notes:

https://gist.github.com/viatropos/4689443#comment-764567

We're moving to a more DSL-like approach that can be expanded to different frameworks such as Ember and Angular. It turns out this is very similar to the d3.js api, and also solves the problem of how to send tons of data around in a super optimized way (such as for multiplayer games).

We landed on the DSL approach after trying to figure out how to get the most performance out of the code. Writing it this way means the server/client code boots up insanely fast (minimal operations at startup, making the terminal start instantly for instance), and the JavaScript the browser will have to load for Tower is a fraction of what it is now. It also changes the way you think about what's happening in the app (more on that in the later comments on that gist).

You will also be able to write the expanded version directly (i.e. App.UserIndexRoute = Tower.Route.extend), but it's much easier on the hands/mind to write it using the DSL. I will look into also making it so you can write this stuff in CoffeeScript the same way you do now (if it's easy/quick to do), but that's a secondary goal.

To answer your question @maedi, Tower will use the latest Ember Routing API on the client, but is going to build the DSL around it, so when you write your routes on the server, you you don't need to use Ember at all (more on this later, but basically, I don't think you need Ember on the server for most cases).

Definitely weight in on the API (gist or this post) if you have any ideas/opinions.

@egeozcan
Copy link

I'd like to start a new weekend project with Tower.js sometime and I really dislike writing and (especially) reading coffee-script code. A JavaScript API would've been awesome. Do you have a timeline for finishing this? Are they any areas a "JavaScript hacker" would be able to help? =)

@thehydroimpulse
Copy link
Member

@egeozcan We're actually basically rewriting Tower in JavaScript with different principles. Completely modular design (~40 separate npm modules). http://github.com/tower

I can't give out a timeline, but things are taking shape.

@egeozcan
Copy link

@thehydroimpulse that sounds great, i'd sure give it a try when you finish.

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.

None yet

7 participants