Ruby on Rails Tutorials

Understanding Tricky Concepts for Junior Developers

Understanding Tricky Concepts for Junior Developers

Hey there! 👋 Let's break down some Rails concepts that might seem confusing at first. I'll explain everything in simple terms with lots of examples.

1. The Mystery of Routes

Routes can be confusing when you're starting out. Let's understand them better:

# config/routes.rb

# ❌ Common Mistake: Adding routes without understanding them
resources :posts
resources :comments
resources :users

# ✅ Better: Understanding what each route does
resources :posts do
  # This creates routes like:
  # GET    /posts          -> posts#index    (shows all posts)
  # GET    /posts/new      -> posts#new      (shows form for new post)
  # POST   /posts          -> posts#create   (creates a new post)
  # GET    /posts/:id      -> posts#show     (shows one post)
  # GET    /posts/:id/edit -> posts#edit     (shows edit form)
  # PATCH  /posts/:id      -> posts#update   (updates a post)
  # DELETE /posts/:id      -> posts#destroy  (deletes a post)
end

# Want to see all your routes? Run:
# rails routes

Why This Matters

When you use resources :posts, Rails creates 7 different routes. Each route connects to a specific action in your controller. Understanding this helps you:

  1. Know which URL to use
  2. Understand what each action does
  3. Fix routing errors

2. Params: Where Do They Come From?

Params often seem magical. Here's where they come from:

# Three main sources of params:

# 1. From the URL
# URL: /posts/123
get '/posts/:id' # -> params[:id] will be "123"

# 2. From form submissions
# In your view (posts/new.html.erb):
<%= form_with model: @post do |f| %>
  <%= f.text_field :title %>
  # When submitted, params will have:
  # params[:post][:title]
<% end %>

# 3. From query strings
# URL: /posts?category=ruby
# -> params[:category] will be "ruby"

# In your controller:
class PostsController < ApplicationController
  def show
    # params is a hash-like object
    puts params # Try this to see what's in params!

    # Common pattern:
    @post = Post.find(params[:id])
  end

  def create
    # ❌ Common Mistake: Using params directly
    @post = Post.create(params[:post]) # UNSAFE!

    # ✅ Better: Use strong parameters
    @post = Post.create(post_params)
  end

  private

  def post_params
    # This is called "strong parameters"
    params.require(:post).permit(:title, :content)
  end
end

3. What's the Deal with Instance Variables (@)?

Instance variables (@) in Rails are how we share data with our views:

# app/controllers/posts_controller.rb
class PostsController < ApplicationController
  def index
    # ❌ Common Mistake: Using a regular variable
    posts = Post.all # The view can't see this!

    # ✅ Better: Using an instance variable
    @posts = Post.all # The view can see this!
  end
end

# app/views/posts/index.html.erb
<% @posts.each do |post| %>  # This works!
  <%= post.title %>
<% end %>

Why We Use Instance Variables

  • Regular variables (without @) can't be seen by the view
  • Instance variables (@) are shared with the view
  • They're like a bridge between your controller and view

4. The Difference Between = and <%=

This trips up many beginners. Here's the difference:

<%# In your view (.html.erb file) %>

<% name = "Alice" %>   
<%# Just runs Ruby code, doesn't show anything %>

<%= name %>           
<%# Runs Ruby code AND shows the result %>

<%# Common examples: %>

<%# ❌ Common Mistake: Using <% when you want to show something %>
<% post.title %>      <%# Nothing appears! %>

<%# ✅ Better: Use <%= when you want to show something %>
<%= post.title %>     <%# Shows the title! %>

<%# When to use each: %>
<% @posts.each do |post| %>  <%# Just Ruby code, no output %>
  <%= post.title %>          <%# Want to show this! %>
<% end %>

5. Associations: How Are Models Connected?

Models can be connected in different ways. Here's how to understand them:

# belongs_to: "I belong to ONE thing"
# has_many: "I have MANY things"

# Example: A Post has many Comments
class Post < ApplicationRecord
  has_many :comments
  # This means:
  # - A post can have many comments
  # - You can do: @post.comments
  # - You can do: @post.comments.create(...)
end

class Comment < ApplicationRecord
  belongs_to :post
  # This means:
  # - Each comment belongs to ONE post
  # - You can do: @comment.post
  # - Comments MUST have a post_id
end

# Using associations:
# ❌ Common Mistake: Not understanding the relationship
@post.comments = Comment.create(...)  # Wrong!

# ✅ Better: Using the relationship properly
# Creating a comment for a post:
@comment = @post.comments.create(content: "Great post!")

# Finding a post's comments:
@comments = @post.comments  # Gets all comments for this post

6. The Different Types of Render

Rendering in Rails can be confusing. Here's what each type does:

class PostsController < ApplicationController
  def show
    @post = Post.find(params[:id])

    # Different ways to render:

    # 1. Implicit render (no render statement)
    # Rails automatically renders show.html.erb

    # 2. Explicit render of a view
    render 'show'  # Same as above

    # 3. Rendering a different view
    render 'preview'  # Renders preview.html.erb

    # 4. Rendering JSON (for APIs)
    render json: @post

    # 5. Rendering with status
    render 'show', status: :not_found  # 404 status
  end

  def create
    @post = Post.new(post_params)

    # ❌ Common Mistake: Forgetting about render vs redirect
    render 'index'  # This might cause errors!

    # ✅ Better: Redirect after changing data
    if @post.save
      redirect_to @post  # Goes to show page
    else
      render 'new'      # Shows the form again
    end
  end
end

7. Callbacks: What Happens When?

Callbacks are methods that run at certain times. Here's how they work:

class Post < ApplicationRecord
  # Callbacks run in this order:
  before_validation :cleanup_title
  after_create :notify_followers
  before_destroy :can_be_deleted?

  private

  # ❌ Common Mistake: Doing too much in callbacks
  after_save :do_everything  # Don't do this!

  # ✅ Better: Simple, focused callbacks
  before_validation :cleanup_title
  def cleanup_title
    self.title = title.strip if title.present?
  end

  # This runs after creating a new post
  after_create :notify_followers
  def notify_followers
    # Send notifications about new post
  end

  # This runs before deleting a post
  before_destroy :can_be_deleted?
  def can_be_deleted?
    throw(:abort) if comments.exists?
  end
end

8. Common Rails Console Commands

The Rails console is your friend! Here are some useful commands:

# Start the console
rails c

# Find things
Post.first          # Get the first post
Post.last           # Get the last post
Post.find(123)      # Find post with id 123
Post.where(published: true)  # Find all published posts

# Create things
post = Post.new(title: "Hello")  # Just creates in memory
post.save                        # Saves to database

# Or do it in one step:
Post.create(title: "Hello")      # Creates and saves

# Update things
post = Post.find(123)
post.update(title: "New title")  # Updates the post

# Delete things
post = Post.find(123)
post.destroy                     # Deletes the post

# Reload things (get fresh from database)
post.reload

# Check if valid
post.valid?        # Returns true or false
post.errors        # See any errors