active-hash / active-hash/active_hash

has_many ActiveRecord though ActiveHash generates invalid SQL

Open
#323 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Ruby
Stars
1.4k
Forks
186
PR merge metrics
No merged PRs in 30d

Description

Describe the bug

I can't retrieve ActiveRecord records from ActiveHash object when the ActiveHash is related to the ActiveRecord through another ActiveHash.

To Reproduce
  1. Create books table below.
# db/schema.rb

ActiveRecord::Schema[7.2].define(version: 2024_09_21_030534) do
  create_table "books", force: :cascade do |t|
    t.string "title"
    t.integer "author_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end
end

# test/fixtures/books.yml

one:
  title: MyString
  author_id: 1

two:
  title: MyString
  author_id: 1

  1. Execute bin/rails db:fixtures:load

  2. Create models below.

# app/models/book.rb

class Book < ApplicationRecord
  extend ActiveHash::Associations::ActiveRecordExtensions
  belongs_to :author
  delegate :country, to: :author
end

# app/models/author.rb

class Author < ActiveHash::Base
  include ActiveHash::Associations

  has_many :books
  belongs_to :country

  self.data = [
    { id: 1, name: 'Author A', country_id: 1 },
    { id: 2, name: 'Author B', country_id: 2 },
  ]
end

# app/models/country.rb

class Country < ActiveHash::Base
  include ActiveHash::Associations

  has_many :authors
  has_many :books, through: :authors

  self.data = [
    { id: 1, name: 'USA' },
    { id: 2, name: 'Japan' },
  ]
end

  1. Execute code below on rails console.
Country.find(1).books
Expected Behavior

Returns all Book records.(They are all have author_id=1, and the author relates to country 1.)

[#<Book:0x00007faef7873860
  id: 298486374,
  title: "MyString",
  author_id: 1,
  created_at: "2024-09-21 03:17:10.084083000 +0000",
  updated_at: "2024-09-21 03:17:10.084083000 +0000">,
 #<Book:0x00007faef7873720
  id: 980190962,
  title: "MyString",
  author_id: 1,
  created_at: "2024-09-21 03:17:10.084083000 +0000",
  updated_at: "2024-09-21 03:17:10.084083000 +0000">]
Actual Behavior

The output is below.

  Book Load (0.7ms)  SELECT "books".* FROM "books" WHERE "books"."country_id" = ? /* loading for pp */ LIMIT ?  [["country_id", 1], ["LIMIT", 11]]
An error occurred when inspecting the object: #<ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: books.country_id>
Result of Kernel#inspect: #<Book::ActiveRecord_Relation:0x00007fb3c5382ef0 @klass=Book(id: integer, title: string, author_id: integer, created_at: datetime, updated_at: datetime), @table=#<Arel::Table:0x00007fb3c53ff6a8 @name="books", @klass=Book(id: integer, title: string, author_id: integer, created_at: datetime, updated_at: datetime), @type_caster=#<ActiveRecord::TypeCaster::Map:0x00007fb3c572f2d8 @klass=Book(id: integer, title: string, author_id: integer, created_at: datetime, updated_at: datetime)>, @table_alias=nil>, @values={:where=>#<ActiveRecord::Relation::WhereClause:0x00007fb3c56d1cc8 @predicates=[#<Arel::Nodes::Equality:0x00007fb3c56d1d40 @left=#<struct Arel::Attributes::Attribute relation=#<Arel::Table:0x00007fb3c53ff6a8 @name="books", @klass=Book(id: integer, title: string, author_id: integer, created_at: datetime, updated_at: datetime), @type_caster=#<ActiveRecord::TypeCaster::Map:0x00007fb3c572f2d8 @klass=Book(id: integer, title: string, author_id: integer, created_at: datetime, updated_at: datetime)>, @table_alias=nil>, name="country_id">, @right=#<ActiveRecord::Relation::QueryAttribute:0x00007fb3c54bcb90 @name="country_id", @value_before_type_cast=1, @type=#<ActiveModel::Type::Value:0x00007fb3c5ec6938 @precision=nil, @scale=nil, @limit=nil>, @original_attribute=nil, @value=1, @_unboundable=nil, @value_for_database=1>>]>}, @loaded=nil, @predicate_builder=#<ActiveRecord::PredicateBuilder:0x00007fb3c572f210 @table=#<ActiveRecord::TableMetadata:0x00007fb3c572f238 @klass=Book(id: integer, title: string, author_id: integer, created_at: datetime, updated_at: datetime), @arel_table=#<Arel::Table:0x00007fb3c53ff6a8 @name="books", @klass=Book(id: integer, title: string, author_id: integer, created_at: datetime, updated_at: datetime), @type_caster=#<ActiveRecord::TypeCaster::Map:0x00007fb3c572f2d8 @klass=Book(id: integer, title: string, author_id: integer, created_at: datetime, updated_at: datetime)>, @table_alias=nil>, @reflection=nil>, @handlers=[[Set, #<ActiveRecord::PredicateBuilder::ArrayHandler:0x00007fb3c572f080 @predicate_builder=#<ActiveRecord::PredicateBuilder:0x00007fb3c572f210 ...>>], [Array, #<ActiveRecord::PredicateBuilder::ArrayHandler:0x00007fb3c572f0d0 @predicate_builder=#<ActiveRecord::PredicateBuilder:0x00007fb3c572f210 ...>>], [ActiveRecord::Relation, #<ActiveRecord::PredicateBuilder::RelationHandler:0x00007fb3c572f120>], [Range, #<ActiveRecord::PredicateBuilder::RangeHandler:0x00007fb3c572f170 @predicate_builder=#<ActiveRecord::PredicateBuilder:0x00007fb3c572f210 ...>>], [BasicObject, #<ActiveRecord::PredicateBuilder::BasicObjectHandler:0x00007fb3c572f1c0 @predicate_builder=#<ActiveRecord::PredicateBuilder:0x00007fb3c572f210 ...>>]]>, @delegate_to_klass=false, @future_result=nil, @records=nil, @async=false, @none=false, @should_eager_load=nil, @arel=nil, @to_sql=nil, @take=nil, @offsets=nil, @cache_keys=nil, @cache_versions=nil>
=> 
My environment

OS: Ubuntsu 20.04.3(WSL)
Ruby version: ruby 3.2.4 (2024-04-23 revision af471c0e01) [x86_64-linux]
Rails version: 7.2.1
active-hash version: 3.3.1

The rails uses sqlite3 as database.
sqlite3 version: 3.37.2 2022-01-06 13:25:41 872ba256cbf61d9290b571c0e6d82a20c224ca3ad82971edc46b29818d5dalt1

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the failure by loading the fixtures with bin/rails db:fixtures:load and running Country.find(1).books. Start with app/models/book.rb, app/models/author.rb, app/models/country.rb, and db/schema.rb to trace the association path and generated query. Done means the query returns the related Book records without referencing a nonexistent books.country_id column.

Written by the indexing model from the issue text.

Assessment

Tech stack
ruby, sqlite
Domain
backend, databases
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.