19 Mar 2022
I was in a situation where a key may or may not be present in a Hash (options
), and I needed to do two different, but very similar things. The general if
/else
seemed like too much:
if options[:uniqueness]
if options[:scope]
validates attribute, :uniqueness => { :case_sensitive => true, :scope => options[:scope] }
else
validates attribute, :uniqueness => { :case_sensitive => true }
end
# ...
end
So I found a nice one-liner that cleaned it up!
if options[:uniqueness]
uniqueness_options = {
:case_sensitive => true,
:scope => ( options[:scope] if options.has_key?(:scope))
}.compact
validates attribute, :uniqueness => uniqueness_options
end
Another approach was to use tap
(which I need to lookup more about)
{ :a => 'animal' }.tap { |hash|
hash[:b] = 'banana' if true
}
which maybe is better since it supports earlier Ruby version and is still very readable.
18 Mar 2022
When writing a method with an options Hash, how best do you specify default key/value pairs that can be safely overwritten?
Well, if it’s just one this should be fine:
def foo(k: 1)
p k
end
foo({ k: 'apple'})
but if you’re dealing with a double spat, Hash#merge
is your friend.
# Can also use a constant here to help document what the defaults are
DEFAULTS = {
fruit: 'apple',
color: 'lavendar',
feels: 'sleepy'
}
def blog(**options)
options = DEFAULT.merge(options)
# ...
end
merge
works like this:
h1 = { "a" => 100, "b" => 200 }
h2 = { "b" => 254, "c" => 300 }
h1.merge(h2) #=> {"a"=>100, "b"=>254, "c"=>300}
h1 #=> {"a"=>100, "b"=>200}
prioritizing the values in the Hash argument.
There’s also apparently Hash#reverse_merge
in Rails, which handles duplicate values the other way— prioritizing the entries in the Hash calling the method.
h1 = { "a" => 100, "b" => 200 }
h2 = { "b" => 254, "c" => 300 }
h1.reverse_merge(h2) # => {"b"=>200, "c"=>300, "a"=>100}
17 Mar 2022
This is a reminder to uninstall unused gems for each of the Ruby versions you have installed. Switch to the desired Ruby version and run
This uninstalls unused versions of gems that are installed. I’m not sure how Ruby determines which gems are not in-use, but it’s handy because the different gem versions installed really add up. Run this command every few months. I don’t remember the last time I did this but I freed up like 3+GB of storage today just cleaning up gems.
15 Mar 2022
I never used serialize
before since Postgres supports :json
and :jsonb
columns which are better. It’s still useful that I can still store Hash data in the sqlite db text
column— especially if my students, who aren’t using Postgres, want to do complicated stuff like OAuth and need to store some credentials.
Re: Spotify API
# in the action of the callback URL...
spotify_user = RSpotify::User.new(request.env['omniauth.auth'])
user = User.find_or_create_by({ :spotify_info => spotify_user.to_hash })
# spotify_info :text
#
class User < ApplicationRecord
serialize(:spotify_info)
end
14 Mar 2022
I knew that OAuth 2 was replacing OAuth 1, but since I wasn’t actively working on projects that used OAuth 1 I didn’t really internalize it until I was helping someone use the rspotify
gem recently and ran into a bunch of issues trying to follow the instructions in the README.
The README is a trap.
Even though it appears to have been updated semi-recently, the setup instructions are outdated. I had to reference an issue from 2016 to figure out why. I searched some other errors and found the omniauth
upgrade guide which mainly clarified that the auth request needs to be a POST
instead of a GET
.