Git Product home page Git Product logo

Comments (7)

solnic avatar solnic commented on June 14, 2024

It works for me, I just had to fix you repro script because you create tables AFTER setting up rom, so inferrer doesn't see any tables. I'll add a warning to inferrer so that people can see that this happens. Here's a working script:

#!/usr/bin/env ruby
require "rom-sql"
require "rom-repository"
require "dry-types"

module Relations
  class Users < ROM::Relation[:sql]
    schema(:users, infer: true)
  end

  class Participants < ROM::Relation[:sql]
    schema(:participants, infer: true) do
      associations do
        belongs_to :user
      end
    end
  end
end

module Repositories
  class Participant < ROM::Repository[:participants]
    relations :users

    def all
      aggregate(:user).to_a
    end
  end
end

config = ROM::Configuration.new(:sql, "sqlite::memory")

config.gateways[:default].tap do |gateway|
  migration = gateway.migration do
    change do
      create_table :users do
        primary_key :id
        string :country, null: true
      end

      create_table :participants do
        primary_key :id
        string :name, null: true
        foreign_key :user_id, :users, null: false
      end
    end
  end
  migration.apply gateway.connection, :up
end

config.register_relation Relations::Users
config.register_relation Relations::Participants
container = ROM.container(config)

connection = container.gateways[:default].connection
connection.execute "INSERT INTO users (country) VALUES ('UK')"
connection.execute "INSERT INTO participants (name, user_id) VALUES ('Fred', 1)"

repo = Repositories::Participant.new(container)

puts repo.all.inspect
# [#<ROM::Struct[Participant] id=1 name="Fred" user_id=1 user=#<ROM::Struct[User] id=1 country="UK" participant_id=1>>]

from rom-sql.

solnic avatar solnic commented on June 14, 2024

@mrship please confirm that this was only a mistake in your setup, and not an actual bug in inferrer :)

from rom-sql.

mrship avatar mrship commented on June 14, 2024

Thanks for looking into this.

In an attempt to show the problem in this issue, my example was a little different to what we actually do in our app. Below is more in line with what we do with our app where we yield the container before we call auto_registration for our relations. The yield is used in the test suite to setup the database we run the tests against, so again, this is a slightly contrived example as we don't actually create tables each time we run the app (just the test suite). However, this does show creating the tables first then autoloading the relations.

I've got an issue with running this locally due to inflection and ROM vs Rom which I'll review to see if I can fix, but once I can this will give a clearer example of what we're actually doing.

Again, if this is pilot error and there are better ways of doing this then please point out the error of my ways :)

#!/usr/bin/env ruby
require "rom"
require "rom-sql"
require "rom-repository"

require_relative "./relations/users"
require_relative "./relations/participants"

config = ROM::Configuration.new(:sql, "sqlite::memory") do |container|
  container.config.gateways[:default].infer_relations = false

  connection = container[:default].connection
  connection.create_table(:users) do
    primary_key :id
    string :country, null: true
  end

  connection.create_table :participants do
    primary_key :id
    string :name, null: true
    foreign_key :user_id, :users, null: false
  end

  connection.execute "INSERT INTO users (country) VALUES ('UK')"
  connection.execute "INSERT INTO participants (name, user_id) VALUES ('Fred', 1)"

  container.auto_registration(__dir__)
end

module Repositories
  class Participant < ROM::Repository[:participants]
    relations :users

    def all
      aggregate(:user).to_a
    end
  end
end

container = ROM.container(config)
repo = Repositories::Participant.new(container)
repo.all

./relations/participants

require "dry-types"

module Relations
  class Participants < ROM::Relation[:sql]
    schema(:participants) do
      attribute :id, Types::Int.meta(primary_key: true)
      attribute :name, Types::String
      attribute :user_id, Types::Int.meta(foreign_key: true, relation: :users)

      associations do
        belongs_to :user
      end
    end
  end
end

./relations/users

require "dry-types"

module Relations
  class Users < ROM::Relation[:sql]
    schema(:users) do
      attribute :id, Types::Int.meta(primary_key: true)
      attribute :country, Types::String
    end
  end
end

from rom-sql.

solnic avatar solnic commented on June 14, 2024

I pushed this here https://github.com/solnic/rom-sql-issue-137

works for me, could you check? just clone + bundle install + bundle exec ruby rom.rb

from rom-sql.

mrship avatar mrship commented on June 14, 2024

Yes, that works for me too. Let's consider this closed then and I'll have a look at why this is/was failing in my actual app.

Thanks again for the support and best of luck with the RC cycle!

from rom-sql.

mrship avatar mrship commented on June 14, 2024

One last play with this:

class Users < ROM::Relation[:sql]
  schema(:users) do
    attribute :id, Types::Int
    attribute :country, Types::String
  end
end

If I don't use schema inference and specify Types::Int then it does still break, but in a different (and odd) way:

/Users/shipmana/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/dry-struct-0.1.1/lib/dry/struct/class_interface.rb:56:in `check_schema_duplication': Attribute :id has already been defined (Dry::Struct::RepeatedAttributeError)

I can work around that using Types::Serial but I thought I'd pass that on in case it is also a regression.

from rom-sql.

solnic avatar solnic commented on June 14, 2024

@mrship yeah that's certainly not the best way of handling a missing PK attribute. I'll improve this somehow. You need to either use inference, or do Types::Int.meta(primary_key: true) or primary_key :id.

from rom-sql.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.