def destroy
@original_picture = OriginalPicture.edit(params[:id], @artist)
- OriginalPicture.transaction do
- @original_picture.destroy
- end
respond_to do |format|
- format.html { redirect_to original_pictures_url }
- format.json { head :ok }
+ if @original_picture.destroy_with_resource_picture
+ format.html { redirect_to original_pictures_url }
+ format.json { head :ok }
+ else
+ format.html { redirect_to original_picture_path(@original_picture) }
+ format.json { render json: @original_picture.errors, status: :unprocessable_entity }
+ end
end
end
end
class Author < ActiveRecord::Base
has_one :artist
belongs_to :user
- has_many :comic
- has_many :panel
+ has_many :comics
+ has_many :panels
validates :name, :presence => true, :length => {:maximum => 30}
validates :user_id, :numericality => true, :existence => {:both => false}
validates :artist_id, :presence => true, :numericality => true, :existence => {:both => false}
validates :md5, :presence => true, :length => {:minimum => 32, :maximum => 32}
- before_destroy :destroy_with_file
-
def supply_default
end
{:include => {:resource_picture => {}, :pictures => {}}}
end
- def destroy_with_file
- PictureIO.original_picture_io.delete self.filename
- self.resource_picture.destroy
- end
-
def store(imager)
unless imager
self.errors.add :base, I18n.t('errors.invalid_image')
PictureIO.original_picture_io.get self.filename, subdir
end
+ def destroy_with_resource_picture
+ res = false
+ OriginalPicture.transaction do
+ begin
+ PictureIO.original_picture_io.delete(self.filename) if PictureIO.original_picture_io.exist?(self.filename)
+ rescue PictureIO::Error
+ res = false
+ raise ActiveRecord::Rollback
+ end
+ if self.resource_picture
+ res = self.resource_picture.unpublish
+ raise ActiveRecord::Rollback unless res
+ end
+ self.pictures.each do |picture|
+ res = picture.unpublish
+ raise ActiveRecord::Rollback unless res
+ end
+ res = self.destroy
+ raise ActiveRecord::Rollback unless res
+ end
+ res
+ end
+
def self.export ar
l = LicenseGroup.list
op = OriginalPicture.list ar.id
end
def showable? au = nil
+ return false unless self.original_picture
return true if self.own?(au)
self.enable? and self.head?
end
PictureIO.picture_io.get self.filename, subdir
end
+ def unpublish
+ imager = PettanImager.load(File.open(Rails.root + 'app/assets/images/error.png', 'rb').read)
+ return false unless imager
+ self.store imager
+ end
+
def credit_template
"#{self.classname.tableize}/attributes/credit"
end
res = false
ResourcePicture.transaction do
begin
- if res = self.destroy
- PictureIO.resource_picture_io.delete(self.filename)
- PictureIO.resource_picture_io.delete(self.filename, 'full')
- res = true
- end
+ PictureIO.resource_picture_io.delete(self.filename) if PictureIO.resource_picture_io.exist?(self.filename)
+ PictureIO.resource_picture_io.delete(self.filename, 'full') if PictureIO.resource_picture_io.exist?(self.filename, 'full')
rescue PictureIO::Error
res = false
raise ActiveRecord::Rollback
end
+ res = self.destroy
+ raise ActiveRecord::Rollback unless res
end
res
end
self.author.panels.each do |panel|
raise ActiveRecord::Rollback unless panel.destroy_with_elements
end
+ if self.author.artist
+ self.author.artist.original_pictures.each do |original_picture|
+ raise ActiveRecord::Rollback unless original_picture.destroy_with_resource_picture
+ end
+ raise ActiveRecord::Rollback unless self.author.artist.destroy
+ end
raise ActiveRecord::Rollback unless self.author.destroy
- raise ActiveRecord::Rollback unless self.destroy
+ raise ActiveRecord::Rollback unless super
res = true
end
res
<h1><%= t('.title') %></h1>
<div>
- <% if @picture.enable? %>
- <% if @picture.head? %>
+ <% if @picture.original_picture %>
+ <% if @picture.enable? %>
+ <% if @picture.head? %>
+ <p>
+ <%= t 'pictures.show.announce.head' -%>
+ <%= link_to tag(:img, @picture.tmb_opt_img_tag), resource_picture_path(@picture.resource_picture) %>
+ </p>
+ <% else %>
+ <p>
+ <%= t 'pictures.show.announce.tail' -%>
+ <%= link_to tag(:img, @picture.head.tmb_opt_img_tag), resource_picture_path(@picture.head.resource_picture) %>
+ </p>
+ <% end %>
+ <% else %>
<p>
- <%= t 'pictures.show.announce.head' -%>
- <%= link_to tag(:img, @picture.tmb_opt_img_tag), resource_picture_path(@picture.resource_picture) %>
+ <%= t 'pictures.show.announce.disable' -%>
</p>
- <% else %>
+ <% end %>
+ <% if @picture.own? @artist %>
<p>
- <%= t 'pictures.show.announce.tail' -%>
- <%= link_to tag(:img, @picture.head.tmb_opt_img_tag), resource_picture_path(@picture.head.resource_picture) %>
+ <%= t 'pictures.show.announce.owner' -%>
+ <%= link_to tag(:img, @picture.original_picture.tmb_opt_img_tag), original_picture_path(@picture.original_picture) %>
</p>
<% end %>
<% else %>
<p>
- <%= t 'pictures.show.announce.disable' -%>
- </p>
- <% end %>
- <% if @picture.own? @artist %>
- <p>
- <%= t 'pictures.show.announce.owner' -%>
- <%= link_to tag(:img, @picture.original_picture.tmb_opt_img_tag), original_picture_path(@picture.original_picture) %>
+ <%= t 'pictures.show.announce.destroyed' -%>
</p>
<% end %>
</div>
head: 素材として利用できます。
tail: この画像は既に改訂されています。素材として利用するなら、こちら(最新版)が利用できます。
owner: あなたの画像です。原画を管理するなら、こちらを利用してください。
+ destroyed: この素材は削除されています。素材として利用できません。
md5:
title: 実素材MD5検索一覧
credit:
end
end
+ describe '削除に於いて' do
+ before do
+ @op = FactoryGirl.create :original_picture, :artist_id => @artist.id
+ sign_in @user
+ end
+ context '事前チェックしておく' do
+ before do
+ OriginalPicture.stub(:edit).with(any_args()).and_return @op
+ OriginalPicture.any_instance.stub(:destroy_with_resource_picture).with(any_args()).and_return(true)
+ end
+ it '原画モデルに編集取得を問い合わせている' do
+ OriginalPicture.should_receive(:edit).exactly(1)
+ delete :destroy, :id => @op.id
+ end
+ it 'モデルに削除を依頼する' do
+ OriginalPicture.any_instance.should_receive(:destroy_with_resource_picture).exactly(1)
+ delete :destroy, :id => @op.id
+ end
+ it '@original_pictureにアレを取得している' do
+ delete :destroy, :id => @op.id
+ assigns(:original_picture).id.should eq(@op.id)
+ end
+ end
+ context 'つつがなく終わるとき' do
+ before do
+ OriginalPicture.any_instance.stub(:destroy_with_resource_picture).with(any_args()).and_return(true)
+ end
+ context 'html形式' do
+ it 'ステータスコード302 Foundを返す' do
+ delete :destroy, :id => @op.id
+ response.status.should eq 302
+ end
+ it '原画の一覧ページへ遷移する' do
+ delete :destroy, :id => @op.id
+ response.should redirect_to(original_pictures_path)
+ end
+ end
+ context 'json形式' do
+ it 'ステータスコード200 OKを返す' do
+ delete :destroy, :id => @op.id, :format => :json
+ response.should be_success
+ end
+ it 'ページ本体は特に返さない' do
+ delete :destroy, :id => @op.id, :format => :json
+ response.body.should match /./
+ end
+ end
+ end
+ context '作家権限がないとき' do
+ before do
+ sign_out @user
+ end
+ it 'ステータスコード302 Foundを返す' do
+ delete :destroy, :id => @op.id
+ response.status.should eq 302
+ end
+ context 'html形式' do
+ it 'サインインページへ遷移する' do
+ delete :destroy, :id => @op.id
+ response.body.should redirect_to '/users/sign_in'
+ end
+ end
+ context 'json形式' do
+ it '応答メッセージにUnauthorizedを返す' do
+ delete :destroy, :id => @op.id, :format => :json
+ response.message.should match(/Unauthorized/)
+ end
+ end
+ end
+ context '削除に失敗したとき' do
+ before do
+ OriginalPicture.any_instance.stub(:destroy_with_resource_picture).and_return(false)
+ end
+ context 'html形式' do
+ it 'ステータスコード302 Foundを返す' do
+ delete :destroy, :id => @op.id
+ response.status.should eq 302
+ end
+ it 'その原画の詳細ページへ遷移する' do
+ delete :destroy, :id => @op.id
+ response.should redirect_to(original_picture_path(@op))
+ end
+ end
+ context 'json形式' do
+ it 'ステータスコード422 unprocessable_entity を返す' do
+ delete :destroy, :id => @op.id, :format => :json
+ response.status.should eq 422
+ end
+ it '応答メッセージUnprocessable Entityを返す' do
+ delete :destroy, :id => @op.id, :format => :json
+ response.message.should match(/Unprocessable/)
+ end
+ end
+ end
+ end
end
end
end
+ describe '削除に於いて' do
+ before do
+ @op = FactoryGirl.create :original_picture, :artist_id => @artist.id
+ end
+ context '事前チェックしておく' do
+ before do
+ OriginalPicture.any_instance.stub(:destroy).and_return(true)
+ ResourcePicture.any_instance.stub(:unpublish).and_return(true)
+ Picture.any_instance.stub(:unpublish).with(any_args).and_return(true)
+ PictureIO.original_picture_io.stub(:delete).with(any_args).and_return(true)
+ end
+ it '原画モデルに削除を依頼している' do
+ OriginalPicture.any_instance.should_receive(:destroy).exactly(1)
+ r = @op.destroy_with_resource_picture
+ end
+ it '保管庫に原画の画像データ削除を依頼している' do
+ PictureIO.original_picture_io.should_receive(:delete).with(@op.filename).exactly(1)
+ r = @op.destroy_with_resource_picture
+ end
+ context '自身にリンクされた素材があるとき' do
+ it '素材モデルに削除を依頼している' do
+ @p = FactoryGirl.create :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id, :revision => 0
+ @rp = FactoryGirl.create :resource_picture, :artist_id => @artist.id, :license_id => @license.id, :original_picture_id => @op.id, :picture_id => @p.id
+ ResourcePicture.any_instance.should_receive(:unpublish).exactly(1)
+ r = @op.destroy_with_resource_picture
+ end
+ end
+ context '自身にリンクされた素材がないとき' do
+ it '素材モデルに削除を依頼しない' do
+ ResourcePicture.any_instance.should_not_receive(:unpublish)
+ r = @op.destroy_with_resource_picture
+ end
+ end
+ context '自身にリンクされた実素材があるとき' do
+ it 'すべての実素材に墨塗を依頼している' do
+ @p = FactoryGirl.create :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id, :revision => 0
+ Picture.any_instance.should_receive(:unpublish).with(any_args).exactly(1)
+ r = @op.destroy_with_resource_picture
+ end
+ end
+ context '自身にリンクされた実素材がないとき' do
+ it '実素材に墨塗を依頼しない' do
+ Picture.any_instance.should_not_receive(:unpublish)
+ r = @op.destroy_with_resource_picture
+ end
+ end
+ end
+ context 'つつがなく終わるとき' do
+ before do
+ PictureIO.original_picture_io.stub(:delete).with(any_args).and_return(true)
+ @p = FactoryGirl.create :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id, :revision => 0
+ @rp = FactoryGirl.create :resource_picture, :artist_id => @artist.id, :license_id => @license.id, :original_picture_id => @op.id, :picture_id => @p.id
+ end
+ it '自身を削除する' do
+ lambda {
+ r = @op.destroy_with_resource_picture
+ }.should change(OriginalPicture, :count).by(-1)
+ lambda {
+ r = OriginalPicture.find @op.id
+ }.should raise_error
+ end
+ it 'Trueを返す' do
+ r = @op.destroy_with_resource_picture
+ r.should be_true
+ end
+ end
+ context '自身の削除に失敗したとき' do
+ before do
+ OriginalPicture.any_instance.stub(:destroy).with(any_args).and_return(false)
+ end
+ it 'Falseを返す' do
+ r = @op.destroy_with_resource_picture
+ r.should be_false
+ end
+ it 'ロールバックしている' do
+ lambda {
+ r = @op.destroy_with_resource_picture
+ }.should_not change(OriginalPicture, :count)
+ end
+ end
+ context '画像の削除に失敗したとき' do
+ before do
+ PictureIO.original_picture_io.stub(:delete).with(@op.filename).and_raise(PictureIO::Error)
+ end
+ it 'Falseを返す' do
+ r = @op.destroy_with_resource_picture
+ r.should be_false
+ end
+ it 'ロールバックしている' do
+ lambda {
+ r = @op.destroy_with_resource_picture
+ }.should_not change(OriginalPicture, :count)
+ end
+ end
+ context '素材の削除に失敗とき' do
+ before do
+ @p = FactoryGirl.create :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id, :revision => 0
+ @rp = FactoryGirl.create :resource_picture, :artist_id => @artist.id, :license_id => @license.id, :original_picture_id => @op.id, :picture_id => @p.id
+ ResourcePicture.any_instance.stub(:unpublish).with(any_args).and_return(false)
+ end
+ it 'Falseを返す' do
+ r = @op.destroy_with_resource_picture
+ r.should be_false
+ end
+ it 'ロールバックしている' do
+ lambda {
+ r = @op.destroy_with_resource_picture
+ }.should_not change(OriginalPicture, :count)
+ lambda {
+ r = @op.destroy_with_resource_picture
+ }.should_not change(ResourcePicture, :count)
+ end
+ end
+ context '実素材の墨塗に失敗とき' do
+ before do
+ @p = FactoryGirl.create :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id, :revision => 0
+ @rp = FactoryGirl.create :resource_picture, :artist_id => @artist.id, :license_id => @license.id, :original_picture_id => @op.id, :picture_id => @p.id
+ Picture.any_instance.stub(:unpublish).with(any_args).and_return(false)
+ end
+ it 'Falseを返す' do
+ r = @op.destroy_with_resource_picture
+ r.should be_false
+ end
+ it 'ロールバックしている' do
+ lambda {
+ r = @op.destroy_with_resource_picture
+ }.should_not change(OriginalPicture, :count)
+ lambda {
+ r = @op.destroy_with_resource_picture
+ }.should_not change(ResourcePicture, :count)
+ end
+ end
+ end
+
=begin
describe 'エクスポートに於いて' do
before do
before do
@p = FactoryGirl.build :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id
end
+ context '自身に原画がリンクしていないとき' do
+ before do
+ Picture.any_instance.stub(:original_picture).with(any_args).and_return(nil)
+ end
+ it 'Falseを返す' do
+ r = @p.showable?(@author)
+ r.should be_false
+ end
+ end
it '自作の実素材ならyes' do
Picture.any_instance.stub(:own?).with(any_args).and_return(true)
@p.showable?(@artist).should == true
end
+ describe '墨塗に於いて' do
+ before do
+ @p = FactoryGirl.create :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id, :ext => 'png'
+ end
+ context '事前チェック' do
+ before do
+ @imager = ImagerTest.load "abc\ndef\nghi"
+ Picture.any_instance.stub(:store).with(any_args).and_return(true)
+ PettanImager.stub(:load).with(any_args).and_return(@imager)
+ end
+ it '画像ライブラリにロードを依頼している' do
+ PettanImager.should_receive(:load).with(any_args).exactly(1)
+ r = @p.unpublish
+ end
+ it '自身に作成を依頼している' do
+ Picture.any_instance.should_receive(:store).with(any_args).exactly(1)
+ r = @p.unpublish
+ end
+ end
+ context 'つつがなく終わるとき' do
+ before do
+ Picture.any_instance.stub(:store).with(any_args).and_return(true)
+ end
+ it 'Trueを返す' do
+ r = @p.unpublish
+ r.should be_true
+ end
+ end
+ #例外ケース
+ context '画像ライブラリのロードに失敗したとき' do
+ before do
+ PettanImager.stub(:load).and_return(false)
+ end
+ it 'Falseを返す' do
+ r = @p.unpublish
+ r.should be_false
+ end
+ end
+ context '作成に失敗したとき' do
+ before do
+ Picture.any_instance.stub(:store).with(any_args).and_return(false)
+ end
+ it 'Falseを返す' do
+ r = @p.unpublish
+ r.should be_false
+ end
+ end
+ end
+
describe 'フラグ展開に於いて' do
before do
@p = FactoryGirl.build :picture, :original_picture_id => @op.id, :license_id => @license.id,