• R/O
  • HTTP
  • SSH
  • HTTPS

pettanr: コミット

サーバ側、Railsシステム本体


コミットメタ情報

リビジョン212567177d209b6a8a83c5440cf3e33e7d389084 (tree)
日時2012-12-26 08:05:52
作者yasushiito <yas@pen-...>
コミッターyasushiito

ログメッセージ

t30350#:fix destroy in op, p, user

変更サマリ

差分

--- a/app/controllers/original_pictures_controller.rb
+++ b/app/controllers/original_pictures_controller.rb
@@ -122,13 +122,15 @@ class OriginalPicturesController < ApplicationController
122122
123123 def destroy
124124 @original_picture = OriginalPicture.edit(params[:id], @artist)
125- OriginalPicture.transaction do
126- @original_picture.destroy
127- end
128125
129126 respond_to do |format|
130- format.html { redirect_to original_pictures_url }
131- format.json { head :ok }
127+ if @original_picture.destroy_with_resource_picture
128+ format.html { redirect_to original_pictures_url }
129+ format.json { head :ok }
130+ else
131+ format.html { redirect_to original_picture_path(@original_picture) }
132+ format.json { render json: @original_picture.errors, status: :unprocessable_entity }
133+ end
132134 end
133135 end
134136 end
--- a/app/models/author.rb
+++ b/app/models/author.rb
@@ -1,8 +1,8 @@
11 class Author < ActiveRecord::Base
22 has_one :artist
33 belongs_to :user
4- has_many :comic
5- has_many :panel
4+ has_many :comics
5+ has_many :panels
66
77 validates :name, :presence => true, :length => {:maximum => 30}
88 validates :user_id, :numericality => true, :existence => {:both => false}
--- a/app/models/original_picture.rb
+++ b/app/models/original_picture.rb
@@ -11,8 +11,6 @@ class OriginalPicture < ActiveRecord::Base
1111 validates :artist_id, :presence => true, :numericality => true, :existence => {:both => false}
1212 validates :md5, :presence => true, :length => {:minimum => 32, :maximum => 32}
1313
14- before_destroy :destroy_with_file
15-
1614 def supply_default
1715 end
1816
@@ -137,11 +135,6 @@ class OriginalPicture < ActiveRecord::Base
137135 {:include => {:resource_picture => {}, :pictures => {}}}
138136 end
139137
140- def destroy_with_file
141- PictureIO.original_picture_io.delete self.filename
142- self.resource_picture.destroy
143- end
144-
145138 def store(imager)
146139 unless imager
147140 self.errors.add :base, I18n.t('errors.invalid_image')
@@ -167,6 +160,29 @@ class OriginalPicture < ActiveRecord::Base
167160 PictureIO.original_picture_io.get self.filename, subdir
168161 end
169162
163+ def destroy_with_resource_picture
164+ res = false
165+ OriginalPicture.transaction do
166+ begin
167+ PictureIO.original_picture_io.delete(self.filename) if PictureIO.original_picture_io.exist?(self.filename)
168+ rescue PictureIO::Error
169+ res = false
170+ raise ActiveRecord::Rollback
171+ end
172+ if self.resource_picture
173+ res = self.resource_picture.unpublish
174+ raise ActiveRecord::Rollback unless res
175+ end
176+ self.pictures.each do |picture|
177+ res = picture.unpublish
178+ raise ActiveRecord::Rollback unless res
179+ end
180+ res = self.destroy
181+ raise ActiveRecord::Rollback unless res
182+ end
183+ res
184+ end
185+
170186 def self.export ar
171187 l = LicenseGroup.list
172188 op = OriginalPicture.list ar.id
--- a/app/models/picture.rb
+++ b/app/models/picture.rb
@@ -44,6 +44,7 @@ class Picture < ActiveRecord::Base
4444 end
4545
4646 def showable? au = nil
47+ return false unless self.original_picture
4748 return true if self.own?(au)
4849 self.enable? and self.head?
4950 end
@@ -161,6 +162,12 @@ class Picture < ActiveRecord::Base
161162 PictureIO.picture_io.get self.filename, subdir
162163 end
163164
165+ def unpublish
166+ imager = PettanImager.load(File.open(Rails.root + 'app/assets/images/error.png', 'rb').read)
167+ return false unless imager
168+ self.store imager
169+ end
170+
164171 def credit_template
165172 "#{self.classname.tableize}/attributes/credit"
166173 end
--- a/app/models/resource_picture.rb
+++ b/app/models/resource_picture.rb
@@ -216,15 +216,14 @@ class ResourcePicture < ActiveRecord::Base
216216 res = false
217217 ResourcePicture.transaction do
218218 begin
219- if res = self.destroy
220- PictureIO.resource_picture_io.delete(self.filename)
221- PictureIO.resource_picture_io.delete(self.filename, 'full')
222- res = true
223- end
219+ PictureIO.resource_picture_io.delete(self.filename) if PictureIO.resource_picture_io.exist?(self.filename)
220+ PictureIO.resource_picture_io.delete(self.filename, 'full') if PictureIO.resource_picture_io.exist?(self.filename, 'full')
224221 rescue PictureIO::Error
225222 res = false
226223 raise ActiveRecord::Rollback
227224 end
225+ res = self.destroy
226+ raise ActiveRecord::Rollback unless res
228227 end
229228 res
230229 end
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -28,8 +28,14 @@ class User < ActiveRecord::Base
2828 self.author.panels.each do |panel|
2929 raise ActiveRecord::Rollback unless panel.destroy_with_elements
3030 end
31+ if self.author.artist
32+ self.author.artist.original_pictures.each do |original_picture|
33+ raise ActiveRecord::Rollback unless original_picture.destroy_with_resource_picture
34+ end
35+ raise ActiveRecord::Rollback unless self.author.artist.destroy
36+ end
3137 raise ActiveRecord::Rollback unless self.author.destroy
32- raise ActiveRecord::Rollback unless self.destroy
38+ raise ActiveRecord::Rollback unless super
3339 res = true
3440 end
3541 res
--- a/app/views/pictures/show.html.erb
+++ b/app/views/pictures/show.html.erb
@@ -1,26 +1,32 @@
11 <h1><%= t('.title') %></h1>
22 <div>
3- <% if @picture.enable? %>
4- <% if @picture.head? %>
3+ <% if @picture.original_picture %>
4+ <% if @picture.enable? %>
5+ <% if @picture.head? %>
6+ <p>
7+ <%= t 'pictures.show.announce.head' -%>
8+ <%= link_to tag(:img, @picture.tmb_opt_img_tag), resource_picture_path(@picture.resource_picture) %>
9+ </p>
10+ <% else %>
11+ <p>
12+ <%= t 'pictures.show.announce.tail' -%>
13+ <%= link_to tag(:img, @picture.head.tmb_opt_img_tag), resource_picture_path(@picture.head.resource_picture) %>
14+ </p>
15+ <% end %>
16+ <% else %>
517 <p>
6- <%= t 'pictures.show.announce.head' -%>
7- <%= link_to tag(:img, @picture.tmb_opt_img_tag), resource_picture_path(@picture.resource_picture) %>
18+ <%= t 'pictures.show.announce.disable' -%>
819 </p>
9- <% else %>
20+ <% end %>
21+ <% if @picture.own? @artist %>
1022 <p>
11- <%= t 'pictures.show.announce.tail' -%>
12- <%= link_to tag(:img, @picture.head.tmb_opt_img_tag), resource_picture_path(@picture.head.resource_picture) %>
23+ <%= t 'pictures.show.announce.owner' -%>
24+ <%= link_to tag(:img, @picture.original_picture.tmb_opt_img_tag), original_picture_path(@picture.original_picture) %>
1325 </p>
1426 <% end %>
1527 <% else %>
1628 <p>
17- <%= t 'pictures.show.announce.disable' -%>
18- </p>
19- <% end %>
20- <% if @picture.own? @artist %>
21- <p>
22- <%= t 'pictures.show.announce.owner' -%>
23- <%= link_to tag(:img, @picture.original_picture.tmb_opt_img_tag), original_picture_path(@picture.original_picture) %>
29+ <%= t 'pictures.show.announce.destroyed' -%>
2430 </p>
2531 <% end %>
2632 </div>
--- a/config/locales/pettanr.ja.yml
+++ b/config/locales/pettanr.ja.yml
@@ -584,6 +584,7 @@ ja:
584584 head: 素材として利用できます。
585585 tail: この画像は既に改訂されています。素材として利用するなら、こちら(最新版)が利用できます。
586586 owner: あなたの画像です。原画を管理するなら、こちらを利用してください。
587+ destroyed: この素材は削除されています。素材として利用できません。
587588 md5:
588589 title: 実素材MD5検索一覧
589590 credit:
--- a/spec/controllers/original_pictures_controller_spec.rb
+++ b/spec/controllers/original_pictures_controller_spec.rb
@@ -909,4 +909,99 @@ describe OriginalPicturesController do
909909 end
910910 end
911911
912+ describe '削除に於いて' do
913+ before do
914+ @op = FactoryGirl.create :original_picture, :artist_id => @artist.id
915+ sign_in @user
916+ end
917+ context '事前チェックしておく' do
918+ before do
919+ OriginalPicture.stub(:edit).with(any_args()).and_return @op
920+ OriginalPicture.any_instance.stub(:destroy_with_resource_picture).with(any_args()).and_return(true)
921+ end
922+ it '原画モデルに編集取得を問い合わせている' do
923+ OriginalPicture.should_receive(:edit).exactly(1)
924+ delete :destroy, :id => @op.id
925+ end
926+ it 'モデルに削除を依頼する' do
927+ OriginalPicture.any_instance.should_receive(:destroy_with_resource_picture).exactly(1)
928+ delete :destroy, :id => @op.id
929+ end
930+ it '@original_pictureにアレを取得している' do
931+ delete :destroy, :id => @op.id
932+ assigns(:original_picture).id.should eq(@op.id)
933+ end
934+ end
935+ context 'つつがなく終わるとき' do
936+ before do
937+ OriginalPicture.any_instance.stub(:destroy_with_resource_picture).with(any_args()).and_return(true)
938+ end
939+ context 'html形式' do
940+ it 'ステータスコード302 Foundを返す' do
941+ delete :destroy, :id => @op.id
942+ response.status.should eq 302
943+ end
944+ it '原画の一覧ページへ遷移する' do
945+ delete :destroy, :id => @op.id
946+ response.should redirect_to(original_pictures_path)
947+ end
948+ end
949+ context 'json形式' do
950+ it 'ステータスコード200 OKを返す' do
951+ delete :destroy, :id => @op.id, :format => :json
952+ response.should be_success
953+ end
954+ it 'ページ本体は特に返さない' do
955+ delete :destroy, :id => @op.id, :format => :json
956+ response.body.should match /./
957+ end
958+ end
959+ end
960+ context '作家権限がないとき' do
961+ before do
962+ sign_out @user
963+ end
964+ it 'ステータスコード302 Foundを返す' do
965+ delete :destroy, :id => @op.id
966+ response.status.should eq 302
967+ end
968+ context 'html形式' do
969+ it 'サインインページへ遷移する' do
970+ delete :destroy, :id => @op.id
971+ response.body.should redirect_to '/users/sign_in'
972+ end
973+ end
974+ context 'json形式' do
975+ it '応答メッセージにUnauthorizedを返す' do
976+ delete :destroy, :id => @op.id, :format => :json
977+ response.message.should match(/Unauthorized/)
978+ end
979+ end
980+ end
981+ context '削除に失敗したとき' do
982+ before do
983+ OriginalPicture.any_instance.stub(:destroy_with_resource_picture).and_return(false)
984+ end
985+ context 'html形式' do
986+ it 'ステータスコード302 Foundを返す' do
987+ delete :destroy, :id => @op.id
988+ response.status.should eq 302
989+ end
990+ it 'その原画の詳細ページへ遷移する' do
991+ delete :destroy, :id => @op.id
992+ response.should redirect_to(original_picture_path(@op))
993+ end
994+ end
995+ context 'json形式' do
996+ it 'ステータスコード422 unprocessable_entity を返す' do
997+ delete :destroy, :id => @op.id, :format => :json
998+ response.status.should eq 422
999+ end
1000+ it '応答メッセージUnprocessable Entityを返す' do
1001+ delete :destroy, :id => @op.id, :format => :json
1002+ response.message.should match(/Unprocessable/)
1003+ end
1004+ end
1005+ end
1006+ end
9121007 end
--- a/spec/models/original_picture_spec.rb
+++ b/spec/models/original_picture_spec.rb
@@ -783,6 +783,140 @@ describe OriginalPicture do
783783 end
784784 end
785785
786+ describe '削除に於いて' do
787+ before do
788+ @op = FactoryGirl.create :original_picture, :artist_id => @artist.id
789+ end
790+ context '事前チェックしておく' do
791+ before do
792+ OriginalPicture.any_instance.stub(:destroy).and_return(true)
793+ ResourcePicture.any_instance.stub(:unpublish).and_return(true)
794+ Picture.any_instance.stub(:unpublish).with(any_args).and_return(true)
795+ PictureIO.original_picture_io.stub(:delete).with(any_args).and_return(true)
796+ end
797+ it '原画モデルに削除を依頼している' do
798+ OriginalPicture.any_instance.should_receive(:destroy).exactly(1)
799+ r = @op.destroy_with_resource_picture
800+ end
801+ it '保管庫に原画の画像データ削除を依頼している' do
802+ PictureIO.original_picture_io.should_receive(:delete).with(@op.filename).exactly(1)
803+ r = @op.destroy_with_resource_picture
804+ end
805+ context '自身にリンクされた素材があるとき' do
806+ it '素材モデルに削除を依頼している' do
807+ @p = FactoryGirl.create :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id, :revision => 0
808+ @rp = FactoryGirl.create :resource_picture, :artist_id => @artist.id, :license_id => @license.id, :original_picture_id => @op.id, :picture_id => @p.id
809+ ResourcePicture.any_instance.should_receive(:unpublish).exactly(1)
810+ r = @op.destroy_with_resource_picture
811+ end
812+ end
813+ context '自身にリンクされた素材がないとき' do
814+ it '素材モデルに削除を依頼しない' do
815+ ResourcePicture.any_instance.should_not_receive(:unpublish)
816+ r = @op.destroy_with_resource_picture
817+ end
818+ end
819+ context '自身にリンクされた実素材があるとき' do
820+ it 'すべての実素材に墨塗を依頼している' do
821+ @p = FactoryGirl.create :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id, :revision => 0
822+ Picture.any_instance.should_receive(:unpublish).with(any_args).exactly(1)
823+ r = @op.destroy_with_resource_picture
824+ end
825+ end
826+ context '自身にリンクされた実素材がないとき' do
827+ it '実素材に墨塗を依頼しない' do
828+ Picture.any_instance.should_not_receive(:unpublish)
829+ r = @op.destroy_with_resource_picture
830+ end
831+ end
832+ end
833+ context 'つつがなく終わるとき' do
834+ before do
835+ PictureIO.original_picture_io.stub(:delete).with(any_args).and_return(true)
836+ @p = FactoryGirl.create :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id, :revision => 0
837+ @rp = FactoryGirl.create :resource_picture, :artist_id => @artist.id, :license_id => @license.id, :original_picture_id => @op.id, :picture_id => @p.id
838+ end
839+ it '自身を削除する' do
840+ lambda {
841+ r = @op.destroy_with_resource_picture
842+ }.should change(OriginalPicture, :count).by(-1)
843+ lambda {
844+ r = OriginalPicture.find @op.id
845+ }.should raise_error
846+ end
847+ it 'Trueを返す' do
848+ r = @op.destroy_with_resource_picture
849+ r.should be_true
850+ end
851+ end
852+ context '自身の削除に失敗したとき' do
853+ before do
854+ OriginalPicture.any_instance.stub(:destroy).with(any_args).and_return(false)
855+ end
856+ it 'Falseを返す' do
857+ r = @op.destroy_with_resource_picture
858+ r.should be_false
859+ end
860+ it 'ロールバックしている' do
861+ lambda {
862+ r = @op.destroy_with_resource_picture
863+ }.should_not change(OriginalPicture, :count)
864+ end
865+ end
866+ context '画像の削除に失敗したとき' do
867+ before do
868+ PictureIO.original_picture_io.stub(:delete).with(@op.filename).and_raise(PictureIO::Error)
869+ end
870+ it 'Falseを返す' do
871+ r = @op.destroy_with_resource_picture
872+ r.should be_false
873+ end
874+ it 'ロールバックしている' do
875+ lambda {
876+ r = @op.destroy_with_resource_picture
877+ }.should_not change(OriginalPicture, :count)
878+ end
879+ end
880+ context '素材の削除に失敗とき' do
881+ before do
882+ @p = FactoryGirl.create :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id, :revision => 0
883+ @rp = FactoryGirl.create :resource_picture, :artist_id => @artist.id, :license_id => @license.id, :original_picture_id => @op.id, :picture_id => @p.id
884+ ResourcePicture.any_instance.stub(:unpublish).with(any_args).and_return(false)
885+ end
886+ it 'Falseを返す' do
887+ r = @op.destroy_with_resource_picture
888+ r.should be_false
889+ end
890+ it 'ロールバックしている' do
891+ lambda {
892+ r = @op.destroy_with_resource_picture
893+ }.should_not change(OriginalPicture, :count)
894+ lambda {
895+ r = @op.destroy_with_resource_picture
896+ }.should_not change(ResourcePicture, :count)
897+ end
898+ end
899+ context '実素材の墨塗に失敗とき' do
900+ before do
901+ @p = FactoryGirl.create :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id, :revision => 0
902+ @rp = FactoryGirl.create :resource_picture, :artist_id => @artist.id, :license_id => @license.id, :original_picture_id => @op.id, :picture_id => @p.id
903+ Picture.any_instance.stub(:unpublish).with(any_args).and_return(false)
904+ end
905+ it 'Falseを返す' do
906+ r = @op.destroy_with_resource_picture
907+ r.should be_false
908+ end
909+ it 'ロールバックしている' do
910+ lambda {
911+ r = @op.destroy_with_resource_picture
912+ }.should_not change(OriginalPicture, :count)
913+ lambda {
914+ r = @op.destroy_with_resource_picture
915+ }.should_not change(ResourcePicture, :count)
916+ end
917+ end
918+ end
919+
786920 =begin
787921 describe 'エクスポートに於いて' do
788922 before do
--- a/spec/models/picture_spec.rb
+++ b/spec/models/picture_spec.rb
@@ -286,6 +286,15 @@ describe Picture do
286286 before do
287287 @p = FactoryGirl.build :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id
288288 end
289+ context '自身に原画がリンクしていないとき' do
290+ before do
291+ Picture.any_instance.stub(:original_picture).with(any_args).and_return(nil)
292+ end
293+ it 'Falseを返す' do
294+ r = @p.showable?(@author)
295+ r.should be_false
296+ end
297+ end
289298 it '自作の実素材ならyes' do
290299 Picture.any_instance.stub(:own?).with(any_args).and_return(true)
291300 @p.showable?(@artist).should == true
@@ -852,6 +861,55 @@ describe Picture do
852861
853862 end
854863
864+ describe '墨塗に於いて' do
865+ before do
866+ @p = FactoryGirl.create :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id, :ext => 'png'
867+ end
868+ context '事前チェック' do
869+ before do
870+ @imager = ImagerTest.load "abc\ndef\nghi"
871+ Picture.any_instance.stub(:store).with(any_args).and_return(true)
872+ PettanImager.stub(:load).with(any_args).and_return(@imager)
873+ end
874+ it '画像ライブラリにロードを依頼している' do
875+ PettanImager.should_receive(:load).with(any_args).exactly(1)
876+ r = @p.unpublish
877+ end
878+ it '自身に作成を依頼している' do
879+ Picture.any_instance.should_receive(:store).with(any_args).exactly(1)
880+ r = @p.unpublish
881+ end
882+ end
883+ context 'つつがなく終わるとき' do
884+ before do
885+ Picture.any_instance.stub(:store).with(any_args).and_return(true)
886+ end
887+ it 'Trueを返す' do
888+ r = @p.unpublish
889+ r.should be_true
890+ end
891+ end
892+ #例外ケース
893+ context '画像ライブラリのロードに失敗したとき' do
894+ before do
895+ PettanImager.stub(:load).and_return(false)
896+ end
897+ it 'Falseを返す' do
898+ r = @p.unpublish
899+ r.should be_false
900+ end
901+ end
902+ context '作成に失敗したとき' do
903+ before do
904+ Picture.any_instance.stub(:store).with(any_args).and_return(false)
905+ end
906+ it 'Falseを返す' do
907+ r = @p.unpublish
908+ r.should be_false
909+ end
910+ end
911+ end
912+
855913 describe 'フラグ展開に於いて' do
856914 before do
857915 @p = FactoryGirl.build :picture, :original_picture_id => @op.id, :license_id => @license.id,
旧リポジトリブラウザで表示