-
Notifications
You must be signed in to change notification settings - Fork 442
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
Tracking attribute changes #352
Tracking attribute changes #352
Conversation
Attributes should only be flagged as dirty if the assigned attribute has changed. Assigning the same value to an attribute as the current value should not flag the value as dirty.
To complement the flagging of dirty attributes, added functionality similar to Rails which will track the values of changed attributes. Added the following methods: - $model->changed_attributes() Returns a hash of all attributes that have changed and their original values. #=> $changed_attributes[$attribute] = $original_value; - $model->changes() Returns a hash of attributes that have changed with the original and current values. #=> $changes[$attribute] = array($original_value, $current_value) - $model->previous_changes() Returns the changes to a model's attributes before it was saved. - $model->attribute_was($attribute) Returns the original value of an attribute before it was changed Also made a change to the read_attribute() method. It seems that there is a quirk in PHP when the return value of the __get() method is passed by reference and you are trying to set a value using one of the 'combined assignment' operators (e.g. .=). If the return value of the __get() method is a reference to an array element then a weird thing happens - the value passed to the __set() method is the same as the current value. That's a super confusing explanation, so an example will clear it up: class Person { private $attributes = array('name' => "John"); public function &__get($name) { return $this->attributes[$name]; } public function __set($name, $value) { echo "original value: {$this->attributes[$name]}\n"; $this->attributes[$name] = $value; echo "new value: {$this->attributes[$name]}\n"; } } $person = new Person(); $person->name .= " Doe"; A simple change to the __get() method: public function &__get($name) { $value = $this->attributes[$name]; return $value; } seems to clear up the issue. So I applied that same logic to the Model::read_attribute() method, assigning the $this->attributes[$name] value to a variable, and then returning that. I don't think that should mess anything up, all unit tests still pass.
Took out the conversion of DateTime objects to strings, that is just unnecessary. DateTime objects should be kept as they are. Also added test to make sure that changing a DateTime attribute tracks a change.
This looks good, sir, and good work on the tests. Since this isn't a critical feature addition, I recommend pushing to 1.2... Any objection? |
Sure, 1.2 sounds good |
@leightonshank, I just realized you live in Richmond, VA too! Now I have to accept this PR, right? : ) |
@jpfuentes2 Ha, I didn't know you were in Richmond either, that's cool that you're local. So if it helps get this PR in then I'm all for it! What do you do in RVA? |
@leightonshank, as you can see I don't do much PHP or PHP-ActiveRecord : ). I work remotely primarily doing back-end work in a slew of different languages. I'm going to make sure this is on the 1.2 road map. |
Closing in favor of #427 |
This PR contains 2 updates to implement tracking changed attributes in ActiveRecord\Model, based on the Rails ActiveRecord implementation.
assign_attribute()
method so that attributes are only flagged as dirty if the attribute value changes.