Beginner: Guidance on building CRUD


#1

Very new to Ember, and I am a bit confused on a few things when it comes to using ember-data. In general, I love the idea, but working with it has been frustrating and a bit baffling.

I have a route for showing all existing models for a resource, and a nested show route for loading details. On that page, I have a small form for adding new models, which will trigger an action handled by the route.

This was all surprisingly easy and straight forward. Now however, I feel like I hit a bit of a wall.

Should a creation form be backed by a model? Since there is only one model per controller, does that mean creation forms need to exist in their own route? It seems like a strange limitation.

When handling the create action, I am calling store.createRecord, and then saving it. Which makes loads of sense if it saves successfully. If it doesn’t, do I need to manually remove the model from the store?. It would make much more sense to me to instantiate the model, and if that succeeds then add it to the store, but apparently it isn’t possible to instantiate models directly.

When the server responds with a 422, an exception is thrown by ember-data. Is that expected, or is there something I should be handling? More complex validation needs to happen server side, and validation failure is definitely not an exceptional situation, having exceptions being thrown feels like I’m missing something.

If there are errors added by the server, should I try to re-save the same model instance?

What is the recommended way to display server generated errors on a form?

Given how much effort has gone into having conventions, documentation, and tools for streamlining common tasks, it feels like the validation workflow is an area that is sorely lacking.


#2

Heya! Welcome to the Ember community! :smile:

First up, you should think of Ember as a completely different brand of thing than anything else you’ve encountered before… that’s to say, throw out your old definitions for stuff, and be open to the fact that things that are named something might not be what you’d assume them to be.

Ember Data has the concept of a store which contains all your records. Syncing that store to APIs is a separate concern. So, if you create a record in Ember Data’s store, it’s available to every other part of your app on that particular instance of Ember. You can experience this if you have a bound list on a page of, say, people, and you manually (using the JS console) create another Person object in the Ember Data store. It’ll just appear on the list. save() and revert() have to do with syncing the store to the backing APIs, not to do with adding things into the store. createRecord has to do with adding things into the store. Interestingly, deleteRecord() can be used to remove an object from the store, but then you have to save() in order to sync the back end API. Perhaps the naming is a bit, well, odd… :smile:

It sounds like perhaps you haven’t worked through the example video, or the todo mvc example… you should definitely do those. The “standard” ember way is to not create a new record for your form and then throw it away. So, if you have a Person with a name, then Ember tends towards getting you to create your form with just separate objects… I had to jump this hurdle, too, given that I’d come from a whole raft of other “ways” of doing things.

There’s currently not really any particular recommended way of handling validations. I have a sneaking suspicion this will be coming to Ember Data: as you may or may not know, Ember Data isn’t finished yet.

You touch on an interesting point to do with validations, because often there seems to be a requirement of similar code in both the client and the server, depending on the applicaiton being developed. Duplicated code is really smelly, and yet we find outselves having to do it to some degree. What would be really nice is some way for Ember to communicate with the server about its data schema and their validations and other application logic, if required, but we don’t really have any such protocols or technology yet, do we? :smile:

For example, if you have a Regexp validation on your name field for Person, and your server has three clients, one of which is Ember (web) and another of which is, say, an Android api… and another one which is a straight up HTML form without Ember… how do you provide validations to all three? The answer is you pretty much have to code the validaiton three times, once in the android app, once in the server and once in the Ember side. Note, though, that the validation should happen as closely to the client as possible, IMHO. So, if Ember is your only client, do your validation on the client side, and just have another validation on the server as a reinforcement / check against someone doing some tricky stuff in JS… the same way you might have validation in your SQL even though your server side code might be actually handling all the referential integrity or the data validation…

Hope that makes sense and I haven’t muddied the waters too much.


#3

Thanks for the quick reply :smile:

What you are saying about the store / form attr object makes sense, what is tripping me up is the validation scenario. Let’s say someone tries to create three records, if they fail there are three broken models in the store. I can manually remove them on failure of save(), but it feels strange to have to do that. I think i’ll just suck it up and do that, and hope that the powers that be more fully support validations in the near future.

WRT client side only validations, my problem is one of them is uniqueness. I can always create a route to check for uniqueness before submitting, but it is easier to do those sorts of validations on save. The other thing there is ember-validations doesn’t seem to easily support custom AJAX validations.

