clear icon indicating copy to clipboard operation
clear copied to clipboard

Allow overriding column setter

Open mloughran opened this issue 3 years ago • 3 comments

Apologies if this is possible and I've overlooked.

I'm struggling to understand why the custom Account#email= method in the following does not get called:

require "spec"
require "clear"

class Account
  include Clear::Model

  column email : String

  def email=(e : String)
    super(email.downcase.strip)
  end
end

describe Account do
  it "overrides email setter" do
    account = Account.new
    account.email = "[email protected] "
    account.email.should eq("[email protected]")
  end
end

Is there a better way of achieving this? Thanks!

mloughran avatar May 12 '22 10:05 mloughran

I think clear implements a lot of defs in a finished macro, which would be defined after your own email= def, overwriting whatever you had with its own. You should be able to overwrite its own def with yours by wrapping your method with a finished macro:

macro finished
  def email=(e : String)
    previous_def(email.downcase.strip)
  end
end

No idea if you still have this problem, since it was posted so long ago :grimacing:

Vici37 avatar Jul 07 '22 14:07 Vici37

And thinking about it, you might want to replace super with previous_def, since you don't want to call the parent classes' method of email=, which doesn't exist for Object, only the previous definition of it.

Vici37 avatar Jul 07 '22 15:07 Vici37

@Vici37 thanks – I can confirm that using macro finished and previous_def does indeed allow overriding the setter method. As a newcomer to crystal/clear I would say this was not particularly obvious!

I ended up writing a before :validate hook method to perform this cleanup. This would seem to be the way to go since column= methods are not called when mass assigning values (unlike in sequel from which I was porting some code).

mloughran avatar Jul 14 '22 20:07 mloughran