-
-
Notifications
You must be signed in to change notification settings - Fork 56
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Consider using the Attributes API instead of before_validation callbacks #43
Comments
Sounds like a good idea! I saw the discussion in #34 about using setters, I think whatever you'll end up with will be better than I'm not sure how exactly the attributes API works, but it might give the option to use |
Just made my own for this, since the current implementation is doing in place string manipulation, which won't work in ruby 3. I only overwrote cast, since I don't want it to run when loading from the database. On using multiple filters: it's really easy to create a wrapper type, that calls them both. So I would leave that the application. # frozen_string_literal: true
# Strips whitespace and make nil when string becomes empty.
class StrippedString < ActiveModel::Type::ImmutableString
# taken from strip_attributes gem
# Unicode invisible and whitespace characters. The POSIX character class
# [:space:] corresponds to the Unicode class Z ("separator"). We also
# include the following characters from Unicode class C ("control"), which
# are spaces or invisible characters that make no sense at the start or end
# of a string:
# U+180E MONGOLIAN VOWEL SEPARATOR
# U+200B ZERO WIDTH SPACE
# U+200C ZERO WIDTH NON-JOINER
# U+200D ZERO WIDTH JOINER
# U+2060 WORD JOINER
# U+FEFF ZERO WIDTH NO-BREAK SPACE
MULTIBYTE_WHITE = "\u180E\u200B\u200C\u200D\u2060\uFEFF"
MULTIBYTE_SPACE = /[[:space:]#{MULTIBYTE_WHITE}]/.freeze
def initialize(allow_empty: false)
super()
@allow_empty = allow_empty
end
def cast(value)
return unless value
value = super(value).gsub(/\A#{MULTIBYTE_SPACE}+|#{MULTIBYTE_SPACE}+\z/, "").freeze
value.blank? && !@allow_empty ? nil : value
end
end |
Note that in your example you need to either use: class Something < ActiveRecord::Base
attribute :title, Strippable.new(allow_empty: true)
end or add this to an initializer
and use it like this: class Something < ActiveRecord::Base
attribute :title, :stripped_string, allow_empty: true
end |
Are you still interested in this? I'm thinking about it. i (or someone else) could potentially PR... it's potentially fairly simple code; then again, we could also easily copy/paste fork (thanks for MIT license) your logic into an attribute-based thing in another gem, the code here is pretty simple. Some features aren't really available anymore with an ActiveModel-attribute-based implementation. Like the if/unless stuff -- inside attribute casting, you don't have access to the containing record to make decisions based on it's state. And you have a bit more cumbersome API to specify, as you need to write an So... it's got plusses and minuses. Maybe it's really a separate gem. Would you care to update with your current thinking or plans on things? |
Looking forward to this gem using the new |
@justinko "the new normalize Rails method" -- I haven't heard of that, and am not having luck googling for it. This is something built into rails, not a third-party something? Can you give me a link to something? Thanks! |
Whoops, I got the name wrong! |
One major difference is that:
I don't think I would always want that. For example, if normalization is converting the attribute from |
Oh, that is very interesting, thanks @justinko . It does look like a generalized approach to what is being discussed here. @petrgazarov , I see what you mean, but any appraoch based on the Rails Attributes API is probably going to work like this. Because Rails will always |
Related to #34.
Investigate and perhaps consider using the new attributes API instead of a
before_validation
callback.The text was updated successfully, but these errors were encountered: