I'm working in Ruby and ActiveRecord albeit not full Rails; it's really just Sinatra serving the backend. I have an Artist model, that only contains an id and a name. What I'm aiming to do is capitalize (by use of titleize) each name, such that if any word follows a space it's to be capitalized.
I can make this happen with names in an array (self.cleanup
works) but I can't do it within an object. (self.fixer
doesn't) I have pictures below of each function's Pry output.
class Artist < ActiveRecord::Base
has_many :songs
has_many :genres, through: :songs
has_many :reviews, through: :songs
accepts_nested_attributes_for :genres, :songs
# stores an array of all the artists' names
def self.names
all.pluck(:name)
end
# cleans up the names of each Artist, capitalizes all
def self.cleanup
unique_array = self.names.uniq
unique_array.map { |string| string.titleize }
end
# capitalizes each name within the Artist model
def self.fixer
self.all.each do |artist|
artist.name.titleize
end
end
end
Here is my Artist.fixer function, which doesn't work
Here is my Artist.cleanup function, which does
CodePudding user response:
When calling
self.all.each { |artist| artist.name.titleize }
Ruby will iterate over all artists
and call titleize
on their name. But titleize
will not change the string on which it is called, it only returns a titleized version of the string. Because you do not store the returned titleized string it is not persisted after the each
call.
Instead, change your method to this and reassign the titleized version to the artist's name:
def self.fixer
self.all.each do |artist|
artist.name = artist.name.titleize
end
end
Please note that this only changes the artist's name in the array returned from the fixer
method. it does not update and permanently fix the name in the database. Therefore you might want to consider fixing names before saving the name into the database. Then you would not need to fix it each time again when reading a record from the database.
CodePudding user response:
Managed to figure it out, as a two-stepper for anyone confused reading this in posterity.
(1) Defining the function, hereby called title_fixer. (2) Putting a before_save :title_fixer header within my class.
class Artist < ActiveRecord::Base
has_many :songs
has_many :genres, through: :songs
has_many :reviews, through: :songs
accepts_nested_attributes_for :genres, :songs
before_save :title_fixer
## corrects the title capitilzation
## always launched before an artist saves
def title_fixer
## add a case to capitalize after [&, -, /]
self.name = self.name.split(/ |\_/).map(&:capitalize).join(" ")
end
end
Only thing left to do is work with the regex to include cases for "&", "-", and "/" -- for example to capitalize "Hip-hop -> Hip-Hop" and "R&b/soul -> R&B/Soul". Otherwise, it seems to work well.