@loumarven Disciple. Husband. Dad. Dev. Learner.

Inifinite Loop in Rails when Calling update_attribute in an after_save Callback

So I have been learning Ruby on Rails these past months, and I’m steadily learning the basics of the said framework. In this blog, I would like to share about one of the issues I encountered while building an app and the solution I found for the problem.

The Problem

I encountered an infinite loop issue in my Rails app. What I’m basically trying to do is update a column in a table for a model after its nested attributes are saved. I placed my computation in an after_save callback like this (method name arbitrary):

# app/models/nested_model.rb
after_save :update_the_column
# …
def update_the_column
  the_value = compute_value
  parent_model.update_attribute(:the_column, the_value)

I would complete the form (with nested attributes) and submit it but it seemed stuck and would not redirect. So I looked at the logs and there I realized that part of my code was executing infinitely. Time to investigate why.

First thing I did after learning about the problem was to practice technical sophistication (DuckDuckGoing, really). The top search result, unsurprisingly, was from our good friends from over Stack Overflow. The question was asked many years ago, so I was unsure if the answers would help or lead me to finding a solution for my problem. Still I kept reading the answers and learned what was causing the issue.

The Root Cause

Calling update_attribute in an after_save callback invokes the save method which then invokes the after_save callback, thus creating an infinite loop. See source code for details.

Looking at update_attribute’s description in the official Rails documentation, we see that:

  • Validation is skipped.
  • Callbacks are invoked.
  • updated_at/updated_on column is updated if that column is available.
  • Updates all the attributes that are dirty in this object.

The Solution

To solve my infinite loop issue, I made the following changes in my code based on this answer in the same thread.

# app/models/nested_model.rb
after_commit :update_the_column
# …
def update_the_column
  the_value = compute_value
  parent_model.update_column(:the_column, the_value)

I changed the callback from after_save to after_commit, so my computation is only triggered when the database transaction (commit) is complete. Updating the column in the table was done through update_column. From its description, we see that for update_column/s:

  • Validations are skipped.
  • Callbacks are skipped.
  • updated_at/updated_on are not updated.

Applying the changes above solved my issue. While it may not be “The Rails Way” of solving the said problem, I am just glad to have solved this issue and I have learned a few things as I progress in learning Ruby on Rails. If you have the same problem and are considering the solution above, take into account what is mentioned in the method’s description and tweak as you see fit for your application’s context.

Lessons Learned

  • Read the application logs. They provide clues to what is going on in your code.
  • Look around for similar issues. Someone most likely have already encountered the same thing and have found a solution.
  • Understand what was causing the issue.
  • Understand how the changes solves your issue.
  • Read the guides!

I still find the last one intimidating to do most of the time, but reading the guides have really helped a lot and I’ve noticed that they’re beginning to make sense to me more and more.


For the experienced Rails developers here, what is the “Rails way” or recommended approach to solve this issue? I’d love to learn from you.

Getting a Good Old Jekyll Theme to Work on Gitlab Pages

I recently set up my blog using Jekyll and decided to host it on Gitlab Pages. While Gitlab Pages provides documentation on how to set up a static website (and host for free!) using their platform, it’s not as easy as it looks, especially when dealing with a good old Jekyll theme. After spending some time looking for a Jekyll theme to use for my blog, I went on with Lanyon. This post will guide you through the steps and challenges involved in getting the Lanyon Jekyll theme to work on Jekyll 4 and Gitlab Pages.


Let’s gets started.

1. Obtain a local copy of the Lanyon theme

Lanyon is hosted on Github.

Download a zip archive of Lanyon:

wget https://github.com/poole/lanyon/archive/master.zip
unzip master.zip

2. Test run Lanyon locally

cd lanyon-master
jekyll serve

As mentioned above, Lanyon is a good old Jekyll theme. Lanyon was last updated to run on Jekyll 2.x, but you’ll want to use the latest version (v4.0) to benefit from the new features and security updates. When you run the jekyll server for the first time, depending on the version of Jekyll installed on your localhost, you may be prompted with the following error:

Configuration file: /Users/loumarven/Documents/code/my_blog/test/lanyon-master/_config.yml
       Deprecation: You appear to have pagination turned on, but you haven't included the `jekyll-paginate` gem. Ensure you have `plugins: [jekyll-paginate]` in your configuration file.
            Source: /Users/loumarven/Documents/code/my_blog/test/lanyon-master
       Destination: /Users/loumarven/Documents/code/my_blog/test/lanyon-master/_site
 Incremental build: disabled. Enable with --incremental
Since v3.0, permalinks for pages in subfolders must be relative to the site source directory, not the parent directory. Check https://jekyllrb.com/docs/upgrading/ for more info.

3. Create a Gemfile and add the jekyll and jekyll-paginate-v2 gems

