---
title: 'A JavaScript developer''s guide to Rails: Where Does Everything Come From?'
teaser: Discover where Rails methods come from and solve the biggest confusion JavaScript
  developers face when learning Rails.
tags: web,best practices,ruby,rails,javascript,development,learning
author: Will Larry
published_on: 2026-01-21
---

As a senior JavaScript developer learning Rails, you've probably felt this frustration: you're reading Rails code and suddenly come across a method like `current_user`, `redirect_to`, or `belongs_to`, and you have no idea where it originated. There's no import statement. No require. It's just... there.

Coming from JavaScript's explicit world of imports and modules, Rails can feel like programming in a house of mirrors. Everything seems to appear out of thin air. This magical appearance was one of my biggest struggles too, so I want to demystify where everything actually comes from.

## The Fundamental Difference: JavaScript vs Rails

In modern JavaScript, if you want to use something, you import it:

```javascript
import { useState } from 'react';
import express from 'express';
import { getUserById } from './services/users';
```

It's explicit. You can command-click on the import and jump to the source. Beautiful.

In Rails, you write:

```ruby
class User < ApplicationRecord
  has_many :posts
  validates :email, presence: true
end
```

Wait... where did `has_many` come from? Where's `validates`? There's no import statement anywhere. Welcome to Rails "magic."

## Understanding Rails' Philosophy: Convention Over Configuration

