使用活动记录保存时出错
Error when saving using active records
我正在尝试使用 .rake
文件保存记录。但是我在尝试保存更改时遇到错误。
error.message
SQLite3::ConstraintException: UNIQUE constraint failed: versions.id: INSERT INTO "versions" ("app_id", "created_at", "icon_url", "id", "plist_url", "updated_at", "version_number") VALUES (?, ?, ?, ?, ?, ?, ?)
inbox.rake 文件
namespace :inbox do
desc 'Check inbox for new app builds'
task process_inbox: :environment do
# initialize s3 client
s3 = AWS::S3.new
bucket = s3.buckets['my-bucket']
s3_host = 'https://...s3.amazonaws.com/'
exclude_inbox = bucket.objects.select do |s3_object|
s3_object.key.exclude? '_inbox'
end
#find plist within the inbox
plist_objects = exclude_inbox.select do |s3_object|
s3_object.key.include? 'plist'
end
for plist_object in plist_objects
plist = CFPropertyList::List.new(:data => plist_object.read)
data = CFPropertyList.native_types(plist.value)
name = data['items'][0]['metadata']['title']
bundle_version = data['items'][0]['metadata']['bundle-version']
plist_copy = plist_object.copy_to("#{name}/#{bundle_version}/#{name}.plist")
kind = data['items'][0]['metadata']['kind']
plist = CFPropertyList::List.new(:data => plist_copy.read)
data = CFPropertyList.native_types(plist.value)
icon_url = data['items'][0]['assets'][1]['url']
full_url = plist_copy.url_for(:read)
icon = bucket.objects[icon_url.gsub(s3_host, '')]
#find app or create a new app based on its name and kind
app = App.find_or_initialize_by(name: name, app_type: kind)
#app.save unless app.id
#find version or create new version base on app_id and bundle_version
version = Version.find_or_initialize_by(app_id: app.id, id: bundle_version)
version.plist_url = full_url.scheme + '://' + full_url.host + full_url.path
version.icon_url = icon.copy_to("#{name}/#{bundle_version}/#{icon_url.split('/').last.gsub('~','_')}").url_for(:read).to_s
version.version_number = bundle_version
version.app = app
#update app version number
app.version_number = version.version_number
#save changes
begin
app.save
version.save
puts app.attributes , version.attributes
rescue => error
puts error.message
end
end
end
end
这一行就是问题所在
Version.find_or_initialize_by(app_id: app.id, id: bundle_version)
我猜 id 是这里的主键。由于您正在对两个值执行 find_or_initialize
,因此当数据库中存在给定 bundle_version 但不同 app_id
的版本时,您将获得一个新版本
你可能应该这样做,
version = Version.find_or_initialize_by(id: bundle_version)
version.app_id = app.id
这是有问题的行:
version = Version.find_or_initialize_by(app_id: app.id, id: bundle_version)
这更冗长,但可能更符合您的要求:
version = Version.find_by(id: bundle_version, app_id: app.id) || Version.new(app_id: app.id)
我正在尝试使用 .rake
文件保存记录。但是我在尝试保存更改时遇到错误。
error.message
SQLite3::ConstraintException: UNIQUE constraint failed: versions.id: INSERT INTO "versions" ("app_id", "created_at", "icon_url", "id", "plist_url", "updated_at", "version_number") VALUES (?, ?, ?, ?, ?, ?, ?)
inbox.rake 文件
namespace :inbox do
desc 'Check inbox for new app builds'
task process_inbox: :environment do
# initialize s3 client
s3 = AWS::S3.new
bucket = s3.buckets['my-bucket']
s3_host = 'https://...s3.amazonaws.com/'
exclude_inbox = bucket.objects.select do |s3_object|
s3_object.key.exclude? '_inbox'
end
#find plist within the inbox
plist_objects = exclude_inbox.select do |s3_object|
s3_object.key.include? 'plist'
end
for plist_object in plist_objects
plist = CFPropertyList::List.new(:data => plist_object.read)
data = CFPropertyList.native_types(plist.value)
name = data['items'][0]['metadata']['title']
bundle_version = data['items'][0]['metadata']['bundle-version']
plist_copy = plist_object.copy_to("#{name}/#{bundle_version}/#{name}.plist")
kind = data['items'][0]['metadata']['kind']
plist = CFPropertyList::List.new(:data => plist_copy.read)
data = CFPropertyList.native_types(plist.value)
icon_url = data['items'][0]['assets'][1]['url']
full_url = plist_copy.url_for(:read)
icon = bucket.objects[icon_url.gsub(s3_host, '')]
#find app or create a new app based on its name and kind
app = App.find_or_initialize_by(name: name, app_type: kind)
#app.save unless app.id
#find version or create new version base on app_id and bundle_version
version = Version.find_or_initialize_by(app_id: app.id, id: bundle_version)
version.plist_url = full_url.scheme + '://' + full_url.host + full_url.path
version.icon_url = icon.copy_to("#{name}/#{bundle_version}/#{icon_url.split('/').last.gsub('~','_')}").url_for(:read).to_s
version.version_number = bundle_version
version.app = app
#update app version number
app.version_number = version.version_number
#save changes
begin
app.save
version.save
puts app.attributes , version.attributes
rescue => error
puts error.message
end
end
end
end
这一行就是问题所在
Version.find_or_initialize_by(app_id: app.id, id: bundle_version)
我猜 id 是这里的主键。由于您正在对两个值执行 find_or_initialize
,因此当数据库中存在给定 bundle_version 但不同 app_id
你可能应该这样做,
version = Version.find_or_initialize_by(id: bundle_version)
version.app_id = app.id
这是有问题的行:
version = Version.find_or_initialize_by(app_id: app.id, id: bundle_version)
这更冗长,但可能更符合您的要求:
version = Version.find_by(id: bundle_version, app_id: app.id) || Version.new(app_id: app.id)