Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.7.1] - 2026-08-13

### Fixed
- **`rails db:migrate` raised `NameError` on 0.7.0.** The engine registers an
`RcrewAI` acronym inflection (Zeitwerk needs it to resolve
`rcrewai/rails/span.rb` to `RcrewAI::Rails::Span`), so Rails camelizes
`create_rcrewai_tables` to `CreateRcrewAITables` — but the shipped migrations
declared `CreateRcrewaiTables`. Rails resolves a migration's class from its
filename, so following the documented install verbatim failed. Nine migrations
in `db/migrate` and the install template were affected; all now declare the
name Rails derives. Thanks to the user who reported this from a real install.

**If you already installed 0.7.0** and renamed the class by hand, no action is
needed — your migration works. Otherwise, delete the copied migration, upgrade,
and re-run the install (or `rcrew_ai_rails:install:migrations`).

## [0.7.0] - 2026-08-13

### Added
Expand Down Expand Up @@ -162,7 +178,8 @@ existing agents, tasks, and crews build unchanged.
### Changed
- Rename generators from `rcrew_a_i` to `rcrewai` namespacing.

[Unreleased]: https://github.com/gkosmo/rcrewai-rails/compare/v0.7.0...HEAD
[Unreleased]: https://github.com/gkosmo/rcrewai-rails/compare/v0.7.1...HEAD
[0.7.1]: https://github.com/gkosmo/rcrewai-rails/compare/v0.7.0...v0.7.1
[0.7.0]: https://github.com/gkosmo/rcrewai-rails/compare/v0.6.1...v0.7.0
[0.6.1]: https://github.com/gkosmo/rcrewai-rails/compare/v0.6.0...v0.6.1
[0.6.0]: https://github.com/gkosmo/rcrewai-rails/compare/v0.5.1...v0.6.0
Expand Down
2 changes: 1 addition & 1 deletion db/migrate/002_add_config_to_rcrewai_agents.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
class AddConfigToRcrewaiAgents < ActiveRecord::Migration[7.0]
class AddConfigToRcrewAIAgents < ActiveRecord::Migration[7.0]
def change
# max_rpm and llm_config already exist on rcrewai_agents from the
# original create table; only the 0.5.0 additions are new.
Expand Down
2 changes: 1 addition & 1 deletion db/migrate/003_add_output_processing_to_rcrewai_tasks.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
class AddOutputProcessingToRcrewaiTasks < ActiveRecord::Migration[7.0]
class AddOutputProcessingToRcrewAITasks < ActiveRecord::Migration[7.0]
def change
# output_file already exists on rcrewai_tasks from the original create
# table; only the new 0.4/0.5 output-processing options are added here.
Expand Down
2 changes: 1 addition & 1 deletion db/migrate/004_add_lifecycle_to_rcrewai_crews.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
class AddLifecycleToRcrewaiCrews < ActiveRecord::Migration[7.0]
class AddLifecycleToRcrewAICrews < ActiveRecord::Migration[7.0]
def change
add_column :rcrewai_crews, :planning, :boolean, default: false, null: false
add_column :rcrewai_crews, :planning_llm, :string
Expand Down
2 changes: 1 addition & 1 deletion db/migrate/005_add_batch_id_to_rcrewai_executions.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
class AddBatchIdToRcrewaiExecutions < ActiveRecord::Migration[7.0]
class AddBatchIdToRcrewAIExecutions < ActiveRecord::Migration[7.0]
def change
add_column :rcrewai_executions, :batch_id, :string
add_index :rcrewai_executions, :batch_id
Expand Down
2 changes: 1 addition & 1 deletion db/migrate/006_create_rcrewai_knowledge_sources.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
class CreateRcrewaiKnowledgeSources < ActiveRecord::Migration[7.0]
class CreateRcrewAIKnowledgeSources < ActiveRecord::Migration[7.0]
def change
create_table :rcrewai_knowledge_sources do |t|
t.references :owner, polymorphic: true, null: false
Expand Down
2 changes: 1 addition & 1 deletion db/migrate/007_create_rcrewai_flows.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
class CreateRcrewaiFlows < ActiveRecord::Migration[7.0]
class CreateRcrewAIFlows < ActiveRecord::Migration[7.0]
def change
create_table :rcrewai_flow_states do |t|
t.string :state_id, null: false
Expand Down
2 changes: 1 addition & 1 deletion db/migrate/008_add_consensus_agents_to_rcrewai_crews.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
class AddConsensusAgentsToRcrewaiCrews < ActiveRecord::Migration[7.0]
class AddConsensusAgentsToRcrewAICrews < ActiveRecord::Migration[7.0]
def change
add_column :rcrewai_crews, :consensus_agents, :integer
end
Expand Down
2 changes: 1 addition & 1 deletion db/migrate/010_create_rcrewai_spans.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
class CreateRcrewaiSpans < ActiveRecord::Migration[7.0]
class CreateRcrewAISpans < ActiveRecord::Migration[7.0]
def change
create_table :rcrewai_spans do |t|
t.references :execution, null: false, foreign_key: { to_table: :rcrewai_executions }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
class AddObservationRollupsToRcrewaiExecutions < ActiveRecord::Migration[7.0]
class AddObservationRollupsToRcrewAIExecutions < ActiveRecord::Migration[7.0]
def change
add_column :rcrewai_executions, :total_cost_usd, :decimal, precision: 12, scale: 6
add_column :rcrewai_executions, :total_tokens, :integer
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
class CreateRcrewaiTables < ActiveRecord::Migration[7.0]
class CreateRcrewAITables < ActiveRecord::Migration[7.0]
def change
create_table :rcrewai_crews do |t|
t.string :name, null: false
Expand Down
2 changes: 1 addition & 1 deletion lib/rcrewai/rails/version.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module RcrewAI
module Rails
VERSION = "0.7.0"
VERSION = "0.7.1"
Version = VERSION
end
end
22 changes: 19 additions & 3 deletions spec/generators/install_generator_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,23 @@ def migration_paths
end

