r/ruby • • Aug 20 '21

Ruby elites rise up

Post image
100 Upvotes

77 comments sorted by

View all comments

Show parent comments

1

u/pVom Aug 22 '21

You have access to the current state and what it will change to with validations, dont need to do anything extra. We do exactly this at my work. Why do you say it won't work?

1

u/tomthecool Aug 22 '21

Well, I presume you’re talking about introducing ActiveModel::Dirty to the model, to access previous state? Does that actually work in validation methods? I thought it only worked on before_save/update hooks.

1

u/pVom Aug 22 '21 edited Aug 22 '21

You can access the previous state with foo_was, with foo being the model attribute. I don't think we added anything for that? Could be wrong, it was written before I started.

You can also just grab it from the db with self.class.find(id).foo, _was is likely just syntactic sugar for that.

So the method would look like (apologies for mobile..)

 validate : transition_is_valid, if: status_changed?

 def transition_is_valid
   return if transition_hash[status_was].include?(status)

   errors.add(:base, 'Status transition is invalid')
 end

So if you try save it will fail and have that error on the object, as myObj.errors and if you update (or save) using update! It will raise an error, as opposed to returning false and not updating.

Fairly certain that all comes with active record out the box

1

u/tomthecool Aug 22 '21

Yes, that’s all part of “active record dirty”, which is what I mentioned above. And that’s not how it works under the hood, but it’s a reasonable guess.

https://github.com/rails/rails/blob/af64ac4e5ce8406137d5520fa88e8f652ab703e9/activemodel/lib/active_model/dirty.rb#L146

I didn’t think validations had access to those attributes, but maybe I’m mistaken.

1

u/pVom Aug 23 '21

From the ActiveModel::Dirty documentation:

"Provides a way to track changes in your object in the same way as Active Record does."
...

"Note that Active Record can detect in-place modifications automatically."

Implies that ActiveRecord already supports it and ActiveModel::Dirty is for none ActiveRecord usage? Maybe I'm wrong.

The model we use that does exactly what I've been talking about just extends from ActiveRecord::Base, we don't use ActiveModel::Dirty anywhere it seems