视图不打印数据库列值(Ruby on Rails)
View does not print database column value (Ruby on Rails)
标题也可以是:update_column 语句没有在数据库中保存值,尽管日志表明发生了这种情况。
我想将 PDF 文件上传到 Google 云存储,为了开始,我下载了 Google 的示例 Rails 应用程序,我可以完美地工作(上传和下载)
然后我将代码复制到我自己的应用程序中(请参阅下面的相关文件)并且文件 UPloading 也能正常工作。
但是,由于某些原因,在 upload.rb 模型文件中,当 file
数据库列更新为 pdf_file 的正确 url 时 Google 云,该值未保存在数据库中。
日志表明它已保存,如您在行 SQL (0.3ms) UPDATE "uploads" SET "file" = 'https://pdf-uploads.storage.googleapis.com/uploads/2/Selection_002.png' WHERE "uploads"."id" = ? [["id", 2]]
中所见。当我尝试在我的视图中检索 link 以显示它时,文件列似乎是空的。
Web 服务器日志
begin transaction
SQL (0.3ms) INSERT INTO "uploads" ("songname", "artist", "album", "level", "video", "user_id", "genre_id", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) [["songname", "Hello"], ["artist", "Adele"], ["album", "Hello - Single"], ["level", 1], ["video", ""], ["user_id", 1], ["genre_id", 5], ["created_at", "2015-12-25 05:19:42.601108"], ["updated_at", "2015-12-25 05:19:42.601108"]]
SQL (0.3ms) UPDATE "uploads" SET "file" = 'https://pdf-uploads.storage.googleapis.com/uploads/2/Selection_002.png' WHERE "uploads"."id" = ? [["id", 2]]
(3.6ms) commit transaction
upload.rb 模型文件
attr_accessor :file
private
after_create :upload_file, if: :file
def upload_file
file_object = StorageBucket.files.new(
key: "uploads/#{id}/#{file.original_filename}",
body: file.read,
public: true
)
file_object.save
# this is what is causing the problem
update_columns file: file_object.public_url
end
uploads_controller.rb
def create
@upload = current_user.uploads.build(upload_params)
if params[:genre_id].blank?
@upload.genre = Genre.find_by_name('Uncategorized')
else
@upload.genre = Genre.find_by_id(params[:genre_id])
end
if @upload.level.blank?
@upload.level = 3
end
respond_to do |format|
if @upload.save
format.html { redirect_to @upload, notice: 'Upload was successfully created.' }
format.json { render :show, status: :created, location: @upload }
else
format.html { render :new }
format.json { render json: @upload.errors, status: :unprocessable_entity }
end
end
end
从 rails 控制台检查新条目
Upload.last
Upload Load (0.6ms) SELECT "uploads".* FROM "uploads" ORDER BY "uploads"."id" DESC LIMIT 1
=> #<Upload id: 2, songname: "Hello", artist: "Adele", album: "Hello - Single", level: 1, video: "", file: "https://pdf-uploads.storage.googleapis.com/uploads...", downloads: 0, views: 2, user_id: 1, genre_id: 5, created_at: "2015-12-25 05:19:42", updated_at: "2015-12-25 05:20:07">
如您所见,它在文件列中插入了一个值(由于某种原因被截断了……不确定这是否只是为了保持输出简短,或者截断的值是否实际存储在数据库中。
file: "https://pdf-uploads.storage.googleapis.com/uploads..."
现在,这就是问题的开始。
在我看来,我有这行代码 Upload URL: <%= @upload.file.to_s %>
来打印数据库文件列,但它什么也不打印(比如文件属性为空)。就像我解释的那样,我检查过该列绝对不是空白
我使用 table_print gem 从 rails 控制台打印数据库 table,它显示文件列为空白列(同样,没有知道为什么会那样做。Rails 记录打印机显示 截断的 url 存储在数据库中)
同样,我昨晚花了好几个小时弄明白了,但我自己弄不明白。预先感谢您的帮助。
attr_accessor
给你制造麻烦。
你为什么要用它?您的字段已经在数据库中。
如果 rails3 使用 attr_accessible
rails4 strong_params
.
编辑:
移除attr_accessor :file
在您的 uploads_controller 中,将 file
字段添加到 upload_params
方法。
确保您允许所有相关的上传参数,包括 :file
# app/controllers/uploads_controller.rb
class UploadsController < ApplicationController
def create
...
end
private
def upload_params
params.require(:some_required_param).permit(:genre_id, :file)
end
end
然后确保你的表单上有 :multipart => true
# some_view.html.erb
<%= form_tag({:action => "create"}, :method => :post, :multipart => true do %>
处的注释是由于变量 'file' 是一个字符串。如果你要 file.is_a? String
Ruby 会证实这一点。我假设文件是 URL:
=> #<Upload id: 2, songname: "Hello",
artist: "Adele", album: "Hello - Single",
level: 1, video: "",
file: "https://pdf-uploads.storage.googleapis.com/uploads...",
downloads: 0, views: 2, user_id: 1, genre_id: 5,
created_at: "2015-12-25 05:19:42", updated_at: "2015-12-25 05:20:07">
新的错误是因为String中没有方法original_filename。 attr_accessor 文件覆盖模型中的行为以允许将对象作为文件传递,该文件使用参数中传递的文件对象的实例更新列文件。
删除 attr_accessor 将允许从数据库中检索字符串(因此您可以 <%= @upload.file.to_s %>
)。然而,如果你有 attr_accesor 在那里,你的空实例变量 returns。
那么当你覆盖 getter 时,你如何获得在视图上显示的路径?
- 重命名
attr_accessor file
- 将
attr_accessor
更改为 attr_writter
以通过在参数中传递临时文件但返回字符串来维护更新文件
- 为
attributes[:file]
的 getter 创建一个实例方法
我认为第 2 种方法最简单,但可能会对下游产生一些严重的影响。实施#3 看起来像:
# app/models/upload.rb
def file_path
attributes['file']
end
# app/views/uploads/index.html.erb
<%= @upload.file_path %>
标题也可以是:update_column 语句没有在数据库中保存值,尽管日志表明发生了这种情况。
我想将 PDF 文件上传到 Google 云存储,为了开始,我下载了 Google 的示例 Rails 应用程序,我可以完美地工作(上传和下载) 然后我将代码复制到我自己的应用程序中(请参阅下面的相关文件)并且文件 UPloading 也能正常工作。
但是,由于某些原因,在 upload.rb 模型文件中,当 file
数据库列更新为 pdf_file 的正确 url 时 Google 云,该值未保存在数据库中。
日志表明它已保存,如您在行 SQL (0.3ms) UPDATE "uploads" SET "file" = 'https://pdf-uploads.storage.googleapis.com/uploads/2/Selection_002.png' WHERE "uploads"."id" = ? [["id", 2]]
中所见。当我尝试在我的视图中检索 link 以显示它时,文件列似乎是空的。
Web 服务器日志
begin transaction
SQL (0.3ms) INSERT INTO "uploads" ("songname", "artist", "album", "level", "video", "user_id", "genre_id", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) [["songname", "Hello"], ["artist", "Adele"], ["album", "Hello - Single"], ["level", 1], ["video", ""], ["user_id", 1], ["genre_id", 5], ["created_at", "2015-12-25 05:19:42.601108"], ["updated_at", "2015-12-25 05:19:42.601108"]]
SQL (0.3ms) UPDATE "uploads" SET "file" = 'https://pdf-uploads.storage.googleapis.com/uploads/2/Selection_002.png' WHERE "uploads"."id" = ? [["id", 2]]
(3.6ms) commit transaction
upload.rb 模型文件
attr_accessor :file
private
after_create :upload_file, if: :file
def upload_file
file_object = StorageBucket.files.new(
key: "uploads/#{id}/#{file.original_filename}",
body: file.read,
public: true
)
file_object.save
# this is what is causing the problem
update_columns file: file_object.public_url
end
uploads_controller.rb
def create
@upload = current_user.uploads.build(upload_params)
if params[:genre_id].blank?
@upload.genre = Genre.find_by_name('Uncategorized')
else
@upload.genre = Genre.find_by_id(params[:genre_id])
end
if @upload.level.blank?
@upload.level = 3
end
respond_to do |format|
if @upload.save
format.html { redirect_to @upload, notice: 'Upload was successfully created.' }
format.json { render :show, status: :created, location: @upload }
else
format.html { render :new }
format.json { render json: @upload.errors, status: :unprocessable_entity }
end
end
end
从 rails 控制台检查新条目
Upload.last
Upload Load (0.6ms) SELECT "uploads".* FROM "uploads" ORDER BY "uploads"."id" DESC LIMIT 1
=> #<Upload id: 2, songname: "Hello", artist: "Adele", album: "Hello - Single", level: 1, video: "", file: "https://pdf-uploads.storage.googleapis.com/uploads...", downloads: 0, views: 2, user_id: 1, genre_id: 5, created_at: "2015-12-25 05:19:42", updated_at: "2015-12-25 05:20:07">
如您所见,它在文件列中插入了一个值(由于某种原因被截断了……不确定这是否只是为了保持输出简短,或者截断的值是否实际存储在数据库中。
file: "https://pdf-uploads.storage.googleapis.com/uploads..."
现在,这就是问题的开始。
在我看来,我有这行代码 Upload URL: <%= @upload.file.to_s %>
来打印数据库文件列,但它什么也不打印(比如文件属性为空)。就像我解释的那样,我检查过该列绝对不是空白
我使用 table_print gem 从 rails 控制台打印数据库 table,它显示文件列为空白列(同样,没有知道为什么会那样做。Rails 记录打印机显示 截断的 url 存储在数据库中)
同样,我昨晚花了好几个小时弄明白了,但我自己弄不明白。预先感谢您的帮助。
attr_accessor
给你制造麻烦。
你为什么要用它?您的字段已经在数据库中。
如果 rails3 使用 attr_accessible
rails4 strong_params
.
编辑:
移除attr_accessor :file
在您的 uploads_controller 中,将 file
字段添加到 upload_params
方法。
确保您允许所有相关的上传参数,包括 :file
# app/controllers/uploads_controller.rb
class UploadsController < ApplicationController
def create
...
end
private
def upload_params
params.require(:some_required_param).permit(:genre_id, :file)
end
end
然后确保你的表单上有 :multipart => true
# some_view.html.erb
<%= form_tag({:action => "create"}, :method => :post, :multipart => true do %>
file.is_a? String
Ruby 会证实这一点。我假设文件是 URL:
=> #<Upload id: 2, songname: "Hello", artist: "Adele", album: "Hello - Single", level: 1, video: "", file: "https://pdf-uploads.storage.googleapis.com/uploads...", downloads: 0, views: 2, user_id: 1, genre_id: 5, created_at: "2015-12-25 05:19:42", updated_at: "2015-12-25 05:20:07">
新的错误是因为String中没有方法original_filename。 attr_accessor 文件覆盖模型中的行为以允许将对象作为文件传递,该文件使用参数中传递的文件对象的实例更新列文件。
删除 attr_accessor 将允许从数据库中检索字符串(因此您可以 <%= @upload.file.to_s %>
)。然而,如果你有 attr_accesor 在那里,你的空实例变量 returns。
那么当你覆盖 getter 时,你如何获得在视图上显示的路径?
- 重命名
attr_accessor file
- 将
attr_accessor
更改为attr_writter
以通过在参数中传递临时文件但返回字符串来维护更新文件 - 为
attributes[:file]
的 getter 创建一个实例方法
我认为第 2 种方法最简单,但可能会对下游产生一些严重的影响。实施#3 看起来像:
# app/models/upload.rb
def file_path
attributes['file']
end
# app/views/uploads/index.html.erb
<%= @upload.file_path %>