3

I have a new model myModel that I'm creating with a one-to-many relationship to a bunch of sub-models mySubModel that are being created at the same time.

when I try to save the model:

<cfset myModel=model("myModel").new(params.mymodel)>
<cfset myModel.save()>

only the model part gets saved, the items inside params.myModel.mySubModels do not get created. The models have their relations setup and I can get it to pull the data in the same format out of myModel with the right include.

I could save each of the models separately, but I'm worried about that causing problems or just creating needles lines of code if cfwheels is able to handle this already. I would have to save the initial model and then save the additional sub-models, and if there is an error, delete the model and other sub-models that have already been written to the database.

Daniel
  • 34,125
  • 17
  • 102
  • 150

3 Answers3

3

As long as the main object relates to sub-objects with hasMany, Nested Properties will be invaluable to you.

In the main model:

function init() {
    hasMany("subModels");
    nestedProperties("subModels");
}

Then a call to save() in the controller runs saves on the parent object and all of its associated children.

function create() {
    myModel = model("myModel").new(params.myModel);

    // This call to `save()` saves associated children represented in `params.myModel` too
    if (myModel.save()) {
        redirectTo(route="myRoute", success="The model was saved successfully.");
    }
    else {
        flashInsert(error="There was an error saving the model.");
        renderPage(action="new");
    }
}

If you can comment more about your particular data structure, I can help you with the form part. Calling something "subModel" is only going to get us so far in this discussion.

Chris Peters
  • 17,918
  • 6
  • 49
  • 65
  • Thanks a lot Chris, I had missed the nestedProperty inside the model. – Daniel Dec 09 '11 at 01:02
  • Yes thanks Chris - I've used wheels for a while, but hadn't really noticed that feature. Good to know. – Jake Feasel Dec 09 '11 at 06:11
  • Good, but still unclear how to fetch and display flash messages for sub-model validation errors. Say, can `errorMessagesFor` be used? – Sergey Galashyn Dec 09 '11 at 17:03
  • Sergii - That's not what was asked, nor was any detail about the view provided where I could figure out what Daniel wants for his app to do. If you have a question related to that, why not ask it as a separate question? – Chris Peters Dec 09 '11 at 20:20
0

I'm looking at the docs here: http://cfwheels.org/docs/1-1/chapter/associations specifically, the section related to "hasMany()". I see several functions there for creating new child records based on the parent record, but none that will create multiple at a single go. At best, it seems like this is what you could do:

<cfset myModel=model("myModel").create(params.mymodel)>

<cfloop array="#params.mymodel.mySubModels#" index="thisSubModel">
  <cfset myModel.createMySubModel(thisSubModel)>
</cfloop>

Which really doesn't seem that bad.

Jake Feasel
  • 16,785
  • 5
  • 53
  • 66
0

I would define two methods in the model's init, like this:

validate(methods="validateChildren");
afterCreate(methods="createChildren");

validateChildren would run validation for each child model (defined in corresponding models, of course), consider using valid for this purpose -- it fires the validation without saving data.

Use syntax like this to pass the error to the parent model level:

addError(property="someproperty", message="Something wrong happened");

Then if there are not errors createChildren method would create all needed sub-models, using params to override the safe defaults. Personally I would not use looping over params because relying on external data is not so good idea and can mess the stuff.

Sergey Galashyn
  • 6,946
  • 2
  • 19
  • 39
  • I understand why this answer was downvoted: it does not use the power of framework object model properly, but at least it allows to fetch all sub-model warnings easily. – Sergey Galashyn Dec 09 '11 at 17:05