It’s now time to use Jekyll 4.0. Also, as you see on the error above, this theme has pagination turned on, so we’ll use a compatible jekyll pagination gem. I originally used the jekyll-paginate gem but later found out that this gem is no longer under active development as of Jekyll 3. The good thing is, there’s the jekyll-paginate-v2 gem that supports Jekyll 3.0 and newer.

In your Gemfile, type the following:

source "https://rubygems.org"

gem 'jekyll', '~> 4.0.0'
gem 'jekyll-paginate-v2', '3.0.0'

Install these gems:

bundle update

4. Update _config.yml to use the jekyll-paginate-v2 gem

  enabled: true
  debug: false
  collections: 'posts'
  per_page: 5
  permalink: '/page/:num/'
plugins: [jekyll-paginate-v2]

5. Update index.html to use pagination

layout: default
title: Home
  enabled: true

You’ll also need to put a forward slash (/) before the paginator.next_page and paginator.previous_page for the Older and Newer links at the bottom of the page:

<a class="pagination-item older" href="{{ site.baseurl }}/page/{{paginator.next_page}}">Older</a>
<a class="pagination-item newer" href="{{ site.baseurl }}/page/{{paginator.previous_page}}">Newer</a>

6. Test the modifications made to Lanyon

bundle exec jekyll serve

Looking good so far. The previous error no longer shows up. Visit to check the build result. You should see the homepage with the 2 posts properly displayed.

7. Test if pagination works

In order to test the pagination, we’ll need to have more posts inside the _posts directory.
Create several arbitrary posts and run the jekyll server again with bundle exec jekyll serve.
Click on the Older and Newer links at the bottom of the page to check if pagination already works.

8. Update index.html to properly display each post when clicking the post title

Try to click a post title to be directed to the post itself.
The post would not be displayed as the URL is incorrect.
You’ll get something like in the URL.
To fix this, remove the forward slash (/) between site.baseurl and post.url (the href for post.title).

<a href="{{ site.baseurl }}{{ post.url }}">
  {{ post.title }}

Thanks to this Github issue comment for the solution.
Click on a post again and it should now be displayed.

At this point, Lanyon should work on your localhost.
Time to deploy on Gitlab Pages.

9. Create your repository’s CI file

In Lanyon’s root directory, create a .gitlab-ci.yml file and put the following:

  - bundle install

  stage: test
  - bundle exec jekyll build -d test
    - test
  - master

  stage: deploy
  - bundle exec jekyll build -d public
    - public
  - master

Gitlab CI/CD will refer to this yaml file to build your Gitlab Pages site.
Note: To understand how to create your own .gitlab-ci.yml for your site, check out this documentation

10. Rename the Lanyon root folder to its appropriate project name

If using this theme for your user page (i.e. personal website/blog), rename the folder to your-gitlab-username.gitlab.io. If using this theme for a project’s page, rename the folder to your desired projectname.
See this table for more info on how you may want to name this folder.

11. Update _config.yml with the correct URL and baseurl

Here’s a sample:

url:     'https://loumarven.gitlab.io'
baseurl: '/lanyon-gitlab' # because the project (and folder) name is `lanyon-gitlab`
# baseurl: '' # use empty string if your site is for your user or group website

12. Ignore the Jekyll cache

Let’s also update .gitignore before we push to our remote repository (next step).
In .gitignore, add the following to ignore the Jekyll cache:


13. Create a repository in Gitlab and push your updated Lanyon source code to the remote repository

When creating a project in Gitlab, give this project the same name as your Lanyon root folder name in the previous step.
Next, execute the commands below in Lanyon’s root folder:

git init
git remote add origin git@gitlab.com:your-username/your-project-name.git
git add .
git commit -m "Initial commit"
git push -u origin master

Gitlab CI/CD will run the .gitlab-ci.yml script as soon as you push to the repository.
To view the build result, select Jobs under CI / CD for your Gitlab project.
A passed status indicates that the build succeeded.

You may now try to check your Jekyll-powered Gitlab Pages site by visiting its URL.
What did you get?
In my case, the page was displayed but the styling (CSS) was not applied. CSS not applied for Lanyon Gitlab Pages site
Using the browser’s Inspect Element tool, we’ll see that the CSS file could not be found (404).
CSS not found for Lanyon Gitlab Pages site

The next two steps solves the CSS issue.

14. Rename the public folder to something else

Our problem is that the CSS files could not be found.
So what is causing that?
According to the Gitlab Pages documentation:

GitLab will always deploy your website from a very specific folder called public in your repository.

Because Gitlab will deploy to the public folder, everything inside of Lanyon’s public folder where the assets (images, CSS) are stored will be ignored.
This took me some time (and grit) to figure out.
On your Gitlab project, you can browse the files generated by the job and you’ll see that the asset files are missing.

