Rails activerecord - 无法访问列别名
Rails activerecord - cannot access column slug
我决定在我的 URL 中添加 slug,我添加了一个名为 "slug" 的列,创建了迁移,成功迁移了它,验证了数据库中存在一个列:
但是我无法创建记录,因为出现以下错误:
NoMethodError: #Hotel:0x3d19a60
的未定义方法`slug='
我正在使用 friendly_id 库,但这个问题可能与库本身无关。无论如何,这里有一些相关数据:
- Rails 版本: 4.2.4
- Ruby 版本: 2.1.7
- Frienldy ID 版本: 5.1.0
- 数据库: Postgres 9.3.5
部分酒店模型class:
class Hotel < ActiveRecord::Base
extend FriendlyId
friendly_id :generate_slug, use: :slugged
def generate_slug
"#{self.name} #{self.id}"
end
def should_generate_new_friendly_id?
name_changed? || new_record?
end
def normalize_friendly_id(text)
super(I18n.transliterate(text))
end
部分代码,调用保存时抛出的错误(数据被隐藏):
rest = Hotel.new(:name => "*", :telephone => "*", :email => "*", :web_page => "*", :state => 1, :city_search => "*", :smoking => *,
:address_attributes => {:city => "*", :street => "*", :postal_code => "*", :country_code => "*"})
ObjectSkipValidator.setup_validations(rest, nil)
rest.save!
当然 table 有 slug 列,我的迁移:
AFFECTED_TABLES = [:restaurants, :hotels]
def change
AFFECTED_TABLES.each do |tab|
add_column tab, :slug, :string
add_index tab, :slug, unique: true
end
end
我试图重写 ActiveRecord,这样我就可以看到问题出在哪里,看起来 attribute_missing 方法中需要的属性散列不包含列 "slug" 但所有其他列存在。
ActiveRecord::AttributeSet::Builder.build_from_database - 调用时,值不包含 slug 列
还有这部分方法ActiveModel::AttributeMethods。method_missing:
match = match_attribute_method?(method.to_s)
match ? attribute_missing(match, *args, &block) : super
从不调用 attribute_missing,因此没有为此特定列创建 getter 和 setter,因为匹配器找不到 slug 列。
那么,为什么我无法访问或设置模型的 "slug" 属性?感谢您的任何回复。
编辑:
感谢 Sean 的评论,看起来问题出在数据库填充之前的某些步骤中。这个任务正在填充 - 我已经使用它很长时间了,没有任何问题 - 在 db:populate 任务期间抛出错误:
task prepare_all: :environment do
puts "==== PREPARING DATABASE ===="
Rake::Task["db:drop"].invoke()
Rake::Task["db:create"].invoke()
Rake::Task["db:migrate"].invoke()
Rake::Task["db:populate"].invoke()
Rake::Task["db:codetables_populate"].invoke()
Rake::Task["db:geocode"].invoke()
puts "==== DATABASE PREPARED ===="
end
任务执行使用:
bundle exec rake db:prepare_all RAILS_ENV=development
如果我运行一项一项的任务,例如。 db:drop、db:create、db:migrate、db:populate,它按预期工作并且正在创建 slug。看来我的任务调用方式是错误的。
看起来问题出在 rake 任务本身。我不确定发生错误的原因(为什么没有添加最后一次迁移),但如果我在任务之外删除并创建数据库,它可以使用以下设置。任务现在看起来像这样:
task prepare_all: :environment do
puts "==== PREPARING DATABASE ===="
Rake::Task["db:migrate"].invoke
Rake::Task["db:reset"].invoke
Rake::Task["db:populate"].invoke
Rake::Task["db:codetables_populate"].invoke
Rake::Task["db:geocode"].invoke
puts "==== DATABASE PREPARED ===="
end
我决定在我的 URL 中添加 slug,我添加了一个名为 "slug" 的列,创建了迁移,成功迁移了它,验证了数据库中存在一个列:
但是我无法创建记录,因为出现以下错误:
NoMethodError: #Hotel:0x3d19a60
的未定义方法`slug='我正在使用 friendly_id 库,但这个问题可能与库本身无关。无论如何,这里有一些相关数据:
- Rails 版本: 4.2.4
- Ruby 版本: 2.1.7
- Frienldy ID 版本: 5.1.0
- 数据库: Postgres 9.3.5
部分酒店模型class:
class Hotel < ActiveRecord::Base
extend FriendlyId
friendly_id :generate_slug, use: :slugged
def generate_slug
"#{self.name} #{self.id}"
end
def should_generate_new_friendly_id?
name_changed? || new_record?
end
def normalize_friendly_id(text)
super(I18n.transliterate(text))
end
部分代码,调用保存时抛出的错误(数据被隐藏):
rest = Hotel.new(:name => "*", :telephone => "*", :email => "*", :web_page => "*", :state => 1, :city_search => "*", :smoking => *,
:address_attributes => {:city => "*", :street => "*", :postal_code => "*", :country_code => "*"})
ObjectSkipValidator.setup_validations(rest, nil)
rest.save!
当然 table 有 slug 列,我的迁移:
AFFECTED_TABLES = [:restaurants, :hotels]
def change
AFFECTED_TABLES.each do |tab|
add_column tab, :slug, :string
add_index tab, :slug, unique: true
end
end
我试图重写 ActiveRecord,这样我就可以看到问题出在哪里,看起来 attribute_missing 方法中需要的属性散列不包含列 "slug" 但所有其他列存在。
ActiveRecord::AttributeSet::Builder.build_from_database - 调用时,值不包含 slug 列
还有这部分方法ActiveModel::AttributeMethods。method_missing:
match = match_attribute_method?(method.to_s)
match ? attribute_missing(match, *args, &block) : super
从不调用 attribute_missing,因此没有为此特定列创建 getter 和 setter,因为匹配器找不到 slug 列。
那么,为什么我无法访问或设置模型的 "slug" 属性?感谢您的任何回复。
编辑: 感谢 Sean 的评论,看起来问题出在数据库填充之前的某些步骤中。这个任务正在填充 - 我已经使用它很长时间了,没有任何问题 - 在 db:populate 任务期间抛出错误:
task prepare_all: :environment do
puts "==== PREPARING DATABASE ===="
Rake::Task["db:drop"].invoke()
Rake::Task["db:create"].invoke()
Rake::Task["db:migrate"].invoke()
Rake::Task["db:populate"].invoke()
Rake::Task["db:codetables_populate"].invoke()
Rake::Task["db:geocode"].invoke()
puts "==== DATABASE PREPARED ===="
end
任务执行使用:
bundle exec rake db:prepare_all RAILS_ENV=development
如果我运行一项一项的任务,例如。 db:drop、db:create、db:migrate、db:populate,它按预期工作并且正在创建 slug。看来我的任务调用方式是错误的。
看起来问题出在 rake 任务本身。我不确定发生错误的原因(为什么没有添加最后一次迁移),但如果我在任务之外删除并创建数据库,它可以使用以下设置。任务现在看起来像这样:
task prepare_all: :environment do
puts "==== PREPARING DATABASE ===="
Rake::Task["db:migrate"].invoke
Rake::Task["db:reset"].invoke
Rake::Task["db:populate"].invoke
Rake::Task["db:codetables_populate"].invoke
Rake::Task["db:geocode"].invoke
puts "==== DATABASE PREPARED ===="
end