0

This question was discussed numerous times, however I run into an issue that I could not find an answer to.

I am building a login system where one Member(:class) "bails for" a new Member. Internally, they are referenced as "member" and "candidate" respectively. Until the member has accepted the bail, a BailRequest(:class) is listed in the according table.

According to the rails guide, the right way to tell rails about the class refering to would be

class BailRequest < ApplicationRecord
  belongs_to :candidate, class_name: "Member"
  belongs_to :member
end

where class_name: "Member" should tell rails that BailRequest.candidate is of class: Member. The very same approach worked in the member class flawlessly

class Member < ApplicationRecord
  belongs_to :bail, class_name: "Member", optional: true
  has_many :associates, class_name: "Member", foreign_key: "bail_id"
end

However, this time when I want to save a BailRequest to the database, I get an ActiveRecord::StatementInvalid: SQLite3::SQLException: no such table: main.candidates.

It looks like ActiveRecord is expecting a table called "candidates" here. What am I missing?

$ rails -v
Rails 5.2.1

[$ ruby -v
ruby 2.3.1p112 (2016-04-26) [i386-linux-gnu]]

The schema.rb shows the following after migration

  create_table "bail_requests", force: :cascade do |t|
      t.integer "candidate_id"
      t.integer "member_id"
      t.string "message", limit: 100
      t.boolean "accepted"
      t.datetime "created_at", null: false
      t.datetime "updated_at", null: false
      t.index ["candidate_id"], name: "index_bail_requests_on_candidate_id", unique: true
      t.index ["member_id"], name: "index_bail_requests_on_member_id"
  end

  create_table "members", force: :cascade do |t|
    t.string "email", limit: 50, null: false
    t.string "password_digest", null: false
    t.integer "bail_id"
    t.string "username", limit: 50
    t.string "first_name", limit: 50
    t.string "last_name", limit: 50
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["email"], name: "index_members_on_email", unique: true
    t.index ["username"], name: "index_members_on_username", unique: true
  end

Logic:

  1. When a Member m registers, m has to reference a Member n by name. m.bail equals nil/null and a BailRequest br is created with br.member = n and br.candidate = m
  2. If member accepts the bail, br.accepted is set to true. m.bail is set to n and m is in n.associates
randmin
  • 818
  • 8
  • 16
  • can you explain this part for me? class_name: "Member" in your association – Kick Buttowski Feb 01 '19 at 20:39
  • Can you post the member table too it seems odd that a member would belong to a bail in the given context. might also want to add `foreign_key: "candidate_id"` to the belongs to on `BailRequest` – engineersmnky Feb 01 '19 at 20:50
  • Kick Buttowski engineersmnky :I added some explanation and code. – randmin Feb 01 '19 at 21:29
  • engineersmnky it appears that I do not need a foreign_key for Member.bail as while it itself is the foreign_key for associates, it does not expect the key to be "somewhere else" like in another table or here in the same table but in another column. I conclude that BailRequest.candidate would also not need the foreign_key attribute as it itself holds the reference and does not look "somewhere else". Actually tested, but no changes – randmin Feb 02 '19 at 00:07
  • @randmin, do you have more code on your model? maybe a callback or something? – arieljuod Feb 02 '19 at 04:52
  • @arieljuod only one validation validates_associated :candidate, :member, but these where added after the error appeared first. This to me seems strange and I consider some workaround by now.. – randmin Feb 02 '19 at 05:13
  • 1
    @randmin, i've just created a simple Rails app with just those 2 models and those 2 migrations and sqlite database and when I create a BailRequest it works just fine, there's something else on your app that we are not seeing, the relationship works as it should, any extra code that you think might be relevant? – arieljuod Feb 02 '19 at 05:37
  • I expect this to be a problem with the migration/reference. I just migrated a copy to postgresql and had to change t.references :model to t.integer :model_id to make the migrations work (I believe this is postgres specific as it handles object relations differently). In the postgres app the error does not appear. Btw, if someone wants to go this path and change all t.references to t.integer with suffix _id, don't forget to add foreign_key: "model_id" to your associations accordingly. – randmin Feb 02 '19 at 07:14

1 Answers1

0

In the migration file, I changed

t.references :candidate, index: {:unique=>true}

to

t.integer :candidate_id, index: {:unique=>true}, foreign_key: true

and rerun the migration. It is now working on the rails console. Thanks to arieljuod for your effort.

randmin
  • 818
  • 8
  • 16