Rails 多态关联未初始化常量错误
Rails Polymorphic Associations Uninitialized Constant Error
几个小时以来一直在调试这个问题,但仍然找不到解决方案。当我在事务控制器的更新方法中发送调用 @transaction.save 的 PUT 请求时,我的服务器日志吐出:
NameError - uninitialized constant Transaction::Respondable:
基本相关架构是用户和组织都可以有请求,请求可以有事务,用户和组织也可以有事务。区别在于事务存在于初始化请求的 Person/Organization 1 和响应请求的 Person/Organization 2 之间。换句话说,一个事务同时属于一个请求(并通过一个请求 User/Orgnization 1)和 User/Organization 2。我现在只是在寻找用户,所以我不会包含有关组织的代码现在,因为它尚未实施。相关代码如下:
架构:
create_table "transactions", force: true do |t|
t.string "name", null: false
t.string "description", null: false
t.integer "listable_id", null: false
t.string "listable_type", null: false
t.integer "respondable_id", null: false
t.string "respondable_type", null: false
t.datetime "created_at"
t.datetime "updated_at"
end
listable 指的是 Request(也是多态的,因为它也可以来自 Offer,但现在不相关)。可响应指的是用户。
create_table "requests", force: true do |t|
t.string "name", null: false
t.string "description", null: false
t.integer "requestable_id", null: false
t.string "requestable_type", null: false
t.datetime "created_at"
t.datetime "updated_at"
end
用户模式无关紧要,因为它不包含指向其他表的链接(只有关系 has_many)。
这是我的模型:
class User < ActiveRecord::Base
...
has_many :requests, as: :requestable, dependent: :destroy
has_many :responded_transactions, class_name: 'Transaction', as: :respondable, dependent: :destroy
has_many :listed_transactions, through: :requests, source: :transactions
...
end
class Request < ActiveRecord::Base
validates :name, :description, :requestable, presence: true
has_many :transactions, as: :listable, dependent: :destroy
belongs_to :requestable, polymorphic: true
def relevant_transaction(user)
self.transactions.where('respondable_id = ?', user.id).first
end
end
class Transaction < ActiveRecord::Base
validates :name, :description, :listable, :respondable, presence: true
validates :respondable, uniqueness: { scope: :listable, message: 'You have already initialized a transaction on this item' }
belongs_to :listable, polymorphic: true
belongs_to :respondable, polymorphic: true
before_validation :set_name_and_description
private
def set_name_and_description
self.name = listable.name
self.description = listable.description
end
end
和 TransactionsController:
module Api
class TransactionsController < ApplicationController
def create
@transaction = current_user.responded_transactions.new(transaction_params)
if @transaction.save
render :show, status: :created
else
render json: @transaction.errors.full_messages, status: :unprocessable_entity
end
end
def update
@transaction = Transaction.find(params[:id])
if @transaction.save
render :show, status: :saved
else
render json: @transaction.errors.full_messages, status: :unprocessable_entity
end
end
private
def transaction_params
params.require(:transaction).permit(:listable_id, :listable_type)
end
end
end
最奇怪的是,在 Rails 控制器中,可以进行 User.first.responded_transactions 或 Transaction.first.respondable 等调用。然而,似乎与 respondable 相关的某些东西在某处失败了...任何帮助将不胜感激!
问题出在你的验证上。尝试单独验证您的多态列。让我告诉你:
validates(
:respondable_id,
uniqueness: {
scope: [:respondable_type, :listable_id, :listable_type],
message: "You've already initialized a transaction on this item"
}
)
几个小时以来一直在调试这个问题,但仍然找不到解决方案。当我在事务控制器的更新方法中发送调用 @transaction.save 的 PUT 请求时,我的服务器日志吐出:
NameError - uninitialized constant Transaction::Respondable:
基本相关架构是用户和组织都可以有请求,请求可以有事务,用户和组织也可以有事务。区别在于事务存在于初始化请求的 Person/Organization 1 和响应请求的 Person/Organization 2 之间。换句话说,一个事务同时属于一个请求(并通过一个请求 User/Orgnization 1)和 User/Organization 2。我现在只是在寻找用户,所以我不会包含有关组织的代码现在,因为它尚未实施。相关代码如下:
架构:
create_table "transactions", force: true do |t|
t.string "name", null: false
t.string "description", null: false
t.integer "listable_id", null: false
t.string "listable_type", null: false
t.integer "respondable_id", null: false
t.string "respondable_type", null: false
t.datetime "created_at"
t.datetime "updated_at"
end
listable 指的是 Request(也是多态的,因为它也可以来自 Offer,但现在不相关)。可响应指的是用户。
create_table "requests", force: true do |t|
t.string "name", null: false
t.string "description", null: false
t.integer "requestable_id", null: false
t.string "requestable_type", null: false
t.datetime "created_at"
t.datetime "updated_at"
end
用户模式无关紧要,因为它不包含指向其他表的链接(只有关系 has_many)。
这是我的模型:
class User < ActiveRecord::Base
...
has_many :requests, as: :requestable, dependent: :destroy
has_many :responded_transactions, class_name: 'Transaction', as: :respondable, dependent: :destroy
has_many :listed_transactions, through: :requests, source: :transactions
...
end
class Request < ActiveRecord::Base
validates :name, :description, :requestable, presence: true
has_many :transactions, as: :listable, dependent: :destroy
belongs_to :requestable, polymorphic: true
def relevant_transaction(user)
self.transactions.where('respondable_id = ?', user.id).first
end
end
class Transaction < ActiveRecord::Base
validates :name, :description, :listable, :respondable, presence: true
validates :respondable, uniqueness: { scope: :listable, message: 'You have already initialized a transaction on this item' }
belongs_to :listable, polymorphic: true
belongs_to :respondable, polymorphic: true
before_validation :set_name_and_description
private
def set_name_and_description
self.name = listable.name
self.description = listable.description
end
end
和 TransactionsController:
module Api
class TransactionsController < ApplicationController
def create
@transaction = current_user.responded_transactions.new(transaction_params)
if @transaction.save
render :show, status: :created
else
render json: @transaction.errors.full_messages, status: :unprocessable_entity
end
end
def update
@transaction = Transaction.find(params[:id])
if @transaction.save
render :show, status: :saved
else
render json: @transaction.errors.full_messages, status: :unprocessable_entity
end
end
private
def transaction_params
params.require(:transaction).permit(:listable_id, :listable_type)
end
end
end
最奇怪的是,在 Rails 控制器中,可以进行 User.first.responded_transactions 或 Transaction.first.respondable 等调用。然而,似乎与 respondable 相关的某些东西在某处失败了...任何帮助将不胜感激!
问题出在你的验证上。尝试单独验证您的多态列。让我告诉你:
validates(
:respondable_id,
uniqueness: {
scope: [:respondable_type, :listable_id, :listable_type],
message: "You've already initialized a transaction on this item"
}
)