ruby-on-railsruby

How get actual attributes passed to class create Ruby on Rails


Im trying to set a value based on if certain param was passed or not to the constructor, let say we have:

# == Schema
# id   :bigint  not null
# foo  :string
# done_at :datetime
#
class Model1
  belongs_to :something
  before_create :set_done_at

  private

  def set_done_at
    return if done_at.present? # we set to done_at if passed 
    self.done_at = Time.current
  end
end

So the behavior would be

m1 = Model.create(foo: "hi")
m1.done_at
=> 2025-03-26 20:57:08

m2 = Model.create(done_at: the_epoch)
m2.done_at
=> 1970-01-01 00:00:00

But now my problem is that done_at could be explicitly passed as nil and this logic not longer works since im using .present?.

I tryied checking if the key is present on the hash passed to the constructor but this is what I can't find, naively I tryied using attributes and attributes_before_type_cast but those return all attributes of the model. I read part of ruby's documentation and come across attribute_present? but for nil it is not of use for me. Would be cool if I can do sometihng like

actual_attributes_passed_to_constructor.key?(:done_at)

The spected would be:

m3 = Model.create(done_at: nil)
m3.done_at
=> nil

A solution would be using an adapter for the params before getting into the create, but doing it on the model makes it so much more scalable and less messy with prexisting code

We are on old version :( ruby 2.7.1*

Apreciate any insight


Solution

  • You can use *_came_from_user? attribute method to know if attribute was assigned by the user, whether it's nil or something else:

    def set_done_at
      return if done_at_came_from_user?
    
      self.done_at = Time.current
    end