As for duplication of code, I think validations are something that you just have to suck up and duplicate. Should be in the DB to maintain data integrity, on the app server to handle business logic cases, and on the client to prevent bad requests for silly reasons. Kind of waxing philosophical at this point, but thats my point of view :smile:


#4

I end up adding a hook like this on any route that might be creating new records:

deactivate: function () {
    var model = this.get('content');

    if (model.get('isNew')) {
        model.rollback();
    }
}

I’m 90% sure that’s the right methods, but you get the gist.

Regarding the validations: I’ll advocate for Ember Validations. I’ve used it on a large project and it worked like a charm. Adding new validations is only a couple of lines of code, it gives your model a very intuitive isValid property, etc.

Here’s a pattern we used over and over on our controllers with a save action:

save: function () {
    var model = this.get('content');

    model.validate().then(function () {
        model.save().then(function () {
            // transition or whatever
        }, function () {
            // handle server error
        }
    }, function () {
        // handle validation error
    });
}

The validate method is also something that comes with the ember-validations mixin…it functions the same as isValid.

Note that incorporating all of this is only worth it if your project is big enough, because there’s a bit of overhead in bringing in the validations library. I would say even medium size projects would benefit though.


#5

DUDE! Nice… Man this really should be mentioned somewhere in the ember main site… or on the documentation for ember-data, or something… (I dunno, is it tied to ember data?)


#6

Yeah, it really depends what you want to do, doesn’t it? I mean, sometimes you want your “currently editing” object to appear in with the rest of the objects, so “creating” the object before you present the form and then “reverting” the object if they press cancel is what you want to do… other times you don’t want it to appear bound until after you’ve hit “create” or whatever in the UI.

I personally use the prior approach in my app… beacuse I want a live preview of the data as they’re entering it… if they hit cancel, I just recurse through my object tree of created objects and revert them all (ie remove them all from the store). That works great for my particular use case, but probably standard CRUD wouldn’t have that be the case. You only want your object to appear in a list once it has been synced to the server, and validated…


#7

I don’t think it’s tied to Ember Data in any way…it’s something the Dockyard guys cranked out (edit: Brian Cardarella specifically) that’s become fairly popular. They deserve kudos for this, plus they have some other open source Ember projects too, and blog posts I believe…


#8

This stuff is hard to discover unless you know where to look. It’d be nice if the main ember site helped to discover it… I mean, @mbriggs makes some very valid points which I’ve felt, too… it’s just really hard to know where to begin with what feels like a “standard” app. I know the ember-cli project is coming and there’s the app kit, but it’d be cool if, well I don’t know, we could all work on a common community-driven ember app that’s touted as a “standard” getting started ember app that embodies all of the things that one would want to in a serious “blogging app”… you know - flesh out Tom Dale’s Ember Blog post video as a complete tutorial. I guess I should really do this myself coz I see the need…

There are a lot of toy apps out there, and they’re all well and good, things like the TODOMVC, but there aren’t very many serious apps… it’s like… toys… and then BAM! discourse … read the source code :slight_smile: lol.


#9

I regard the discourse site as the canonical Ember app. Link to the Ember portion of the repo.

Edit: I see you know about discourse as a big app…I guess you mean something between discourse and todo mvc? Yeah, that would be nice… Everything that I’ve worked on that might be useful to you is closed source unforunately.


#10

Yes, fair enough, but my point still stands that it’s AWFULLY COMPLEX for a beginner to digest. There must be some middle ground between a toy site or a handful of demos and the discourse app.


#11

Perhaps the new Ghost UI will be what you want, though that will probably end up as complex as Discourse.


#12

Perhaps what I/we need to do is build a series of steps… in complexity… (ie 10 different example apps, each a little more difficult than the last…) :smile: anyway we’ve digressed a little from the guidance on building CRUD :smile: hehe.


#13

Thanks for the reply :smile: It seems clunkier then it should be, but this is pretty much what I was looking for


#14

Yeah it’s not so much for me… I’ve got a fair handle on Ember’s way of doing things by now… (having used it as the basis for the app I’ve been building over the course of the last 6 to 8 months)… it’s more for new people. I’ve got something in the works, anyway… :smile: I myself, though, am not entirely sure I’m doing it “the right way” :wink: