-1

rails, postgres, devise. There is a side table base with Corporations, to her I was connected successfully. Objective: To create a model User, which will be tied to the corporation, to enable the Corporation to log in as the user. I decided to make the ratio by has_one through.

user_corporation.rb:

class UserCorporation < ActiveRecord::Base
    belongs_to :user
    belongs_to :corporation
end

user.rb:

class User < ActiveRecord::Base

    devise :database_authenticatable,
            :rememberable,
            :trackable,
            :timeoutable,
            :authentication_keys => [:login]

    has_one :user_corporation
    has_one :corporation, :through => :user_corporation
end

corporation.rb:

class Corporation < OtherBaseconfiguration
    self.table_name = 'Corporations'
    has_one :user_corporation
    has_one :user, :through => :user_corporation
end

20160212185152_create_user_corporations.rb:

class CreateUserCorporations < ActiveRecord::Migration
  def change
    create_table :user_corporations do |t|
      t.belongs_to :user, index: true
      t.belongs_to :corporation, index: true
      t.timestamps null: false
    end
  end
end

rake db: migrate executed, the table is created. In the console, trying to get the corporate user, I get the error:

irb(main):006:0> @corpor.corporation
ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR:  relation "user_corporations" does not exist
LINE 5:                WHERE a.attrelid = '"user_corporations"'::reg...
                                          ^
:               SELECT a.attname, format_type(a.atttypid, a.atttypmod),
                     pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod
                FROM pg_attribute a LEFT JOIN pg_attrdef d
                  ON a.attrelid = d.adrelid AND a.attnum = d.adnum
               WHERE a.attrelid = '"user_corporations"'::regclass
                 AND a.attnum > 0 AND NOT a.attisdropped
               ORDER BY a.attnum

    from /home/marson/.rvm/rubies/ruby-2.2.3/lib/ruby/gems/2.2.0/gems/activerecord-4.2.5/lib/active_record/connection_adapters/postgresql_adapter.rb:592:in `async_exec'
    from /home/marson/.rvm/rubies/ruby-2.2.3/lib/ruby/gems/2.2.0/gems/activerecord-4.2.5/lib/active_record/connection_adapters/postgresql_adapter.rb:592:in `block in exec_no_cache'
    from /home/marson/.rvm/rubies/ruby-2.2.3/lib/ruby/gems/2.2.0/gems/activerecord-4.2.5/lib/active_record/connection_adapters/abstract_adapter.rb:472:in `block in log'
    from /home/marson/.rvm/rubies/ruby-2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.5/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
    from /home/marson/.rvm/rubies/ruby-2.2.3/lib/ruby/gems/2.2.0/gems/activerecord-4.2.5/lib/active_record/connection_adapters/abstract_adapter.rb:466:in `log'
    from /home/marson/.rvm/rubies/ruby-2.2.3/lib/ruby/gems/2.2.0/gems/activerecord-4.2.5/lib/active_record/connection_adapters/postgresql_adapter.rb:592:in `exec_no_cache'
    from /home/marson/.rvm/rubies/ruby-2.2.3/lib/ruby/gems/2.2.0/gems/activerecord-4.2.5/lib/active_record/connection_adapters/postgresql_adapter.rb:584:in `execute_and_clear'
    from /home/marson/.rvm/rubies/ruby-2.2.3/lib/ruby/gems/2.2.0/gems/activerecord-4.2.5/lib/active_record/connection_adapters/postgresql/database_statements.rb:160:in `exec_query'
    from /home/marson/.rvm/rubies/ruby-2.2.3/lib/ruby/gems/2.2.0/gems/activerecord-4.2.5/lib/active_record/connection_adapters/postgresql_adapter.rb:733:in `column_definitions'
    from /home/marson/.rvm/rubies/ruby-2.2.3/lib/ruby/gems/2.2.0/gems/activerecord-4.2.5/lib/active_record/connection_adapters/postgresql/schema_statements.rb:186:in `columns'
    from /home/marson/.rvm/rubies/ruby-2.2.3/lib/ruby/gems/2.2.0/gems/activerecord-4.2.5/lib/active_record/connection_adapters/schema_cache.rb:43:in `columns'
    from /home/marson/.rvm/rubies/ruby-2.2.3/lib/ruby/gems/2.2.0/gems/activerecord-4.2.5/lib/active_record/connection_adapters/schema_cache.rb:49:in `columns_hash'
    from /home/marson/.rvm/rubies/ruby-2.2.3/lib/ruby/gems/2.2.0/gems/activerecord-4.2.5/lib/active_record/associations/association_scope.rb:85:in `column_for'
    from /home/marson/.rvm/rubies/ruby-2.2.3/lib/ruby/gems/2.2.0/gems/activerecord-4.2.5/lib/active_record/associations/association_scope.rb:94:in `bind'
    from /home/marson/.rvm/rubies/ruby-2.2.3/lib/ruby/gems/2.2.0/gems/activerecord-4.2.5/lib/active_record/associations/association_scope.rb:103:in `last_chain_scope'
    from /home/marson/.rvm/rubies/ruby-2.2.3/lib/ruby/gems/2.2.0/gems/activerecord-4.2.5/lib/active_record/associations/association_scope.rb:139:in `add_constraints'
... 13 levels...
    from /home/marson/.rvm/rubies/ruby-2.2.3/lib/ruby/gems/2.2.0/gems/railties-4.2.5/lib/rails/commands/console.rb:9:in `start'
    from /home/marson/.rvm/rubies/ruby-2.2.3/lib/ruby/gems/2.2.0/gems/railties-4.2.5/lib/rails/commands/commands_tasks.rb:68:in `console'
    from /home/marson/.rvm/rubies/ruby-2.2.3/lib/ruby/gems/2.2.0/gems/railties-4.2.5/lib/rails/commands/commands_tasks.rb:39:in `run_command!'
    from /home/marson/.rvm/rubies/ruby-2.2.3/lib/ruby/gems/2.2.0/gems/railties-4.2.5/lib/rails/commands.rb:17:in `<top (required)>'
    from /home/marson/.rvm/rubies/ruby-2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.5/lib/active_support/dependencies.rb:274:in `require'
    from /home/marson/.rvm/rubies/ruby-2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.5/lib/active_support/dependencies.rb:274:in `block in require'
    from /home/marson/.rvm/rubies/ruby-2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.5/lib/active_support/dependencies.rb:240:in `load_dependency'
    from /home/marson/.rvm/rubies/ruby-2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.5/lib/active_support/dependencies.rb:274:in `require'
    from /home/marson/rails_project/infinity/bin/rails:9:in `<top (required)>'
    from /home/marson/.rvm/rubies/ruby-2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.5/lib/active_support/dependencies.rb:268:in `load'
    from /home/marson/.rvm/rubies/ruby-2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.5/lib/active_support/dependencies.rb:268:in `block in load'
    from /home/marson/.rvm/rubies/ruby-2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.5/lib/active_support/dependencies.rb:240:in `load_dependency'
    from /home/marson/.rvm/rubies/ruby-2.2.3/lib/ruby/gems/2.2.0/gems/activesupport-4.2.5/lib/active_support/dependencies.rb:268:in `load'
    from /home/marson/.rvm/rubies/ruby-2.2.3/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require'
    from /home/marson/.rvm/rubies/ruby-2.2.3/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require'

what am I doing wrong?

Marsel.V
  • 1,015
  • 1
  • 12
  • 28
  • Show what @corpor contains. – Albert Paul Feb 15 '16 at 18:58
  • @AlbertPaul, `irb(main):001:0> @corpor = User.first User Load (3.6ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT 1 => #` – Marsel.V Feb 15 '16 at 19:05
  • You have 2 databases right? When going through the corporation you are going trough that db, but the migration created the table in the current db. I bet if you accessed it via user it would probably work. Not sure how to get Eround it – Doon Feb 15 '16 at 23:04

4 Answers4

1

Maybe I'm missing it, but if you only need a has_one to has_one between a Corporation and a User, why use a UserCorporations lookup table?

virtual_monk
  • 120
  • 3
  • 12
  • you propose to add a column to the `corporate_id` `users` table? In the beginning, I did not want to do this because the user can be an administrator who is not a corporation. – Marsel.V Feb 16 '16 at 05:16
  • If a User has one or belongs to a corporation. And a corporation has one or belongs to a User, than I believe the user corporation table is useless. You'll still be able to set a User as an admin. You'll have to check admin status in the controller or model. – virtual_monk Feb 16 '16 at 05:40
  • Yes, now I am more inclined to this option – Marsel.V Feb 16 '16 at 05:46
1

Your design is flawed, you're trying to use has_one in the wrong way and its failing for you. You want one of the following designs: A

Corporation has many Users User belongs to Corporation

(A user only ever belongs to one Corp. a Corp can have lots of users).

B

Corporation has many UserCorporations User has many UserCorporations UsedCorporation belongs to User UserCorporation belongs to Corporation

(This is a many to many, so the user can belong to multiple corps and a Corp may have multiple users)

C

Corporation belongs to User User has many Corporations

(A user is connected to multiple corps and a Corp can only belong to a single user)

TomDunning
  • 4,829
  • 1
  • 26
  • 33
  • not exactly in my application need to enable corporations to log in as the user. That is a corporation complies with a user account. Corporation = user – Marsel.V Feb 16 '16 at 05:12
1

Do it with has_many :through as (Corporation has many users user belongs_to corporation )

Corporation belongs_to user User has_many corporations

(user is connected to multiple corporation and a Corporation can only belong_to a single user)

Hizqeel
  • 947
  • 3
  • 20
  • 23
0

Same situation on macOS Big Sur...

bundle list ...

  • devise (4.8.0) ...
  • pg (1.2.3) ...
  • rails (6.1.3.2) ...

Model User and UserRule (one user has one rule)

class User < ApplicationRecord
  has_one :user_rule
end

class DeviseCreateUsers < ActiveRecord::Migration[6.1]
  def change
    create_table :users do |t|
      ## Database authenticatable
      t.string :username, null: false, default: ""
      t.string :email, null: false, default: ""
      t.string :encrypted_password, null: false, default: ""
      ....      
    end
  end
end


class UserRule < ApplicationRecord
  belongs_to :user
end

class CreateUserRules < ActiveRecord::Migration[6.1]
  def change
    create_table :user_rules do |t|
      t.belongs_to :user, index: { unique: true }, foreign_key: true
      ....
    end
  end
end

Content for config/database.yml

development:
  <<: *default
  database: <%= ENV['MY_DATABASE_NAME'] %>
  host:     <%= ENV['MY_DATABASE_HOST'] %>
  port:     <%= ENV['MY_DATABASE_PORT'] %>
  username: <%= ENV['MY_DATABASE_USER'] %>
  password: <%= ENV['MY_DATABASE_PASSWORD'] %>

Clean database:

rake db:drop
rake db:create
rake db:migrate

Go to console:

rails console
Running via Spring preloader in process 25238
Loading development environment (Rails 6.1.3.2)
2.7.2 :001 > User.new
 => #<User id: nil, username: "", email: "", ....>
2.7.2 :002 > UserRule.new
Traceback (most recent call last):
        1: from (irb):2
ActiveRecord::StatementInvalid (PG::UndefinedTable: ERROR:  relation "user_rules" does not exist)
LINE 8:  WHERE a.attrelid = '"user_rules"'::regclass

As show, my User model works fine, but the model UserRule fails...

Let me hardcode the settings for database credentials instead of environment variables...

File config/database.yml:

development:
  <<: *default
  database: "app_development"
  host:     "localhost"
  port:     "5432"
  username: "postgres"
  password: "postgres"

Repeat...

rails console
Running via Spring preloader in process 25238
Loading development environment (Rails 6.1.3.2)
2.7.2 :001 > User.new
 => #<User id: nil, username: "", email: "", ....>
2.7.2 :002 > UserRule.new
=> #<UserRule id: nil, user_id: nil, ...>

Oh surprise !!!

The problem was not Rails, is the database credentials in config/database.yml when environment values are used...

Hardcoding these settings as a workaround when you work on macOS Big Sur, Intel Family.

With Linux works like a charm !!!

hejeroaz
  • 173
  • 2
  • 3