回形针在更新时删除现有附件
paperclip removes existing attachment on update
AR 模型
class Post < ActiveRecord::Base
has_one :sponsor
accepts_nested_attributes_for :sponsor
end
class Sponsor < ActiveRecord::Base
has_attached_file :logo
belongs_to :post
end
控制器
def update
if @post.update(post_params)
flash[:success] = 'Post update sucessfully'
else
flash[:error] = @post.errors.full_messages.join(', ')
render :edit
end
end
def post_params
params.require(:post).permit(:title, :content, sponsor_attributes: [:descriptive_text, :logo, :name, :website, :description])
end
此处,当 Post
更新时,赞助商也会以嵌套形式更新。
但是,如果用户没有选择任何图像,在更新时,Paperclip 会删除现有附件。
如果用户在更新记录时没有 select 其他附件,我们如何保留现有附件?
accepts_nested_attributes_for :sponsor, reject_if: :all_blank
你遇到的问题是,不幸的是,Paperclip 在接受数据方面实际上相当 "dumb"。
由于许多人向 Paperclip 发送关联数据,它基本上会根据所提供的内容构建对象。在您的情况下,这意味着您正在发送空白对象,导致 Paperclip 将您现有的附件替换为空白对象。
accepts_nested_attributes_for
的 reject_if
开关解决了这个问题——它允许您指定 Rails 将 "reject" 任何嵌套数据的任何场合,保留你有文件...
reject_if
Allows you to specify a Proc
or a Symbol
pointing to a method that checks whether a record should be built for a certain attribute hash.
The hash is passed to the supplied Proc or the method and it should return either true or false. When no :reject_if
is specified, a record will be built for all attribute hashes that do not have a _destroy value that evaluates to true.
Passing :all_blank
instead of a Proc
will create a proc that will reject a record where all the attributes are blank excluding any value for _destroy
.
需要注意的是,如果您要更新图像之外的 其他(我看到您有 :descriptive_text
、:logo
、:name
、:website
、:description
)。
在这种情况下,您需要将适当的数据传递给您的 Sponsor
模型(IE 没有 logo
参数):
def post_params
sponsor_params = [:id, :descriptive_text, :logo, :name, :website, :description]
sponsor_params -= [:logo] if (action_name == "update") && !params[:post][:sponsor_attributes][:logo]
params.require(:post).permit(:title, :content, sponsor_attributes: sponsor_params)
end
我相信 Paperclip validators 有更好的方法来做到这一点,但现在以上应该足够了。
参考文献:
- Preventing Paperclip from deleting/overwriting attachments on update
- Rails with Paperclip ignore empty attachments
AR 模型
class Post < ActiveRecord::Base
has_one :sponsor
accepts_nested_attributes_for :sponsor
end
class Sponsor < ActiveRecord::Base
has_attached_file :logo
belongs_to :post
end
控制器
def update
if @post.update(post_params)
flash[:success] = 'Post update sucessfully'
else
flash[:error] = @post.errors.full_messages.join(', ')
render :edit
end
end
def post_params
params.require(:post).permit(:title, :content, sponsor_attributes: [:descriptive_text, :logo, :name, :website, :description])
end
此处,当 Post
更新时,赞助商也会以嵌套形式更新。
但是,如果用户没有选择任何图像,在更新时,Paperclip 会删除现有附件。
如果用户在更新记录时没有 select 其他附件,我们如何保留现有附件?
accepts_nested_attributes_for :sponsor, reject_if: :all_blank
你遇到的问题是,不幸的是,Paperclip 在接受数据方面实际上相当 "dumb"。
由于许多人向 Paperclip 发送关联数据,它基本上会根据所提供的内容构建对象。在您的情况下,这意味着您正在发送空白对象,导致 Paperclip 将您现有的附件替换为空白对象。
accepts_nested_attributes_for
的 reject_if
开关解决了这个问题——它允许您指定 Rails 将 "reject" 任何嵌套数据的任何场合,保留你有文件...
reject_if
Allows you to specify a
Proc
or aSymbol
pointing to a method that checks whether a record should be built for a certain attribute hash.The hash is passed to the supplied Proc or the method and it should return either true or false. When no
:reject_if
is specified, a record will be built for all attribute hashes that do not have a _destroy value that evaluates to true.Passing
:all_blank
instead of aProc
will create a proc that will reject a record where all the attributes are blank excluding any value for_destroy
.
需要注意的是,如果您要更新图像之外的 其他(我看到您有 :descriptive_text
、:logo
、:name
、:website
、:description
)。
在这种情况下,您需要将适当的数据传递给您的 Sponsor
模型(IE 没有 logo
参数):
def post_params
sponsor_params = [:id, :descriptive_text, :logo, :name, :website, :description]
sponsor_params -= [:logo] if (action_name == "update") && !params[:post][:sponsor_attributes][:logo]
params.require(:post).permit(:title, :content, sponsor_attributes: sponsor_params)
end
我相信 Paperclip validators 有更好的方法来做到这一点,但现在以上应该足够了。
参考文献:
- Preventing Paperclip from deleting/overwriting attachments on update
- Rails with Paperclip ignore empty attachments