anykeyh / clear

Advanced ORM between postgreSQL and Crystal
https://github.com/anykeyh/clear
MIT License
269 stars 34 forks source link

Clear v0.9 regressions with self-reference and has_many through #208

Open mamantoha opened 3 years ago

mamantoha commented 3 years ago

2 models: User and Friendship.

class User
  include Clear::Model

  primary_key
  column name : String
  timestamps

  has_many friendships : Friendship
  has_many requestors : User, through: :friendships, relation: :requestor
  has_many receivers : User, through: :friendships, relation: :receiver
end

class Friendship
  include Clear::Model

  belongs_to requestor : User, foreign_key: "requestor_id"
  belongs_to receiver : User, foreign_key: "receiver_id"
end
user1 = User.query.find_or_create(name: "John") { }
user2 = User.query.find_or_create(name: "Jane") { }
user3 = User.query.find_or_create(name: "Tom") { }

Regression 1

user1.requestors << user2

Error:

Unhandled exception: Operation not permitted on this collection. (Exception)
  from lib/clear/src/clear/model/collection.cr:430:7 in '<<'
  from src/run.cr:15:1 in '__crystal_main'
  from /snap/crystal/587/share/crystal/src/crystal/main.cr:110:5 in 'main_user_code'
  from /snap/crystal/587/share/crystal/src/crystal/main.cr:96:7 in 'main'
  from /snap/crystal/587/share/crystal/src/crystal/main.cr:119:3 in 'main'
  from __libc_start_main
  from _start
  from ???

This can be fixed by:

Friendship.create!({receiver: user1, requestor: user2})

In clear v0.8 this worked.

Regression 2

user1.requestors.each { |user| puts user.name }

Error:

Unhandled exception: table name "users" specified more than once
Error caught, last query was:
SELECT DISTINCT users.* FROM "users" INNER JOIN friendships ON ("friendships"."requestor_id" = "users"."id") INNER JOIN users ON ("users"."id" = "friendships"."user_id") WHERE ("users"."id" = 1) (Clear::SQL::Error)
  from lib/clear/src/clear/sql/logger.cr:69:5 in 'each'
  from src/run.cr:22:1 in '__crystal_main'
  from /snap/crystal/587/share/crystal/src/crystal/main.cr:110:5 in 'main_user_code'
  from /snap/crystal/587/share/crystal/src/crystal/main.cr:96:7 in 'main'
  from /snap/crystal/587/share/crystal/src/crystal/main.cr:119:3 in 'main'
  from __libc_start_main
  from _start
  from ???
Caused by: table name "users" specified more than once (PQ::PQError)
  from lib/pg/src/pq/connection.cr:203:7 in 'handle_error'
  from lib/pg/src/pq/connection.cr:186:7 in 'handle_async_frames'
  from lib/pg/src/pq/connection.cr:162:7 in 'read'
  from lib/pg/src/pq/connection.cr:157:7 in 'read'
  from lib/pg/src/pq/connection.cr:414:31 in 'expect_frame'
  from lib/pg/src/pq/connection.cr:413:5 in 'expect_frame'
  from lib/pg/src/pg/statement.cr:18:5 in 'perform_query'
  from lib/db/src/db/statement.cr:93:9 in 'perform_query_with_rescue'
  from lib/db/src/db/statement.cr:80:7 in 'query:args'
  from lib/db/src/db/query_methods.cr:46:7 in 'query'
  from lib/clear/src/clear/sql/query/fetch.cr:137:40 in 'each'
  from src/run.cr:22:1 in '__crystal_main'
  from /snap/crystal/587/share/crystal/src/crystal/main.cr:110:5 in 'main_user_code'
  from /snap/crystal/587/share/crystal/src/crystal/main.cr:96:7 in 'main'
  from /snap/crystal/587/share/crystal/src/crystal/main.cr:119:3 in 'main'
  from __libc_start_main
  from _start
  from ???