Rails operates on a principle called ["Convention over Configuration."](https://rubyonrails.org/doctrine#convention-over-configuration) The framework makes assumptions about what you need and automatically loads it for you. This automatic loading is the opposite of JavaScript's explicit nature, but once you understand the patterns, it becomes predictable.

## The Big Sources: Where Rails Methods Actually Come From

### Inheritance

```ruby
class ApplicationController < ActionController::Base
end

class UsersController < ApplicationController
  def index
    redirect_to root_path  # Where does redirect_to come from?
  end
end
```

`redirect_to` comes from `ActionController::Base`, which `ApplicationController` inherits from. This is similar to JavaScript class inheritance, but Rails takes it much further.

### Mixins

Rails automatically includes specific modules based on what you inherit from. When you inherit from `ApplicationRecord`, Rails includes dozens of modules:

```ruby
class User < ApplicationRecord
  belongs_to :organization  # From ActiveRecord::Associations
  has_many :posts          # From ActiveRecord::Associations
  validates :email, presence: true  # From ActiveRecord::Validations
  before_save :normalize_email      # From ActiveRecord::Callbacks
end
```

These methods come from modules mixed into `ActiveRecord::Base` (which `ApplicationRecord` inherits from). This means every model you create automatically gets these methods:

- `ActiveRecord::Associations` gives you `has_many`, `belongs_to`, `has_one`, `has_and_belongs_to_many`
- `ActiveRecord::Validations` gives you `validates`, `validate`, `valid?`, `invalid?`
- `ActiveRecord::Callbacks` gives you `before_save`, `after_create`, `around_update`, and more

In JavaScript terms, it's like if all your model classes automatically got `Object.assign`'d with a bunch of utility methods.

## Using Mixins Manually

You can also create and use your own mixins. Here's an example showing the difference between `include` and `extend`:

```ruby
module Taggable
  def add_tag(tag)
    # instance method
  end

  def self.included(base)
    base.extend(ClassMethods)
  end

  module ClassMethods
    def find_by_tag(tag)
      # class method
    end
  end
end

class Post < ApplicationRecord
  include Taggable  # Makes add_tag available as an instance method
                    # and find_by_tag available as a class method
end

# Now you can use:
post = Post.new
post.add_tag("ruby")        # instance method from include
Post.find_by_tag("rails")   # class method from extend (via ClassMethods)
```

`include` adds module methods as instance methods of the class, while `extend` adds them as class methods.

### Helper Methods

In your controllers, you get methods like:

```ruby
class PostsController < ApplicationController
  def show
    @post = Post.find(params[:id])  # Where's params from?

    if current_user.admin?  # And current_user?
      render :admin_view
    end
  end
end
```

`params` and `render` both come from `ActionController::Base`. `current_user` probably comes from a gem like Devise, or you defined it in `ApplicationController`.

## View Helpers

In your views, you have access to helper methods from `ActionView::Helpers`:

```erb
<%= form_with model: @post do |f| %>
  <%= f.text_field :title %>
  <%= link_to "Back", posts_path %>
  <%= f.submit %>
<% end %>
```

Rails automatically includes helper modules from `ActionView::Helpers` into `ActionView::Base`, which all your views inherit from. So `form_with` comes from `ActionView::Helpers::FormHelper`, `link_to` comes from `ActionView::Helpers::UrlHelper`, and dozens of other helpers are available without importing anything.

## Custom Helpers

When you create helpers in `app/helpers/`, Rails automatically makes them available to views:

```ruby
# app/helpers/posts_helper.rb
module PostsHelper
  def formatted_post_date(post)
    post.created_at.strftime("%B %d, %Y")
  end
end
```

Rails automatically includes all helper modules in your views. So in any view, you can call:

```erb
<%= formatted_post_date(@post) %>
```

The magic happens because Rails includes all helpers in the base view class. You can see this if you check `ActionView::Base.included_modules` - it includes all the helper modules from `app/helpers/`.

### Dynamic Methods

Dynamic methods are where Rails goes full wizard mode. Some methods are **created at runtime** based on your database schema:

```ruby
user = User.new
user.email = "dev@example.com"  # email= doesn't exist in your code!
user.save
```

If your `users` table has an `email` column, Rails automatically creates:

- `email` (getter)
- `email=` (setter)
- `email?` (boolean check)
- `email_was` (previous value)
- `email_changed?`

These methods are generated dynamically when Rails reads your database schema. In JavaScript, this would be like using Proxy objects to intercept property access, but Rails does it with metaprogramming.

### Route Helpers

When you define routes:

```ruby
# config/routes.rb
resources :posts, only: [:index, :show, :create, :update, :destroy]
```

Rails automatically creates helper methods:

- `posts_path` → `/posts`
- `new_post_path` → `/posts/new`
- `edit_post_path(post)` → `/posts/1/edit`
- `post_path(post)` → `/posts/1`

These are generated based on your routes file. Coming from React Router or Express, this feels weird because there's no central place you import these from.

## How to Actually Find Where Things Come From

### Use `method` and `source_location`

In a Rails console, you can inspect any method:

```ruby
User.method(:has_many).source_location
# => ["/path/to/gems/activerecord-7.0.0/lib/active_record/associations.rb", 1234]
# Class methods point to where they're explicitly defined

user = User.first
user.method(:email).source_location
# => ["/path/to/gems/activemodel-7.0.0/lib/active_model/attribute_methods.rb", 273]
# Dynamic attribute methods point to Rails' metaprogramming machinery
```

### Check the Inheritance Chain

```ruby
User.ancestors
# => [User, ApplicationRecord, ActiveRecord::Base, ...]
```

This shows you all the classes and modules mixed in. Each one could provide methods.

### Search the Codebase

Unlike JavaScript, searching for where something is defined can be tricky. You can search for:

- `def method_name` (instance method)
- `def self.method_name` (class method)
- `delegate :method_name` (delegation)
- `attr_accessor :method_name` (attribute accessor)
- Method name in gems (check your Gemfile)

### Search Your Code vs Gems

You'll often need to search in different locations depending on where the method is defined:

```bash
# Search YOUR codebase (app/, lib/, config/)
rg "def current_user" app/

# Search inside GEMS using bundle show
rg "def redirect_to" $(bundle show actionpack)
```

### Use Rails Documentation

When you encounter an unfamiliar method, Rails has two main documentation sources:

**[Rails Guides](https://guides.rubyonrails.org/)** - Start here when you're learning. They provide context, examples, and explain the "why" behind features. Great for understanding concepts.

**[Rails API](https://api.rubyonrails.org/)** - Use this when you know what you're looking for and need precise method signatures, parameters, and return values. Better for reference once you're more experienced.

## Common "Where Did That Come From?" Examples

### Controllers

```ruby
class PostsController < ApplicationController
  before_action :authenticate_user!  # From Devise gem
  before_action :set_post, only: [:show, :edit]  # before_action from ActionController::Base

  def index
    @posts = Post.all  # Post constant is auto-loaded from app/models/post.rb
  end

  def show
    # @post set by before_action
    respond_to do |format|  # respond_to from ActionController::Base
      format.html
      format.json { render json: @post }  # render from ActionController::Base
    end
  end

  private

  def set_post
    @post = Post.find(params[:id])  # params from ActionController::Base
  end
end
```

### Models

```ruby
class User < ApplicationRecord
  # Where do these methods come from?

  belongs_to :organization    # From ActiveRecord::Associations
  has_many :posts            # From ActiveRecord::Associations

  validates :email, presence: true, uniqueness: true   # From ActiveRecord::Validations
  validates :username, presence: true                  # From ActiveRecord::Validations

  before_save :normalize_email  # From ActiveRecord::Callbacks

  def self.active
    where(active: true)  # From ActiveRecord::QueryMethods
  end

  def full_name
    # first_name and last_name are dynamic methods created from database columns
    "#{first_name} #{last_name}"
  end

  private

  def normalize_email
    # self.email= is a dynamic method created from the email database column
    self.email = email.downcase.strip
  end
end
```

All these methods come from modules that `ActiveRecord::Base` includes:

- Associations: `belongs_to`, `has_many`, `has_one`, etc.
- Validations: `validates`, `validate`, `errors`, etc.
- Callbacks: `before_save`, `after_create`, `around_update`, etc.
- Query methods: `where`, `find`, `find_by`, `order`, etc.
- Dynamic attribute methods: Created from your database schema

### Views

```erb
<%= form_with model: @post do |f| %>
  <%= f.text_field :title %>
  <%= f.submit %>
<% end %>

<%= link_to "All Posts", posts_path %>
```

`form_with` comes from `ActionView::Helpers::FormHelper`, `link_to` comes from `ActionView::Helpers::UrlHelper` (both automatically included), `posts_path` is a route helper generated from your routes file, and `@post` is an instance variable set in the controller that Rails passes to the view.

## The JavaScript Mental Model Shift

In JavaScript/TypeScript, you think: *"I need this function, so I'll import it."*

In Rails, you think: *"I'm in a [controller/model/view], so I probably have access to [these categories of methods]."*

It's less about tracking individual imports and more about understanding the context you're in:

- In a controller: You have access to `params`, `session`, `redirect_to`, `render`, etc.
- In a model: You have access to validations, associations, callbacks, query methods
- In a view: You have access to all view helpers, URL helpers, and instance variables from the controller

## Pro Tips for JavaScript Developers

**Keep the Rails API docs open:** [api.rubyonrails.org](https://api.rubyonrails.org/) is your friend. When you see a mysterious method, search it there.

**Use an IDE with Ruby/Rails support:** VSCode with Ruby LSP can jump to method definitions, even in gems.

**Read your Gemfile:** Many mysterious methods come from gems. Devise gives you `authenticate_user!`, Pundit gives you `authorize`, etc.

**Learn to love the magic, but prefer explicit code:** Initially, Rails' implicit nature feels uncomfortable. While Rails provides lots of implicit behavior, thoughtbot's approach emphasizes being explicit when it improves clarity.

**Think in layers:** View → Controller → Model. Each layer has its own set of available methods.

---

The "where does this come from?" problem in Rails is real, and it's jarring coming from JavaScript's explicit world. Rails' magic is predictable magic. Once you learn the conventions and common patterns, finding where things originate becomes straightforward.

Here's the payoff: once you understand Rails conventions, you can jump into any Rails codebase and immediately feel at home. The controllers work the same way. The models use the same methods. The patterns are consistent. Compare that to JavaScript, where every project can have a completely different architecture, folder structure, and set of conventions. You've probably experienced the frustration of joining a new JavaScript project and spending days just figuring out where everything lives and how it's organized. Rails eliminates that problem. Learn the conventions once, and they apply everywhere.

JavaScript makes you explicitly import everything, giving you total clarity but more boilerplate. Rails hides the imports, giving you less boilerplate but requiring you to learn the framework's conventions. As a JavaScript developer, you're used to being explicit. Rails asks you to trust the framework. Give it time, and the magic becomes second nature.
