rom-rb / rom

Data mapping and persistence toolkit for Ruby
https://rom-rb.org
MIT License
2.07k stars 161 forks source link

uninitialized constant ROM::Memory::Types::Int #689

Closed wilsonsilva closed 2 months ago

wilsonsilva commented 2 months ago

Describe the bug

When I run the example code from https://rom-rb.org/learn/core/5.2/associations/, I get an error:

test.rb:6:in `block in <class:Users>': uninitialized constant ROM::Memory::Types::Int (NameError)

    attribute :id, Types::Int
                        ^^^^^
    from /Users/wilson/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/rom-core-5.3.1/lib/rom/schema/dsl.rb:184:in `instance_exec'
    from /Users/wilson/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/rom-core-5.3.1/lib/rom/schema/dsl.rb:184:in `call'
    from /Users/wilson/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/rom-core-5.3.1/lib/rom/relation/class_interface.rb:114:in `block in schema'
    from /Users/wilson/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/rom-core-5.3.1/lib/rom/setup/finalize/finalize_relations.rb:78:in `build_relation'
    from /Users/wilson/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/rom-core-5.3.1/lib/rom/setup/finalize/finalize_relations.rb:50:in `block (2 levels) in run!'
    from /Users/wilson/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/rom-core-5.3.1/lib/rom/setup/finalize/finalize_relations.rb:33:in `each'
    from /Users/wilson/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/rom-core-5.3.1/lib/rom/setup/finalize/finalize_relations.rb:33:in `block in run!'
    from /Users/wilson/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/rom-core-5.3.1/lib/rom/relation_registry.rb:11:in `initialize'
    from /Users/wilson/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/rom-core-5.3.1/lib/rom/registry.rb:27:in `new'
    from /Users/wilson/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/rom-core-5.3.1/lib/rom/registry.rb:27:in `new'
    from /Users/wilson/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/rom-core-5.3.1/lib/rom/setup/finalize/finalize_relations.rb:32:in `run!'
    from /Users/wilson/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/rom-core-5.3.1/lib/rom/setup/finalize.rb:88:in `load_relations'
    from /Users/wilson/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/rom-core-5.3.1/lib/rom/setup/finalize.rb:64:in `run!'
    from /Users/wilson/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/rom-core-5.3.1/lib/rom/create_container.rb:40:in `finalize'
    from /Users/wilson/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/rom-core-5.3.1/lib/rom/create_container.rb:16:in `initialize'
    from /Users/wilson/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/rom-core-5.3.1/lib/rom/create_container.rb:61:in `initialize'
    from /Users/wilson/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/rom-core-5.3.1/lib/rom/create_container.rb:67:in `new'
    from /Users/wilson/.asdf/installs/ruby/3.3.0/lib/ruby/gems/3.3.0/gems/rom-core-5.3.1/lib/rom/create_container.rb:67:in `container'
    from test.rb:31:in `<main>'

Requiring 'rom/memory/types' didn't solve the issue.

To Reproduce

Execute the code from the associations documentation:

require "rom"
require "rom/memory"

class Users < ROM::Relation[:memory]
  schema do
    attribute :id, Types::Int
    attribute :name, Types::String

    primary_key :id

    associations do
      has_many :tasks, combine_key: :user_id, override: true, view: :for_users
    end
  end
end

class Tasks < ROM::Relation[:memory]
  schema do
    attribute :id, Types::Int
    attribute :user_id, Types::Int
    attribute :title, Types::String

    primary_key :id
  end

  def for_users(_assoc, users)
    restrict(user_id: users.map { |u| u[:id] })
  end
end

rom = ROM.container(:memory) do |config|
  config.register_relation(Users, Tasks)
end

users = rom.relations[:users]
tasks = rom.relations[:tasks]

[{ id: 1, name: "Jane" }, { id: 2, name: "John" }].each { |tuple| users.insert(tuple) }
[{ id: 1, user_id: 1, title: "Jane's task" }, { id: 2, user_id: 2, title: "John's task" }].each { |tuple| tasks.insert(tuple) }

# load all tasks for all users
tasks.for_users(users.associations[:tasks], users).to_a
# [{:id=>1, :user_id=>1, :title=>"Jane's task"}, {:id=>2, :user_id=>2, :title=>"John's task"}]

# load tasks for particular users
tasks.for_users(users.associations[:tasks], users.restrict(name: "John")).to_a
# [{:id=>2, :user_id=>2, :title=>"John's task"}]

# when we use `combine`, our `for_users` will be called behind the scenes
puts users.restrict(name: "John").combine(:tasks).to_a
# {:id=>2, :name=>"John", :tasks=>[{:id=>2, :user_id=>2, :title=>"John's task"}]}

Expected behavior

The code should behave as documented.

My environment

flash-gordon commented 2 months ago

I think that it's because the memory plugin doesn't define its own type container. Examples should be updated, but adding Types = Dry.Types() at the top of a script should work too.

wilsonsilva commented 2 months ago

Thanks, @flash-gordon. I opened a PR to fix the documentation https://github.com/rom-rb/rom/pull/690

flash-gordon commented 2 months ago

Thanks! Ahh, right, it's the old name of the type, I forgot it completely because I've been dealing with quite a bunch of languages at once recently :) It messes with your brain when same things are named differently everywhere.

I've merged the PR, let's see if the pipeline will manage to deploy it