On Nov 17, 7:37 pm, abusiek <[EMAIL PROTECTED]> wrote:
> On Nov 17, 8:43 am, Daniel Bush <[EMAIL PROTECTED]> wrote:
>
>
>
> > On Nov 17, 5:45 pm, abusiek <[EMAIL PROTECTED]> wrote:
>
> > > Hi!
>
> > > I'm struggling with this for a while and i'm new to rails so it's
> > > quite frustrating ;)
>
> > > I need to create new model object based on old one with only few
> > > changes.
>
> > > I have desings -> has many -> lines -> has_many -> fields
>
> > > I've got input from user in array like this:
>
> > > field =>[
> > >     line_id =>[ fiel_id => field_value]
> > > ]
>
> > > so I iterate:
>
> > > input[:field].each do |line_id, line|
> > >     line.each do |field_id, field_value|
> > >     design.lines.find(line_id).fields.find(field_id).value =
> > > field_value
> > >     design.lines.find(line_id).fields.find(field_id).something =
> > > field_value
> > > end
> > > end
>
> > You're finding stuff and assigning new values to what was found but
> > not saving these changes back to the db as far as I can tell here.
> > Retrieve the field once
> >   field=design.lines.find(line_id).fields.find(field_id)
> > update its values and then save it
> >   field.something = ...
> >   field.save (or field.save!)
> > You're not creating anything new, just updating old.
>
> > If you want a new field, you'll need to create it:
> >   design.lines.find(line_id).fields.push(Field.new({hash-of-
> > attributes}))
> > This will add a new field to design's line with line_id.
>
> > You could probably do something like
> >   new_field=Field.new(field.attributes)
> > to create a new field with the same attributes as the existing
> > 'field', alter
> > its values as required and then push it onto the fields collection:
> >   design.lines.find(line_id).fields.push(Field.new(new_field))
>
> > Be careful with names like 'field' - I don't know if they'll clash
> > with rails names.
> > Maybe also consider not chaining all those 'finds' together in one
> > line.
> > Find each thing and store it in a local variable or an instance
> > variable so
> > you won't have to get it again during the action.
>
> > --
> > Daniel Bush
>
> I followed your suggestion and write this code:
>
> 1    new_design = Design.new design.attributes

There's actually a 'clone' method which is probably better than what I
suggested before.
  new_design = design.clone
But don't forget that you'll need to save it at some point.

> 2   design.background.colour_id = 123
> 3    new_design.background = Background.new
> design.background.attributes
> 4    lines = design.lines
> 5    for line in  lines
> 6        new_line = Line.new line.attributes
> 7        fields = line.fields
> 8        for field in fields
> 9          field.value = input_data[:field][line.id][field.id]
> 10          new_field = Field.new field.attributes
> 11         new_line.fields.push(new_field)
> 12        end
> 13       new_design.lines.push(new_line)
> 14    end
>
>    and now I'v got error that i have nil object in line 5, 8, 9 so it'
> seems that rails think's design has no lines.
>

I'm guessing it's line 9 and it has something to do with input_data
[:field] or input_data[:field][line.id] that's returning nil.  5 and 8
are just part of the looping which means there are lines and each line
does have fields.

You could compress your code a little eg
  design.lines.each do |line|
    new_line = line.clone
    ...
    line.fields.each do |field|
    ...
    end
  end
I didn't mean to break everything up into separate assignments;
whatever you think is best.

--
Daniel Bush
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Ruby 
on Rails: Talk" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to