Get attributes that were used to instantiate object

This topic is referring to the following issue on Github:

It would be great to have a method that can return all of the attributes that were used when instantiating a new object. Just for demonstration let’s call the method .original_attributes. So for example, when calling:

new_attributes = {'name': "John", 'age': 27, 'address': ""}
new_or_changed_user = User.new(**new_attributes)
new_or_changed_user.original_attributes

Then this should pretty much return everything that was provided in the new_attributes variable, something along the lines of:

{"name"=>"John", "age"=>27, "address": ""}

Like this we would know exactly which attributes were specifically provided, and can call an upsert exactly on those columns to update them. The problem is that .changes doesn’t work as default values are being ignored.

Would attributes_before_type_cast serve your purposes here?

EDIT: Ah, I misread - I thought your goal was to get the attributes before they’re transformed, but it seems you’re trying to get the set of attributes that have changed from what’s in the database. (For new records, that’s of course everything.) What about changes_to_save? Unless you need to know changes that aren’t to be saved, in which case I’m not sure I understand the utility of getting such attributes if the goal is to get the changes into the database.

Thank you @jas14

Here is the application:

We want to instantiate an array of new objects, based on their updated values. Let’s say we are updating 100 records all at once - so we map through them and instantiate the new records by calling Record.new and then pass in the attributes that we want to update.

Now we want to perform an upsert_all on these records. We know the unique columns and will always provide them when instantiating the objects. But the columns that we want to update actually can vary. So maybe we pass in 2 unique columns on which there is a unique index, and then we only want to update one column on existing records. This we want to abstract in order to not always need to pass in exactly which particular column should be updated, and instead we would just like to check the keys of the attributes that were provided when instantiating the model, and then subtract the unique columns in order to determine which columns should be updated.

The issue with attributes_before_type_cast is that it returns all attributes of the model, and it would be impossible to tell which ones actually were supposed to be updated, as the defaults on columns would interfere. Say the default of a column is actually nil, and then we update records that have non-nill columns to be nil again, then we would have no chance of finding out that nil was specifically provided when instantiating the object.

Similarly changes_to_save does not work, as default values are not being returned. That’s annoying because existing records might have different values other than the default that we would want to reset to the default, but then we would not detect those columns and therefor not include them in the upsert.

So really what we are after is to know exactly which attributes were provided when instantiating. Hope that kind of makes sense.

There was a method on attributes up until 5.1.7 called came_from_user? that might have been perfect for this. I can’t find any mention of it any more in the Rails API documentation.

Walter

Yeah that unfortunately seems to be deprecated. Is there any other good way to access the original attributes that were provided, or find our which columns were provided to instantiate the record?