从一个模型实例引用模型

时间:2017-06-17 12:26:56

标签: ruby-on-rails ruby

这是我的Schema.rb

Schema.rb

ActiveRecord::Schema.define(version: 20170617073406) do

  create_table "actions", force: :cascade do |t|
    t.string "name"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "posts", force: :cascade do |t|
    t.string "post_id"
    t.datetime "timestamp"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "users", force: :cascade do |t|
    t.string "user_id"
    t.datetime "last_activity"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

end

这是我的三个模型类。

Action.rb

class Action < ApplicationRecord
    belongs_to :post
    has_many :users, :foreign_key => 'user_user_id'
end

Post.rb

class Post < ApplicationRecord
    has_many :actions, :foreign_key => 'action_id'
end

User.rb

class User < ApplicationRecord
    has_many :actions, :foreign_key => 'action_id'
end

我正在尝试将Action对象的实例添加到Post模型对象中。

post = Post.find(post_id=post_id)
current_action = post.actions.find_or_create_by(name: "like")

它给我以下错误: SQLite3::SQLException: no such column: actions.action_id: SELECT "actions".* FROM "actions" WHERE "actions"."action_id" = ? AND "actions"."name" = ? LIMIT ?

我是Ruby on Rails的新手,来自Django背景。请帮我解决这个问题。

2 个答案:

答案 0 :(得分:3)

  

行动需要与用户相关多少......

如果您想要多对多关联,则需要使用另一个表(即加入模型):

class Action < ApplicationRecord
    belongs_to :post
    has_many :user_actions
    has_many :users, through: :user_actions
end

class User < ApplicationRecord
    has_many :user_actions
    has_many :actions, through: :user_actions
end

class UserAction < ApplicationRecord
    belongs_to :action
    belongs_to :user
end
  

我要存储的ID比Integer可以做的长。

您可以在迁移中指定自己的id,并避免添加额外的action_id

class CreateActions < ActiveRecord::Migration[5.1]
  def change
    create_table :actions, id: false do |t|
      t.string :id, null: false

      t.timestamps
    end

    add_index :actions, :id , unique: true
  end
end

通过上述设置,您无需在foreign_key中指定任何Post ActiveRecord 将使用默认值(即action_id):< / p>

class Post < ApplicationRecord
    has_many :actions
end

关于关联和外键的注释(以及为什么会出现该错误):

每当您创建关联时,必须在包含foreign_key一面的表格中创建belongs_to,因为 ActiveRecord 会在那里查找该关键字。

即使您未指定belongs_to,对该表的has_many引用仍会查找foreign_key

所以,当你添加

has_many :actions, :foreign_key => 'action_id'

您告诉 ActiveRecord action_id表中查找actions列,但尚未在actions表中创建这些列。

在建议的解决方案中,外键位于连接表模型(即UserActions)上,因此您必须创建一个迁移以包含它们:

rails g migration CreateUserActions user:references action:references

答案 1 :(得分:2)

解决方案:

在命令行中运行迁移:

rails generate migration add_post_to_actions post:belongs_to
rake db:migrate

然后更新:

class Action < ApplicationRecord
  belongs_to :post
  # ...
end

class Post < ApplicationRecord
  self.primary_key = 'post_id'
  has_many :actions
  # ...
end

class User < ApplicationRecord
  self.primary_key = 'user_id'
  # ...
end

说明:

  • 第一行会将post_id列添加到actions表,然后使用外部约束对其进行索引
  • 上述迁移与当前模型文件的内容无关。您甚至可以删除您的models / action.rb或models / user.rb,并且您将看到迁移仍然可以毫无问题地运行,因为只有迁移&#34; do&#34;实际的当前数据库上的东西。迁移文件甚至不关心schema.rb中写入的内容,尽管每次运行迁移时都会更新schema.rb(在数据库已经迁移/更新之后)。