To solve this, we simply rename Lanyon’s public folder to something else. assets would be a reasonable name.

mv public assets

15. Use relative_url

Prepend the baseurl value to the assets URL and in the links in Lanyon’s sidebar using relative_url.

# _includes/head.html
<!-- CSS -->
<link rel="stylesheet" href="{{ "/assets/css/poole.css" | relative_url }}">
<link rel="stylesheet" href="{{ "/assets/css/syntax.css" | relative_url }}">
<link rel="stylesheet" href="{{ "/assets/css/lanyon.css" | relative_url }}">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=PT+Serif:400,400italic,700%7CPT+Sans:400">

<!-- Icons -->
<link rel="apple-touch-icon-precomposed" sizes="144x144" href="{{ "/assets/images/apple-touch-icon-precomposed.png" | relative_url }}">
<link rel="shortcut icon" href="{{ "/assets/images/favicon.ico" | relative_url }}">
# _includes/sidebar.html
<a class="sidebar-nav-item{% if page.url == node.url %} active{% endif %}" href="{{ node.url | relative_url }}">{{ node.title }}</a>

Commit and push your changes.
You now should see the Lanyon CSS styles applied to this Gitlab Pages site.
All green.
Lanyon Gitlab Pages working

Making Time for Learning

Pile of books Photo by NeONBRAND on Unsplash

You’ve always wanted to start learning something new to improve your skills. It may be a technical or soft skill you’ve been wanting to learn about/improve on. The problem is, you don’t have the time to spend for it. You’ve got work, have to commute, got a family to lead, got children to take care of — you have a life to live. So how do you make time for learning when your plate is seemingly already full? In this post, I’m going to share my approach to make time for learning. Let’s get started.

Disclaimer: This does not aim to be an ultimate guide to making time for learning. I do hope though that this post helps you.

1. Make a commitment.

Unless you commit to it, learning will just stay a desire. You think about it, you talk about it, but you make no effort to put in hours to actually do it. Your desire to learn is only the starting point. The goal is to turn that desire into a commitment. The commitment you make will push you and create grit in you to keep learning even when you face obstacles or you just honestly don’t feel like doing it.

One practical way of making a commitment is telling others about it. Tell your family about it. Tell your close friends about it. Tell someone you trust about it. Ask them a favor to check on your progress from time to time and encourage you to keep at it despite the challenges (or excuses) you may have.

keep_learning if self.committed?

2. Evaluate your daily routine.

Get a pen and paper, sit down and list your usual activities and the amount of time you spend for every activity. The list should include all activities that consume a significant amount of your time. If an activity takes at least 30 minutes, include that in the list.

Next, for every activity you’ve listed and its corresponding amount of time spent, indicate whether that activity adds value or not. Essential activities obviously add value, while the non-essential ones oftentimes don’t. A trivial example appears below:

Activity Duration (hours) Adds Value?
Quiet time 0.5 Yes
Exercise 0.5 Yes
Breakfast with family 0.5 Yes
Preparing for work 0.5 Yes
Commute/drive to work (to and fro) 1 Yes
Work 8 Yes
Miscellaneous errands 1 Yes
Dinner with family 0.5 Yes
Social media/web browsing 1 No
Television 1 No
Play/quality time with family 1.5 Yes
Sleep 8 Yes

Based on the example above, we see that we have two usual activities that don’t really add value. You can then use the time you spend for these non-essential activities for learning.

Including learning time in your daily activities, your daily schedule now looks like:

Activity Duration (hours) Adds Value?
Quiet time 0.5 Yes
Exercise 0.5 Yes
Breakfast with family 0.5 Yes
Preparing for work 0.5 Yes
Commute/drive to work (to and fro) 1 Yes
Work 8 Yes
Miscellaneous errands 1 Yes
Dinner with family 0.5 Yes
Social media/web browsing 1 No
Television 1 No
Learning time 2 Yes
Play/quality time with family 1.5 Yes
Sleep 8 Yes

Easier said than done, and your routine may vary from day-to-day, but the point is, you can make time for learning, given that you have activities that don’t add value and you are willing to sacrifice them for one that does. If you have time for entertainment (just like the trivial example above), then most probably you’ll be able to allot time for learning.

Am I saying here that you get rid of these non-essential activities for good? It’s up to you. You may choose to lessen the time you spend for these non-essential activities. Spending 30 minutes or less for these things won’t hurt. I just think that regularly spending hours for entertainment is unproductive. Again, it’s up to you.

You can make time for learning, given that you have activities that don’t add value and you are willing to sacrifice them for one that does. If you have time for entertainment, then most probably you’ll be able to allot time for learning.

3. Put it in schedule.

