changes to model properties are not saved #125

Closed
raldred opened this Issue Nov 2, 2011 · 6 comments

Projects

None yet

6 participants

@raldred
raldred commented Nov 2, 2011

I've upgraded from 1.0 to 1.1.2
There now seems to an issue with my models where changes to properties are not recognised so model.save returns true but never makes a put request to couch.

I'm saving slightly complex data structures in properties, hashes or arrays

eg...

class ExamSitting < CouchRest::Model::Base
  property :seen_questions, Array, :default => []
end

@exam_sitting = ExamSitting.get params[:id]
@exam_sitting.seen_questions << @questions.id
@exam_sitting.save

also....

@exam_sitting.chosen_answers[@question.id]['answer'] = 'xxxxx'
@exam_sitting.save

These all used to work previously absolutely fine.

it's like the object you get back from get or a view is not the actual state of the document.
So when making changes, sometimes the underlying data structure is not updated.
So when calling save it things theres no changes.

Rob

raldred commented Nov 2, 2011

I have had to re work my code for now to....

chosen = @exam_sitting.chosen_answers
chosen.deep_merge!({"#{@question.id}" => {"answer" => 'xxxxx'}})
@exam_sitting.chosen_answers = chosen
@exam_sitting.save

This works

pklingem commented May 2, 2012

I'm having the same issue as @raldred.

I to am having the same issue as @raldred.

Having this same issue as @raldred with version 2.0.0.beta2.

Try defining your property like this:

property :seen_questions, type: [], default: []

I'm not sure why but by specifying the type using the :type parameter the property value will be a CastedArray which extends Array and does some internal dirty tracking. But note that it's incomplete in that only some common Array methods are extended to do dirty tracking while others are not.

Ex.:
@exam_sitting.seen_questions << @questions.id will mark the model as dirty while
@exam_sitting.seen_questions.sort! will not.

Check the CastedArray class to see which methods exactly are supported.

Another option for you is to use the *_will_change! method before you modify your properties, e.g.

@exam_sitting.seen_questions_will_change!
@exam_sitting.seen_questions << @questions.id
@exam_sitting.save

See also the last paragraph here: http://apidock.com/rails/ActiveModel/Dirty

Owner
samlown commented Jan 16, 2013

I've never been very happy with the dirty tracking, especially when dealing with complex models. If you don't need it, I'd suggest disabling it for the model you're developing:

class ExamSitting < CouchRest::Model::Base    
  def disable_dirty; true; end
end

(I'll try and get that into a model configuration option.)

Regarding @jhecking's comment, the type syntax is very old and is the same as writing the following:

property :seen_questions, [], :default => []

Note key difference between that and the following:

property :seen_questions, Array, :default => []

The first is an object or "an array of things", where as the second is a class or "an array", and won't get typecast in the same way. CouchRest will assume that Array is already an object that can be serialised and handle the casted_by properties on its own. Conversely, [] will get converted automatically to a CastedArray that will handle dirty tracking correctly.

Hopefully that clarifies this issue so we can close it. Would be great if anyone has a moment to update the couchrest.info docs!

Cheers, sam

@samlown samlown closed this Jan 16, 2013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment