How to find and remove part of a string in Rails Console - ActiveRecord
Asked Answered
A

4

5

I'm looking for a way in the rails console to find any values that finish with a particular string and remove that string from the value.

Something along the lines of:

Model.all.each{|x| x.duration.slice!(" weeks")}.where("duration IS NOT NULL") 

So that values such as "47 weeks" simply become "47", but there isn't a Slice method for ActiveRecord/ActiveModel and I don't know the equivalent.

Any ideas??

Thanks in advance...

Addington answered 19/4, 2016 at 7:9 Comment(0)
S
6

You can use where("column_name LIKE <matcher>") syntax to search for models with the column having the matching substring:

matching_models = Model.where("duration LIKE '% weeks'")

Then iterate over the result, using gsub to replace the column value

matching_models.find_each do |model|
  model.update_column(:duration, model.duration.gsub(/ weeks$/, "")
end

Some relevant points:

  • Use find_each instead of each as it will load data in batches to better use memory.

  • gsub is used to replace the existing string. The / weeks$/ regex matches strings ending in " weeks".

  • model.update_column is used instead of update_attributes to bypass ActiveRecord validations and callbacks. You can use update_attributes if you want to run validations and callbacks.

Sessler answered 19/4, 2016 at 7:17 Comment(0)
E
3

The accepted answer works correctly but will get noticeably slow if you have a few thousand records ending with " weeks" or more, because Rails has to grab and instantiate all matching records from the table.

In general, it is preferable to leave all work to the database engine, if possible, which could be written like this:

Model.where("duration LIKE '% weeks'").
      update_all("duration = SUBSTRING(duration, 1, LENGTH(duration) - 6)")
# => UPDATE `models` SET `models`.`duration` = SUBSTRING(duration, 1, LENGTH(duration) - 6) WHERE (duration LIKE '% weeks')

This query will be much more performant and memory efficient if you have lots of records to update. It uses the update_all Rails method to run the UPDATE query on all matching records in the table and the SUBSTRING function to shorten the duration field by 6 characters, which is the length of the " weeks" string.

Ellynellynn answered 21/4, 2016 at 4:51 Comment(0)
C
2

As @BoraMa says, the accepted answer will take a long time for thousands of records and their answer works for MySQL so here's a PostgreSQL version:

Model.where("duration LIKE '% weeks'").
      update_all("duration = REPLACE(duration, ' weeks', '')")

Rather than trim the last 6 characters this just replaces " weeks" with an empty string. Your question mentions 'finish with a particular string' so here's the regex version which anchors to the end of the string:

Model.where("duration LIKE '% weeks'").
      update_all("duration = REGEXP_REPLACE(duration, ' weeks$', '')")
Cecilia answered 19/3, 2021 at 19:9 Comment(0)
S
0

You can also use column_name.to_i to get 47 from string 47 weeks

Smallage answered 19/4, 2016 at 8:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.