Making time for learning is likely to happen if you put it in schedule. Don’t decide what time to do it on a day-to-day basis. Learning will become a habit if it’s part of your schedule. If not, you will end up procrastinating and eventually give up.

Here are some guide questions you can ask yourself as you decide where to put learning in your schedule:

  • What time of the day do you still have the energy to learn/study?
  • What time of the day are there less distractions so you can focus?
  • What period of the day can you spend for learning such that the effect/compromise on your priorities is little to none?

After careful thought on your considerations, you can now put “time for learning” in your schedule. Let’s update our trivial example (others omitted for brevity):

Activity Duration (hours) Adds Value? Schedule
Quiet time 0.5 Yes 5:00 AM
Exercise 0.5 Yes 5:30 AM
Learning time 2 Yes 6:00 AM
Breakfast with family 0.5 Yes 8:00 AM
Preparing for work 0.5 Yes 8:30 AM

Of course, putting it in schedule is one thing and following it is another. At first, it can get really challenging to follow your schedule. You may not always hit your schedule, but try not to get too far off from it. Commit to do your best to follow your schedule.

4. Focus. Focus. Focus.

Not only does learning require a lot of time — effective learning also requires focus. There are many resources that share tips on how to stay focused. Choose whatever is applicable to you. For instance, I find that the Pomodoro Technique helps me a lot in staying focused. You would also want to minimize the distractions while you study. While you cannot fully eliminate all distractions, make an effort to at least minimize them. Here are some practical ways you can minimize distractions:

  • Turn off unimportant notifications on your phone and computer.
  • If learning offline, you may turn the WiFi or cellular data off to keep you from checking stuff on the internet while you study.

A side note on distractions:
Your child wanting to play with you or your spouse wanting to spend time with you is NOT a distraction. Go ahead and pause your reading (or that tutorial video) and attend to them. It is important though that you let them know about your commitment to learn and that it requires time. Ask them if the schedule works or not and adjust as necessary.

5. Rest well.

Yes, you need to rest well to be able to make time for learning. Your health is a priority, so you must also schedule time for rest. When your mind and body are well rested, chances are your energy and focus are way better (remember, learning takes time, energy and focus). You won’t miss out so much on your learning if you take a day or two of rest from it. Perhaps do something else outside of learning — take a walk with your family, spend longer time to just quiet yourself and hear from God, catch up with friends, etc.


  1. Make a strong commitment to make time for learning. Tell others about it and update them on your progress.
  2. Evaluate your routine and allot the time you spend for activities that don’t add value to learn instead.
  3. Put time for learning in your schedule and commit to do your best to follow it.
  4. Focus and minimize distractions. If priorities knock on you while you’re in the zone, attend to them.
  5. Rest well. You need it.

puts 'Hello, world!'

Most programmers start dabbling with a programming language by printing that good old “Hello, world!” string on the screen (or console/terminal). In Ruby, this is accomplished by typing (and running) the following:

puts 'Hello, world!'

In keeping with that tradition, this post marks the start of blogging my learning journey!

We have different reasons why we put up our website and blog. Here are my reasons:

Document the things I learn.

I love learning, and I learn most when I try to solve problems. Currently, I am learning about full stack web development. I think what’s missing in my learning process though is being able to document the things I learn. My brain, like a RAM, is volatile. I need to find a way to store them, especially how I’m able to solve the problems I encounter. The moment I forget how I solved a problem, I just need to refer to that document and follow the steps I previously did. By doing so, I get to:

  • save time
  • make the problem solving process less painful

Blogging gives me that opportunity.

Share my content with others who might find it useful.

The good thing about putting up your content (say, tutorial) online is that others get to benefit from it too, besides the content’s author. There might be someone out there who’s currently looking for a solution to a problem which I might have solved already, and sharing how I solved the same problem would also help them save time and make the problem solving process less painful. How many of us have benefited so much from other people’s blogs posts that address and solve a similar problem we face? I am one of the many and I can’t thank these people enough who took the time to write down, document and share their approach (for free) so others would benefit. By putting up and sharing my content online, not only do I get to document the things I learn, but I also get to share it with others and so somehow help them.

Track my learning progress.

I can’t really tell how much progress I am making unless I know where I started. If I blog regularly about the things I learn, I get to see how I progress. I’m excited to see in the future how I’m beginning to grasp and understand what used to be a confusing topic or paradigm. This blog site would also serve as a reminder to myself (at times I’m stuck, down or frustrated) that I, by the grace of God, was able to face and solve challenging problems before, and the same can happen to the current challenge/problem I face.

So there you go with my reasons why I’m starting to blog! Anyway, that first hello world program above is rather short, so I’m ending this post before it gets too long. Till next time.

puts 'Goodbye!'