describe "the migration" do
# The engine registers an `RcrewAI` acronym inflection, so Rails camelizes
# `create_rcrewai_tables` to `CreateRcrewAITables`, not `CreateRcrewaiTables`.
# Rails resolves a migration's class from its filename, so a template whose
# class name disagrees raises NameError on `rails db:migrate` — which is
# exactly what shipped in 0.7.0. Assert the name Rails will actually look
# for, derived the same way Rails derives it, rather than hardcoding it.
it "declares the class name Rails derives from the filename" do
run_generator
filename = File.basename(migration_paths.first, ".rb").sub(/\A\d+_/, "")
expected = ActiveSupport::Inflector.camelize(filename)
declared = File.read(migration_paths.first)[/class (\w+)/, 1]

expect(declared).to eq(expected),
"Rails will look for #{expected} but the migration declares #{declared}; " \
"`rails db:migrate` would raise NameError"
end

it "creates a timestamped migration" do
run_generator
expect(migration_paths.size).to eq(1)
Expand Down Expand Up @@ -81,10 +98,9 @@ def migration_paths
end
end

it "defines a class name matching the Rails migration filename convention" do
it "subclasses ActiveRecord::Migration" do
run_generator
content = File.read(migration_paths.first)
expect(content).to include("class CreateRcrewaiTables < ActiveRecord::Migration")
expect(File.read(migration_paths.first)).to match(/class \w+ < ActiveRecord::Migration/)
end

it "is valid Ruby" do
Expand Down
41 changes: 41 additions & 0 deletions spec/migrations_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
require "rails_helper"

# Rails resolves a migration's class from its filename via the active
# inflections. This engine registers an `RcrewAI` acronym (which Zeitwerk needs
# to map rcrewai/rails/span.rb -> RcrewAI::Rails::Span), so any migration named
# *_rcrewai_* camelizes to `RcrewAI`, not `Rcrewai`.
#
# 0.7.0 shipped 9 migrations plus the install template whose class names
# disagreed with that, so `rails db:migrate` raised NameError on a verbatim
# install. These are the migrations host apps run, so a mismatch is only
# reachable in someone else's app — hence this spec.
RSpec.describe "migration class names" do
def declared_class_name(path)
File.read(path)[/class (\w+)/, 1]
end

def expected_class_name(path)
ActiveSupport::Inflector.camelize(
File.basename(path, ".rb").sub(/\A\d+_/, "")
)
end

engine_root = File.expand_path("..", __dir__)
migrations = Dir[File.join(engine_root, "db/migrate/*.rb")].sort
template = File.join(
engine_root,
"lib/generators/rcrewai/rails/install/templates/create_rcrewai_tables.rb"
)

it "finds migrations to check" do
expect(migrations).not_to be_empty
end

(migrations + [template]).each do |path|
it "#{File.basename(path)} declares the class Rails derives from its filename" do
expect(declared_class_name(path)).to eq(expected_class_name(path)),
"Rails will look for #{expected_class_name(path)} but the file " \
"declares #{declared_class_name(path)}; `rails db:migrate` raises NameError"
end
end
end
40 changes: 40 additions & 0 deletions spec/real_migrate_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
require "rails_helper"
require "rails/generators"
require "generators/rcrewai/rails/install/install_generator"
require "fileutils"

RSpec.describe "running the generated migration the way Rails does" do
let(:destination) { File.expand_path("../tmp/real_migrate", __dir__) }

before do
FileUtils.rm_rf(destination)
FileUtils.mkdir_p(File.join(destination, "config"))
File.write(File.join(destination, "config", "routes.rb"), "Rails.application.routes.draw do\nend\n")
original = $stdout
$stdout = StringIO.new
begin
RcrewAI::Rails::Generators::InstallGenerator.start([], destination_root: destination)
ensure
$stdout = original
end
end

after { FileUtils.rm_rf(destination) }

it "migrates without raising NameError" do
migration_dir = File.join(destination, "db/migrate")

conn = ActiveRecord::Base.establish_connection(
adapter: "sqlite3", database: ":memory:"
).lease_connection

# MigrationContext resolves each migration's class from its filename via the
# active inflections — the exact step a hand-rolled `load` + constant call
# skips, and the step that raised NameError in 0.7.0.
context = ActiveRecord::MigrationContext.new(migration_dir)
expect { context.migrate }.not_to raise_error

tables = conn.tables.grep(/rcrewai/)
expect(tables).to include("rcrewai_crews", "rcrewai_spans", "rcrewai_span_events", "rcrewai_tools")
end
end
Loading