Difference Between downcase and downcase! in Ruby
Methods with an exclamation mark at the end are often called bang-methods. A bang method doesn't necessarily modify its receiver as well as there is no guarantee that methods without a exclamation mark doesn't.
It's all very well explained in this blog post. To quote the post:
The ! in method names that end with !
means, “This method is dangerous”—or,
more precisely, this method is the
“dangerous” version of an otherwise
equivalent method, with the same name
minus the !. “Danger” is relative; the
! doesn’t mean anything at all unless
the method name it’s in corresponds to
a similar but bang-less method name.
and
The ! does not mean “This method
changes its receiver.” A lot of
“dangerous” methods do change their
receivers. But some don’t. I repeat: !
does not mean that the method changes
its receiver.
Ruby on Rails Tutorial -- strange uses of upcase/downcase and case-insensitivity
seems to me that by converting to upper case, and storing the data as lower case, you make sure they're not equivalent, so the "case_sensitive:false" part of the validator will really be tested.
Rails: What does this shorthand '.map(&:downcase)' mean?
It is the same as:
self.keywords = [title, author, description].map { |keyword| keyword.downcase }.join(' ')
has_key combined with .downcase isn't working properly
What you are experiencing is becuase you're calling String#downcase!
and not String#downcase
. If you run IRB and test this out you'll see:
> "TeSt".downcase!
=> "test"
> "test".downcase!
=> nil
> "TeSt".downcase
=> "test"
> "test".downcase
=> "test"
What happens here is that if the string is already lowercase then String#downcase!
will return nil
; however, the alternative String#downcase
will always return a valid lowercase string even when the initial string is already lowercase. It's also important to note that String#downcase!
modifies the string object referenced by the variable which may or may not be a desired result.
> s = "TeSt"
=> "TeSt"
> s.downcase!
=> "test"
> s
=> "test"
This is generally not what you'd like to do, instead you want to call the unmarked downcase
which returns a new String object that represents the lowercase version of the string.
Downcase words except their first character
Advanced regular expressions: positive lookbehind
"My name is MARC".gsub(/(?<=\w)\w+/) { |s| s.downcase }
#=> "My name is Marc"
Even shorter (as suggested by @falsetru):
"My name is MARC".gsub /(?<=\w)\w+/, &:downcase
#=> "My name is Marc"
Why would downcase the key of has not work in this case?
map wants to do the operation on each pair and return 1 value.
When you use [] it is returning one value - an array. When you use k.downcase, v it can do the k.downcase part, but then it doesn't know what , v
means. It's confused about trying to have a result of two things when it should be one. When those are inside the []
(array) brackets they are just elements of the one array that is returned.
`
Before validation method breaking spec with 'undefined method downcase'
As per the documentation exemplifies, you could use attribute_present?
before:
class User < ApplicationRecord
before_validation :normalize_params, on: %i[create update]
validates :email, presence: true, uniqueness: true
validates :username, presence: true, uniqueness: true
private
def normalize_params
titleize_name
downcase_email
# You can any other here.
end
def titleize_name
self.name = name.downcase.titleize if attribute_present? 'name'
end
def downcase_email
self.email = email.downcase if attribute_present? 'email'
end
end
Note you can:
- Use
%i[]
to create an array of symbols. - Validates presence and uniqueness by separating them by comma.
- Prefer the
is_expected.to
thanshould
syntax (it { is_expected.to validate_presence_of :attribute }
) - Separate each of your attribute modifications to easily work and include them.
- Avoid using hash rocket when not needed. See
ruby-style-guide#hash-literals
.
Related Topics
Errno::Enoent No Such File or Directory Rails 4
Rubymine 6.0.2, Unable to Debug
Ruby ".Downcase! " and "Downcase" Confusion
Where Are Catch and Throw Useful in Ruby
Wicked_Pdf Is Not Rendering Header
Jekyll Plugin Not Work on Github
Why Non-Explicit Splat Param Plus Default Param Is Wrong Syntax for Method Definition in Ruby 1.9
Error When Trying to Create Heroku App on Windows
Undefined Method 'Has_Attached_File' with Paperclip 2.3.8 Gem for Rails 2 Using Ruby 1.8.7
How to Create Automatically a Instance of Every Class in a Directory
Map Array of Ints to Nested Array Access
Rails Adding Multiple Objects to an Empty Array
Defined' and 'Unless' Not Working as Expected
Encoding::Undefinedconversionerror: "\Xc2" from Ascii-8Bit to Utf-8
How to Http Post Stream Data from Memory in Ruby
Getting Hash with Symbol as Keys for Mongo in Rails
How to Fix Ruby Script Which Fails with Encoding Error: "\Xd8" on Us-Ascii