Snowman
Snowman

Reputation: 32061

Rails string field in model not saving

video = Video.find(79)
video.url.sub! "http", "https"
video.save

Looking at my server console, when I make this request, I see this:

Video Load (48.7ms)  SELECT `videos`.* FROM `videos` WHERE `videos`.`id` = 79 LIMIT 1
(43.3ms)  BEGIN
(46.4ms)  COMMIT

Notice, no UPDATE call is being made, even though the sub does successfully find a match and make the replacement.

However, doing:

video.url = "https://example.com"
video.save

I see:

(40.6ms)  BEGIN
SQL (41.8ms)  UPDATE `videos` SET `url` = "https://example.com", `updated_at` = '2014-03-18 14:52:22' WHERE `videos`.`id` = 79
(57.8ms)  COMMIT

I've been battling with this for endless hours. Does anyone know what's going on?

Upvotes: 3

Views: 161

Answers (3)

MrYoshiji
MrYoshiji

Reputation: 54882

There is several ways to accomplish what you are trying to do:

video = Video.find(79)
video.url = video.url.sub("http", "https")
video.save
# or
video = Video.find(79)
video.update_attributes(url: video.url.sub!("http", "https")) # does not need a save here

To test and see the changes of a object between updates/saves, you can use the following method:

video = Video.find(79)
video.url.sub! "http", "https"
puts video.changes 
# will display changes as the following:
# { url: ['http://www.youtube.com/watch?v=npvNPORFXpc', 'https://www.youtube.com/watch?v=npvNPORFXpc'] }

Youtube video: alt-J (∆) - Fitzpleasure (Official Music Video)

Upvotes: 3

Dylan Markow
Dylan Markow

Reputation: 124419

Because you're modifying the string in-place using sub!, the url= method that Active Record generates for you never gets called, so it has no idea that you've modified it.

You can either use the video.url = video.url.sub... approach, or you can use the attribute_will_change! method for that specific attribute:

video = Video.find(79)
video.url_will_change!
video.url.sub! "http", "https"
video.save

Upvotes: 4

zwippie
zwippie

Reputation: 15515

This could be related to using a method with an exclamation mark. Most methods ending with a ! have more or less the same issue, that they sometimes return nil.

From the sub! docs:

Returns str if a substitution was performed or nil if no substitution was performed.

Then again, this might not be your problem here.

Upvotes: 0

Related Questions