DEV Community

Takashi Masuda
Takashi Masuda

Posted on • Originally published at masutaka.net

Created a Rails 8 Learning Repository and Started Recovering from a 6-Year Blank with Rails Guides and Claude Code

Last month I changed jobs and returned to Rails development after a long time.

With a 6-year gap and only one month available for learning, I needed to efficiently grasp Rails 8's new features and refresh my memory of existing ones.

So I decided to learn by building a working app together with Claude Code while referencing the Rails Guides. I temporarily subscribed to Claude Code's Max plan at USD 100/mo.

Here's the repository I created:

GitHub logo masutaka / trial-rails8

Rails ガイドを元にした素振り

Learning Process

I used the Rails Guides as my main reference material.

1. Reviewing the Basics with Rails Guides

Following Getting Started with Rails, I created /products. I mainly learned about Active Storage (image uploads) and Action Text (rich text).

2. Learning Hotwire and Solid Trifecta

To learn Hotwire and Solid Trifecta, I created /chat and /posts.

  • /chat: Learned Action Cable, Solid Cable, and Stimulus
  • /posts: Learned Turbo Streams/Frames, Active Job, and Solid Queue. Added comment, follow, and notification features to a typical blog functionality

I learned through AI pair programming with Claude Code. The specific workflow was as follows:

  1. Create a GitHub Issue (e.g., #14 Follow Feature)
  2. Have Claude Code create a plan document (e.g., docs/plan-for-issue-14.md)
  3. Have it create a PR based on the plan while understanding the implementation (e.g., #38)

I also utilized AI reviews from CodeRabbit. It pointed out N+1 queries and suggested adding tests, allowing me to maintain quality even in solo development. It's great that it's free for OSS.

Rails Features I Learned

Hotwire

Hotwire is a framework introduced in Rails 7 for achieving SPA-like UX. Hotwire consists of Turbo and Stimulus.

Turbo is further composed of three parts:

  • Turbo Drive: Speeds up page transitions (fetches and replaces HTML on link clicks)
  • Turbo Frames: Updates parts of a page (inline editing of comments, etc.)
  • Turbo Streams: Updates multiple locations simultaneously (updates list and count when adding comments)

Stimulus is a JavaScript framework, but it's a very thin layer for adding minimal JS with HTML as the starting point. I used it for UI control in the chat feature.

I utilized Turbo Streams in the comment feature. When a comment is posted, model callbacks broadcast it to other users' browsers in real-time.

# app/models/comment.rb
class Comment < ApplicationRecord
  belongs_to :post, counter_cache: true
  belongs_to :user

  after_create_commit do
    # Append to comment list
    broadcast_append_to post,
                        target: "comments",
                        partial: "comments/comment",
                        locals: { comment: self, allow_actions: false }
    # Update comment count
    broadcast_replace_to post,
                         target: "comment_count_#{post.id}",
                         partial: "posts/comment_count",
                         locals: { post: post }
  end
end
Enter fullscreen mode Exit fullscreen mode

Solid Trifecta

"Solid Trifecta" introduced in Rails 8 eliminates the need for external middleware like Redis or Memcached.

  • Solid Queue: Database-based Active Job backend
  • Solid Cable: Database-based Action Cable adapter
  • Solid Cache: Database-based cache store (not used this time)

I used Active Job + Solid Queue for the scheduled post feature. When you set a future datetime for published_at, a job executes at that time to publish the article.

# app/jobs/publish_post_job.rb
class PublishPostJob < ApplicationJob
  queue_as :default

  def perform(post_id, scheduled_at)
    post = Post.find_by(id: post_id)
    return unless post

    # Idempotency: Skip if already published
    return if post.published

    # Skip if publish datetime was changed
    return if post.published_at.blank? || post.published_at.to_i != scheduled_at

    post.update!(published: true)
  end
end
Enter fullscreen mode Exit fullscreen mode

You can check job execution status with Mission Control Jobs. Access http://localhost:3000/jobs in development to view job history and queue status in a Web UI.

Other Features

  • Eager Loading: includes/preload/eager_load to prevent N+1 queries
  • has_secure_password + rate_limit: User authentication and rate limiting
  • Counter Cache: Efficient retrieval of comment counts (belongs_to :post, counter_cache: true)
  • Foreign key constraint on_delete: :cascade: Automatically deletes child records when parent is deleted. Used alongside Rails' dependent: :destroy to maintain DB-level integrity
  • Shallow Routing: Specifying shallow: true for nested resources shortens URLs for member actions (show/edit/update/destroy)
  • Polymorphic Association: Used for notification feature. Manages follow and comment notifications uniformly
  • Self-Referential Association: Used for follow feature. Expresses many-to-many relationships with a single follows table

Conclusion

Despite a 6-year gap, I was able to learn efficiently with Rails Guides and Claude Code.

Note that I didn't write many tests this time. The goal was to learn Rails features, so I'll save test learning for another time.

My mental model was stuck around the time of "temporarily disabling Turbolinks...", so I was quite impressed by Hotwire's ability to achieve SPA-like UX with almost no JavaScript. My memory of Rails was that it often served as an API server or adopted React for the frontend, but I now think Hotwire should be considered first.

Solid Queue and Solid Cable are also nice because you can start with just RDS, reducing the number of components.

I'll continue working through the open Issues while continuing to learn.

References

Top comments (0)