From aec34f8b39f39ec0794d39c878659487909f0136 Mon Sep 17 00:00:00 2001 From: yasushiito Date: Sat, 2 Jun 2012 09:49:10 +0900 Subject: [PATCH] speech balloon template changed --- .../speech_balloon_templates_controller.rb | 22 +- app/models/original_picture.rb | 4 - app/models/speech_balloon_template.rb | 87 ++++- app/models/system_picture.rb | 46 ++- app/views/speech_balloon_templates/browse.html.erb | 27 +- app/views/speech_balloon_templates/list.html.erb | 24 +- app/views/speech_balloon_templates/show.html.erb | 29 +- app/views/system/browse.html.erb | 17 +- config/application.rb | 7 +- .../20120102071851_create_system_pictures.rb | 1 + ...120424100555_create_speech_balloon_templates.rb | 7 + db/schema.rb | 17 +- spec/factories.rb | 10 +- spec/json/invalid_speech_balloon_templates.json | 59 +++ spec/json/speech_balloon_template.json | 21 ++ spec/json/speech_balloon_templates.json | 70 ++++ spec/models/speech_balloon_template_spec.rb | 404 ++++++++++++++++++++- spec/models/system_picture_spec.rb | 283 ++++++++++++++- 18 files changed, 1039 insertions(+), 96 deletions(-) create mode 100644 spec/json/invalid_speech_balloon_templates.json create mode 100644 spec/json/speech_balloon_template.json create mode 100644 spec/json/speech_balloon_templates.json diff --git a/app/controllers/speech_balloon_templates_controller.rb b/app/controllers/speech_balloon_templates_controller.rb index d17ff326..cbb2d5b5 100644 --- a/app/controllers/speech_balloon_templates_controller.rb +++ b/app/controllers/speech_balloon_templates_controller.rb @@ -33,7 +33,7 @@ class SpeechBalloonTemplatesController < ApplicationController # GET /speech_balloon_templates # GET /speech_balloon_templates.json def index - @speech_balloon_templates = SpeechBalloon.all + @speech_balloon_templates = SpeechBalloonTemplate.all respond_to do |format| format.html # index.html.erb @@ -44,25 +44,21 @@ class SpeechBalloonTemplatesController < ApplicationController # GET /speech_balloon_templates/1 # GET /speech_balloon_templates/1.json def show - @speech_balloon_template = SpeechBalloon.find(params[:id], include: {:balloon_templates => :speech_templates}) + @speech_balloon_template = SpeechBalloonTemplate.find(params[:id]) respond_to do |format| format.html # show.html.erb format.json { - render :json => @speech_balloon_template.to_json(include: { - :balloon_templates => {:include => :speech_templates} - }) + render :json => @speech_balloon_template.to_json() } format.jsonp { - render :json => "callback(" + @speech_balloon_template.to_json(include: { - :balloon_templates => {:include => :speech_templates} - }) + ")" + render :json => "callback(" + @speech_balloon_template.to_json() + ")" } end end def list - @speech_balloon_templates = SpeechBalloon.all + @speech_balloon_templates = SpeechBalloonTemplate.all respond_to do |format| format.html { render layout: 'system' } @@ -71,7 +67,7 @@ class SpeechBalloonTemplatesController < ApplicationController end def browse - @speech_balloon_template = SpeechBalloon.find(params[:id]) + @speech_balloon_template = SpeechBalloonTemplate.find(params[:id]) respond_to do |format| format.html { render layout: 'system' } @@ -82,7 +78,7 @@ class SpeechBalloonTemplatesController < ApplicationController # POST /speech_balloon_templates # POST /speech_balloon_templates.json def create - @speech_balloon_template = SpeechBalloon.new(params[:speech_balloon_template]) + @speech_balloon_template = SpeechBalloonTemplate.new(params[:speech_balloon_template]) if em = validate_param(params[:speech_balloon_template]) respond_to do |format| format.json { render json: em, status: :unprocessable_entity } @@ -103,11 +99,11 @@ class SpeechBalloonTemplatesController < ApplicationController # DELETE /speech_balloon_templates/1 # DELETE /speech_balloon_templates/1.json def destroy - @speech_balloon_template = SpeechBalloon.find(params[:id]) + @speech_balloon_template = SpeechBalloonTemplate.find(params[:id]) @speech_balloon_template.destroy respond_to do |format| - format.html { redirect_to speech_balloon_templates_url } + format.html { redirect_to :action => :list } format.json { head :ok } end end diff --git a/app/models/original_picture.rb b/app/models/original_picture.rb index 91a67918..722e1104 100644 --- a/app/models/original_picture.rb +++ b/app/models/original_picture.rb @@ -12,10 +12,6 @@ class OriginalPicture < ActiveRecord::Base before_destroy :destroy_with_file - def validate - errors.add(:filesize, 'size over(1MB)') if self.filesize > 1000000 - end - def supply_default art self.license_id = art.default_license_id if self.license_id.blank? end diff --git a/app/models/speech_balloon_template.rb b/app/models/speech_balloon_template.rb index de6d053c..b5f12e0c 100644 --- a/app/models/speech_balloon_template.rb +++ b/app/models/speech_balloon_template.rb @@ -1,12 +1,89 @@ class SpeechBalloonTemplate < ActiveRecord::Base - has_many :balloon_templates, :dependent => :destroy - has_many :speech_templates, :dependent => :destroy - accepts_nested_attributes_for :balloon_templates - accepts_nested_attributes_for :speech_templates + has_many :speech_balloons + + validates :name, :presence => true, :uniqueness => true, :length => {:maximum => 50} + validates :classname, :presence => true, :length => {:maximum => 50} + validates :caption, :presence => true, :length => {:maximum => 30} + validates :t, :presence => true, :numericality => {:greater_than_or_equal_to => 0} + validates :settings, :presence => true + before_create :supply_t def supply_t - self.t = SpeechBalloon.maximum(:t).to_i + 1 + m = SpeechBalloonTemplate.maximum(:t) + t = m.blank? ? -1 : m.to_i + self.t = t + 1 + end + + def pic_rehash hash + res = true + hash["templates"].each do |n, v| + d = (v["balloon"] || {})["system_picture"] + next nil if d.blank? + sp = SystemPicture.store Base64.decode64(d.to_s) + unless sp + res = false + break + end + v["balloon"]["system_picture_id"] = sp.id + v["balloon"].delete "system_picture" + end + res + end + + def store hash + res = nil + SpeechBalloonTemplate.transaction do + res = pic_rehash hash + if res + data = {:classname => hash["classname"], :caption => hash["caption"], :settings => hash.to_s} + self.attributes = data + res = self.save + end + raise ActiveRecord::Rollback unless res + end + res + end + + def self.store name, hash + st = SpeechBalloonTemplate.find_by_name name + st = SpeechBalloonTemplate.new(:name => name) unless st + st.store hash + st + end + + def self.parse(data) + res = data + begin + res = JSON.parse(data) if data.is_a?(String) + rescue + return false + end + res + end + + def self.import(data) + d = SpeechBalloonTemplate.parse(data) + return false unless d + res = [] + SpeechBalloonTemplate.transaction do + d.each do |name, hash| + st = SpeechBalloonTemplate.store name, hash + res.push(st) unless st.valid? + end + raise ActiveRecord::Rollback unless res.empty? + end + res + end + + def self.import_file(filename) + t = nil + begin + t = File.open(filename, 'r').read + rescue + return false + end + SpeechBalloonTemplate.import t end end diff --git a/app/models/system_picture.rb b/app/models/system_picture.rb index 9d018318..db857b7b 100644 --- a/app/models/system_picture.rb +++ b/app/models/system_picture.rb @@ -2,11 +2,13 @@ class SystemPicture < ActiveRecord::Base has_many :balloons has_many :balloon_templates - before_destroy :destroy_with_file + validates :ext, :presence => true, :length => {:maximum => 4}, :inclusion => {:in => ['png', 'jpeg', 'gif']} + validates :width, :presence => true, :numericality => true, :natural_number => true + validates :height, :presence => true, :numericality => true, :natural_number => true + validates :filesize, :presence => true, :numericality => {:greater_than => 0, :less_than_or_equal_to => 2000000}, :natural_number => true + validates :md5, :presence => true, :length => {:maximum => 32} - def validate - errors.add(:filesize, 'size over(1MB)') if self.filesize > 1000000 - end + before_destroy :destroy_with_file def destroy_with_file PictureIO.system_picture_io.delete self.filename @@ -28,10 +30,38 @@ class SystemPicture < ActiveRecord::Base '/system_pictures/' + filename end - def store(rimg) - bindata = rimg.to_blob - PictureIO.system_picture_io.put bindata, self.filename - true + def data_to_mgk picture_data + begin + mgk = Magick::Image.from_blob(picture_data).shift + rescue + self.errors.add :base, 'magick failed' + return false + end + mgk + end + + def store(picture_data) + mgk = data_to_mgk picture_data + return false unless mgk + res = false + self.attributes = {:ext => mgk.format.downcase, :width => mgk.columns, :height => mgk.rows, + :filesize => mgk.filesize + } + self.md5 = Digest::MD5.hexdigest(picture_data) unless self.md5 + SystemPicture.transaction do + if res = self.save + res = PictureIO.system_picture_io.put(picture_data, self.filename) + end + end + res + end + + def self.store(picture_data) + md5 = Digest::MD5.hexdigest(picture_data) + sp = SystemPicture.find_by_md5(md5) + sp = SystemPicture.new() unless sp + res = sp.store picture_data + res ? sp : nil end def restore(subdir = nil) diff --git a/app/views/speech_balloon_templates/browse.html.erb b/app/views/speech_balloon_templates/browse.html.erb index 154e5926..d4475257 100644 --- a/app/views/speech_balloon_templates/browse.html.erb +++ b/app/views/speech_balloon_templates/browse.html.erb @@ -2,30 +2,27 @@

Name: - <%= h @speech_balloon.name %> + <%= h @speech_balloon_template.name %>

- Tail count: - <%= @speech_balloon.tail_count %> + classname: + <%= h @speech_balloon_template.classname %>

- size count: - <%= @speech_balloon.size_count %> + caption: + <%= h @speech_balloon_template.caption %>

t: - <%= @speech_balloon.t %> + <%= @speech_balloon_template.t %>

-<% @speech_balloon.balloon_templates.each do |balloon_template| -%> -
-

- Tail:<%= balloon_template.tail -%> - Size:<%= balloon_template.size -%> -

- -
-<% end -%> + +

+ settings: + <%= h @speech_balloon_template.settings %> +

+ <%= link_to 'Back', :action => :list %> diff --git a/app/views/speech_balloon_templates/list.html.erb b/app/views/speech_balloon_templates/list.html.erb index d9e74717..175673df 100644 --- a/app/views/speech_balloon_templates/list.html.erb +++ b/app/views/speech_balloon_templates/list.html.erb @@ -1,27 +1,27 @@ -

Listing speech_balloons

+

Listing speech_balloon_templates

- - + + -<% @speech_balloons.each do |speech_balloon| %> +<% @speech_balloon_templates.each do |speech_balloon_template| %> - - - - - - - + + + + + + + <% end %> diff --git a/app/views/speech_balloon_templates/show.html.erb b/app/views/speech_balloon_templates/show.html.erb index 6ef4812b..180db128 100644 --- a/app/views/speech_balloon_templates/show.html.erb +++ b/app/views/speech_balloon_templates/show.html.erb @@ -2,30 +2,27 @@

Name: - <%= h @speech_balloon.name %> + <%= h @speech_balloon_template.name %>

- Tail count: - <%= @speech_balloon.tail_count %> + classname: + <%= h @speech_balloon_template.classname %>

- size count: - <%= @speech_balloon.size_count %> + caption: + <%= h @speech_balloon_template.caption %>

t: - <%= @speech_balloon.t %> + <%= @speech_balloon_template.t %>

-<% @speech_balloon.balloon_templates.each do |balloon_template| -%> -
-

- Tail:<%= balloon_template.tail -%> - Size:<%= balloon_template.size -%> -

- -
-<% end -%> -<%= link_to 'Back', speech_balloons_path %> + +

+ settings: + <%= h @speech_balloon_template.settings %> +

+ +<%= link_to 'Back', speech_balloon_templates_path %> diff --git a/app/views/system/browse.html.erb b/app/views/system/browse.html.erb index e6d7f83c..836bacd3 100644 --- a/app/views/system/browse.html.erb +++ b/app/views/system/browse.html.erb @@ -30,6 +30,11 @@ + + + @@ -43,17 +48,7 @@
id NameTail countsize countclassnamecaption t created_at updated_at
<%= link_to speech_balloon.id, :action => :browse, :id => speech_balloon.id %><%= h speech_balloon.name %><%= speech_balloon.tail_count %><%= speech_balloon.size_count %><%= speech_balloon.t %><%= speech_balloon.created_at %><%= speech_balloon.updated_at %><%= link_to speech_balloon_template.id, :action => :browse, :id => speech_balloon_template.id %><%= h speech_balloon_template.name %><%= h speech_balloon_template.classname %><%= h speech_balloon_template.caption %><%= speech_balloon_template.t %><%= speech_balloon_template.created_at %><%= speech_balloon_template.updated_at %> - <%= link_to 'Destroy', speech_balloon, confirm: 'Are you sure?', method: :delete %> + <%= link_to 'Destroy', speech_balloon_template, confirm: 'Are you sure?', method: :delete %>
+ <%= link_to 'speech_balloons', :controller => 'speech_balloons', :action => :list %> +
<%= link_to 'balloons', :controller => 'balloons', :action => :list %>
- - - - - -
- <%= link_to 'speech_balloons', :controller => 'speech_balloons', :action => :list %> -
- <%= link_to 'balloon_templates', :controller => 'balloon_templates', :action => :list %> -
- <%= link_to 'speech_templates', :controller => 'speech_templates', :action => :list %> + <%= link_to 'speech_balloon_templates', :controller => 'speech_balloon_templates', :action => :list %>
diff --git a/config/application.rb b/config/application.rb index 1f18627a..2b7bcb8f 100644 --- a/config/application.rb +++ b/config/application.rb @@ -7,6 +7,7 @@ require "action_mailer/railtie" require "active_resource/railtie" require "sprockets/railtie" # require "rails/test_unit/railtie" +require 'digest/md5' if defined?(Bundler) # If you precompile assets before deploying to production, use this line @@ -52,11 +53,11 @@ config.assets.initialize_on_precompile = false # Version of your assets, change this if you want to expire all your assets config.assets.version = '1.0' - config.autoload_paths += %W(#{config.root}/lib/validators) + config.autoload_paths += %W(#{config.root}/lib/validators) end end module ActiveRecord class Forbidden < ActiveRecordError - end + end end - + diff --git a/db/migrate/20120102071851_create_system_pictures.rb b/db/migrate/20120102071851_create_system_pictures.rb index f62055d3..ae89408c 100644 --- a/db/migrate/20120102071851_create_system_pictures.rb +++ b/db/migrate/20120102071851_create_system_pictures.rb @@ -5,6 +5,7 @@ class CreateSystemPictures < ActiveRecord::Migration t.integer :width, :null => false t.integer :height, :null => false t.integer :filesize, :null => false + t.string :md5, :null => false, :limit => 32 t.timestamps end diff --git a/db/migrate/20120424100555_create_speech_balloon_templates.rb b/db/migrate/20120424100555_create_speech_balloon_templates.rb index 66e05d6e..15dc922c 100644 --- a/db/migrate/20120424100555_create_speech_balloon_templates.rb +++ b/db/migrate/20120424100555_create_speech_balloon_templates.rb @@ -1,8 +1,15 @@ class CreateSpeechBalloonTemplates < ActiveRecord::Migration def change create_table :speech_balloon_templates do |t| + t.string :name, :null => false, :limit => 50 + t.string :classname, :null => false, :limit => 50 + t.string :caption, :null => false, :limit => 30 + t.integer :t, :null => false, :default => 0 + t.string :settings, :null => false t.timestamps end + add_index :speech_balloon_templates, [:name], :unique => true, :name => 'speech_balloon_templates_name' + add_index :speech_balloon_templates, [:t], :unique => true, :name => 'speech_balloon_templates_t' end end diff --git a/db/schema.rb b/db/schema.rb index 7d8a12ff..2d863a75 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -216,10 +216,18 @@ ActiveRecord::Schema.define(:version => 20120424100555) do end create_table "speech_balloon_templates", :force => true do |t| + t.string "name", :limit => 50, :null => false + t.string "classname", :limit => 50, :null => false + t.string "caption", :limit => 30, :null => false + t.integer "t", :default => 0, :null => false + t.string "settings", :null => false t.datetime "created_at" t.datetime "updated_at" end + add_index "speech_balloon_templates", ["name"], :name => "speech_balloon_templates_name", :unique => true + add_index "speech_balloon_templates", ["t"], :name => "speech_balloon_templates_t", :unique => true + create_table "speech_balloons", :force => true do |t| t.string "name", :null => false t.integer "tail_count", :default => 1, :null => false @@ -261,10 +269,11 @@ ActiveRecord::Schema.define(:version => 20120424100555) do add_index "speeches", ["balloon_id"], :name => "index_speeches_on_balloon_id" create_table "system_pictures", :force => true do |t| - t.string "ext", :null => false - t.integer "width", :null => false - t.integer "height", :null => false - t.integer "filesize", :null => false + t.string "ext", :null => false + t.integer "width", :null => false + t.integer "height", :null => false + t.integer "filesize", :null => false + t.string "md5", :limit => 32, :null => false t.datetime "created_at" t.datetime "updated_at" end diff --git a/spec/factories.rb b/spec/factories.rb index 6cb4f0a7..0ce9e0e7 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -140,9 +140,17 @@ Factory.define :system_picture, :class => SystemPicture do |sp| sp.ext 'png' sp.width 222 sp.height 111 - sp.fileseze 100000 + sp.filesize 100000 + sp.md5 '098f6bcd4621d373cade4e832627b4f6' end +Factory.define :speech_balloon_template, :class => SpeechBalloonTemplate do |sbt| + sbt.name 'Plain@pettanr.com' + sbt.classname 'Plain' + sbt.caption 'normal fuki' + sbt.t 0 + sbt.settings '{}' +end Factory.define :balloon, :class => Balloon do |balloon| balloon.panel_id 1 balloon.balloon_template_id 1 diff --git a/spec/json/invalid_speech_balloon_templates.json b/spec/json/invalid_speech_balloon_templates.json new file mode 100644 index 00000000..9ec2d2c7 --- /dev/null +++ b/spec/json/invalid_speech_balloon_templates.json @@ -0,0 +1,59 @@ +{ + "square@pettan.com": { + "classname": "Square", + "caption": "’·•ûŒ`", + "default_width": 150, + "default_height": 150, + "templates": { + "all": { + "balloon": { + "system_picture": "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" + }, + "speech": { + "x_rate": 1, + "y_rate": 1, + "width_rate": 98, + "height_rate": 98 + } + } + } + }, + "square@pettan.com": { + "classname": "Square", + "caption": "’·•ûŒ`", + "default_width": 150, + "default_height": 150, + "templates": { + "all": { + "balloon": { + "system_picture": "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" + }, + "speech": { + "x_rate": 1, + "y_rate": 1, + "width_rate": 98, + "height_rate": 98 + } + } + } + }, + "square@pettan.com": { + "classname": "Square", + "caption": "’·•ûŒ`", + "default_width": 150, + "default_height": 150, + "templates": { + "all": { + "balloon": { + "system_picture": "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" + }, + "speech": { + "x_rate": 1, + "y_rate": 1, + "width_rate": 98, + "height_rate": 98 + } + } + } + } +} diff --git a/spec/json/speech_balloon_template.json b/spec/json/speech_balloon_template.json new file mode 100644 index 00000000..abe92ecc --- /dev/null +++ b/spec/json/speech_balloon_template.json @@ -0,0 +1,21 @@ +{ + "square@pettan.com": { + "classname": "Square", + "caption": "長方形", + "default_width": 150, + "default_height": 150, + "templates": { + "all": { + "balloon": { + "system_picture": "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" + }, + "speech": { + "x_rate": 1, + "y_rate": 1, + "width_rate": 98, + "height_rate": 98 + } + } + } + } +} diff --git a/spec/json/speech_balloon_templates.json b/spec/json/speech_balloon_templates.json new file mode 100644 index 00000000..dadd1e9d --- /dev/null +++ b/spec/json/speech_balloon_templates.json @@ -0,0 +1,70 @@ +{ + "square@pettan.com": { + "classname": "Square", + "caption": "’·•ûŒ`", + "default_width": 150, + "default_height": 150, + "templates": { + "all": { + "balloon": { + "system_picture": "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" + }, + "speech": { + "x_rate": 1, + "y_rate": 1, + "width_rate": 98, + "height_rate": 98 + } + } + } + }, + "square with size@pettan.com": { + "classname": "SquareWithSize", + "caption": "’·•ûŒ`‰ü", + "default_width": 150, + "default_height": 100, + "size_count": 3, + "width_offset": 0, + "height_offset": 0, + "width_step": 100, + "height_step": 100, + "templates": { + "small": { + "balloon": { + "size": 0, + "system_picture": "R0lGODlhZABkAPcAAAAAAAAAMwAAZgAAmQAAzAAA/wArAAArMwArZgArmQArzAAr/wBVAABVMwBVZgBVmQBVzABV/wCAAACAMwCAZgCAmQCAzACA/wCqAACqMwCqZgCqmQCqzACq/wDVAADVMwDVZgDVmQDVzADV/wD/AAD/MwD/ZgD/mQD/zAD//zMAADMAMzMAZjMAmTMAzDMA/zMrADMrMzMrZjMrmTMrzDMr/zNVADNVMzNVZjNVmTNVzDNV/zOAADOAMzOAZjOAmTOAzDOA/zOqADOqMzOqZjOqmTOqzDOq/zPVADPVMzPVZjPVmTPVzDPV/zP/ADP/MzP/ZjP/mTP/zDP//2YAAGYAM2YAZmYAmWYAzGYA/2YrAGYrM2YrZmYrmWYrzGYr/2ZVAGZVM2ZVZmZVmWZVzGZV/2aAAGaAM2aAZmaAmWaAzGaA/2aqAGaqM2aqZmaqmWaqzGaq/2bVAGbVM2bVZmbVmWbVzGbV/2b/AGb/M2b/Zmb/mWb/zGb//5kAAJkAM5kAZpkAmZkAzJkA/5krAJkrM5krZpkrmZkrzJkr/5lVAJlVM5lVZplVmZlVzJlV/5mAAJmAM5mAZpmAmZmAzJmA/5mqAJmqM5mqZpmqmZmqzJmq/5nVAJnVM5nVZpnVmZnVzJnV/5n/AJn/M5n/Zpn/mZn/zJn//8wAAMwAM8wAZswAmcwAzMwA/8wrAMwrM8wrZswrmcwrzMwr/8xVAMxVM8xVZsxVmcxVzMxV/8yAAMyAM8yAZsyAmcyAzMyA/8yqAMyqM8yqZsyqmcyqzMyq/8zVAMzVM8zVZszVmczVzMzV/8z/AMz/M8z/Zsz/mcz/zMz///8AAP8AM/8AZv8Amf8AzP8A//8rAP8rM/8rZv8rmf8rzP8r//9VAP9VM/9VZv9Vmf9VzP9V//+AAP+AM/+AZv+Amf+AzP+A//+qAP+qM/+qZv+qmf+qzP+q///VAP/VM//VZv/Vmf/VzP/V////AP//M///Zv//mf//zP///wAAAAAAAAAAAAAAACH5BAEAAPwALAAAAABkAGQAAAj/AAEIHEiwoMGDCBMqXMiwocOHECNKnEixosWLGAfu28ixo8ePIEOKHEmypMmOBU+qXMmypcqULmPKnFkSJs2bOGXazMmzJ8mdPoMK3Qd0qFGcRY8qjZl0qdOXBJ9Kbdl0qtWPVa9qJRp1q1ePWb9KDSvWKdmySs+iNap2rdC2bn3CjctzLl2kXe+OzavXLN++af8CZit48NvChuUiTlx3MWO8Gh8PtSv5JOXKNR1jZqp5M9XOnldeDg1yNGmwoE9njqx6punWXFnDdvm6dW3Vt0/nJr07dG/PvzcHxzy8cnHJxx8nZ7w8cXPDzwdHBzy9b3W91+9mp7s9bne339eGX0c7vmx5see/pve6fmt7re+vxrc6f2r9vbJns7z/lL/f/PpBBWCAJvm3lIGBDUjgT6ktyBGCR0FImIIOhiThZA1WeOFhFFaIVYYObhiUiIp16CFKGaWo4oostuhiQQEBADs=" + }, + "speech": { + "x_rate": 3, + "y_rate": 3, + "width_rate": 94, + "height_rate": 94 + } + }, + "middle": { + "balloon": { + "size": 1, + "system_picture": "R0lGODlhyADIAHAAACH5BAEAAPwALAAAAADIAMgAhwAAAAAAMwAAZgAAmQAAzAAA/wArAAArMwArZgArmQArzAAr/wBVAABVMwBVZgBVmQBVzABV/wCAAACAMwCAZgCAmQCAzACA/wCqAACqMwCqZgCqmQCqzACq/wDVAADVMwDVZgDVmQDVzADV/wD/AAD/MwD/ZgD/mQD/zAD//zMAADMAMzMAZjMAmTMAzDMA/zMrADMrMzMrZjMrmTMrzDMr/zNVADNVMzNVZjNVmTNVzDNV/zOAADOAMzOAZjOAmTOAzDOA/zOqADOqMzOqZjOqmTOqzDOq/zPVADPVMzPVZjPVmTPVzDPV/zP/ADP/MzP/ZjP/mTP/zDP//2YAAGYAM2YAZmYAmWYAzGYA/2YrAGYrM2YrZmYrmWYrzGYr/2ZVAGZVM2ZVZmZVmWZVzGZV/2aAAGaAM2aAZmaAmWaAzGaA/2aqAGaqM2aqZmaqmWaqzGaq/2bVAGbVM2bVZmbVmWbVzGbV/2b/AGb/M2b/Zmb/mWb/zGb//5kAAJkAM5kAZpkAmZkAzJkA/5krAJkrM5krZpkrmZkrzJkr/5lVAJlVM5lVZplVmZlVzJlV/5mAAJmAM5mAZpmAmZmAzJmA/5mqAJmqM5mqZpmqmZmqzJmq/5nVAJnVM5nVZpnVmZnVzJnV/5n/AJn/M5n/Zpn/mZn/zJn//8wAAMwAM8wAZswAmcwAzMwA/8wrAMwrM8wrZswrmcwrzMwr/8xVAMxVM8xVZsxVmcxVzMxV/8yAAMyAM8yAZsyAmcyAzMyA/8yqAMyqM8yqZsyqmcyqzMyq/8zVAMzVM8zVZszVmczVzMzV/8z/AMz/M8z/Zsz/mcz/zMz///8AAP8AM/8AZv8Amf8AzP8A//8rAP8rM/8rZv8rmf8rzP8r//9VAP9VM/9VZv9Vmf9VzP9V//+AAP+AM/+AZv+Amf+AzP+A//+qAP+qM/+qZv+qmf+qzP+q///VAP/VM//VZv/Vmf/VzP/V////AP//M///Zv//mf//zP///wAAAAAAAAAAAAAAAAj/APcBGEiwoMGDCBMqXMiwocOHECNKnEgx4T6BFTNq3Mixo8ePCi+CHEmypMmTEEUOvMiypcuXMGPKnEmzps2bOHPq3MmTJUGVAHoKHUq0qNGjSFv+xBg0qdOnUKNKjbl06dSrWLNqnVl15davYMM67dpUrNmzaGuSTcu2Ldu1buPK1Qp3rt27Sevi3ct3p96+gANT9WpVsOHDfw8r5pt4seO5jR9LfkvY6+TLbSNj3rxVM+fPUz2DHj22clnSqKOKTs265+rWsHG+jk2bq+nauHnOzs2bKdDewGnuDk57OHHYxo+zTq4cNfPmo59D/yx9+ubq1i9jzy55O3fH3r8rSQ4v3jD58oHPo++rfv3e9u7vwo8P+Tb91vPvu82vn3LTwv2Bxl+AZw1IoFgGHghWggp2Zl+D1z0IoXYSTthdhRaCh2GG423IoXm5Hn6YXogiskdiie+diKJ8Kq5Y33+WuTgijKfJaCKNNgrGYI5E7cijUD7+qFuLQhZIZJEIHonkgkou6SCOTr74W5RyBUmlcE1eGVqWWqrGZZdPWQnmS2KOqdSXZh5VZpq+tclmWGumGaeZc45ZJ5h3dpmnlnte2SeVf0YZqJODLlkokocWmaiQi/7YKI+P5hipjZPKWKmLl66YKYqbltipiJ9+GCqHo2ZYqoWnTpgqhKs22KqCrx4YK4GoswZYa3+36pfrfbvS12t8v7oX7HrDoldseceKl+x3y3LXbHbPWhftdNNCV21z1yqX7XHbEtdtcN8CF25v4/JWbm7n4pZubesWh+abQ7Ubm7zIvQuva/be61e++uZEL3789nvTv8sFLLBaBh9sG5QKb8lww14+DHGYCU/sEsGpYexcxRb7xHHHbQIIslEak1ZydB93fLKAKVu8MnUtT/wyZzNHKPHIRdWMS5nOFN6Mc7wxQ8zzZENf6PPP+B6N9L5KL+1v0A0X/ZjUGjbt9MBQK0z1Ylt3aPXVCH8N9sJTjj0kjSilrfbabKfEVNtwxy33SfsEBAA7" + }, + "speech": { + "x_rate": 2, + "y_rate": 2, + "width_rate": 96, + "height_rate": 96 + } + }, + "large": { + "balloon": { + "size": 2, + "system_picture": "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" + }, + "speech": { + "x_rate": 1, + "y_rate": 1, + "width_rate": 98, + "height_rate": 98 + } + } + } + } +} diff --git a/spec/models/speech_balloon_template_spec.rb b/spec/models/speech_balloon_template_spec.rb index 14454215..3540bec1 100644 --- a/spec/models/speech_balloon_template_spec.rb +++ b/spec/models/speech_balloon_template_spec.rb @@ -1,5 +1,405 @@ +# -*- encoding: utf-8 -*- require 'spec_helper' - +#フキダシテンプレート describe SpeechBalloonTemplate do - pending "add some examples to (or delete) #{__FILE__}" + before do + #テストデータを用意してね + @f = Rails.root + 'spec/json/speech_balloon_template.json' + @t = File.open(@f, 'r').read + @j = JSON.parse @t + @fs = Rails.root + 'spec/json/speech_balloon_templates.json' + @ts = File.open(@fs, 'r').read + @js = JSON.parse @ts + @fes = Rails.root + 'spec/json/invalid_speech_balloon_templates.json' + @tes = File.open(@fes, 'r').read + @jes = JSON.parse @tes + + @admin = Factory :admin + @license = Factory :license + end + + describe '検証に於いて' do + before do + end + + it 'オーソドックスなデータなら通る' do + @st = Factory.build :speech_balloon_template + @st.should be_valid + end + + context 'nameを検証するとき' do + before do + @st = Factory.build :speech_balloon_template + end + it 'テストデータの確認' do + @st.name = 'abcdefghi0abcdefghi0abcdefghi0abcdefghi0abcdefghi0' + @st.should be_valid + end + it 'nullなら失敗する' do + @st.name = '' + @st.should_not be_valid + end + it '51文字以上なら失敗する' do + @st.name = 'a'*51 + @st.should_not be_valid + end + end + context 'classnameを検証するとき' do + before do + @st = Factory.build :speech_balloon_template + end + it 'テストデータの確認' do + @st.classname = 'abcdefghi0abcdefghi0abcdefghi0abcdefghi0abcdefghi0' + @st.should be_valid + end + it 'nullなら失敗する' do + @st.classname = '' + @st.should_not be_valid + end + it '51文字以上なら失敗する' do + @st.classname = 'a'*51 + @st.should_not be_valid + end + end + context 'captionを検証するとき' do + before do + @st = Factory.build :speech_balloon_template + end + it 'テストデータの確認' do + @st.caption = 'abcdefghi0abcdefghi0abcdefghi0' + @st.should be_valid + end + it 'nullなら失敗する' do + @st.caption = '' + @st.should_not be_valid + end + it '31文字以上なら失敗する' do + @st.caption = 'a'*31 + @st.should_not be_valid + end + end + context 'tを検証するとき' do + before do + @st = Factory.build :speech_balloon_template + end + it 'テストデータの確認' do + @st.t = 0 + @st.should be_valid + end + it 'nullなら失敗する' do + @st.t = nil + @st.should_not be_valid + end + it '数値でなければ失敗する' do + @st.t = 'a' + @st.should_not be_valid + end + it '負なら失敗する' do + @st.t = -1 + @st.should_not be_valid + end + end + context 'settingsを検証するとき' do + before do + @st = Factory.build :speech_balloon_template + end + it 'テストデータの確認' do + @st.settings = '{}' + @st.should be_valid + end + it 'nullなら失敗する' do + @st.settings = nil + @st.should_not be_valid + end + end + end + + describe 'データ補充に於いて' do + before do + end + + end + + describe 'Json解析に於いて' do + before do + end + context 'テキストを渡されたとき' do + it 'Json解析している' do + JSON.should_receive(:parse).with(@t).exactly(1) + r = SpeechBalloonTemplate.parse @t + end + it 'Hashで返す' do + r = SpeechBalloonTemplate.parse @t + r.is_a?(Hash).should be_true + end + end + context 'パース失敗したとき' do + it 'Falseを返す' do + JSON.should_receive(:parse).with(any_args).and_raise('StandardError') + r = SpeechBalloonTemplate.parse @t + r.should be_false + end + end + end + + describe '対象フキダシテンプレートの取得に於いて' do + before do + @st = Factory :speech_balloon_template + end + context 'nameが一致するフキダシテンプレートがないとき' do + it '新規フキダシテンプレートを準備して返す' do + r = SpeechBalloonTemplate.update_speech_balloon_template 'newtemplate', {:classname => 'New'} + r.should be_a_new SpeechBalloonTemplate + r[:classname].should eq 'New' + end + end + context 'nameが一致するフキダシテンプレートがあるとき' do + it '該当フキダシテンプレートを値設定して返す' do + r = SpeechBalloonTemplate.update_speech_balloon_template @st.name, {:classname => 'Update'} + r.is_a?(SpeechBalloonTemplate).should be_true + r.should_not be_a_new SpeechBalloonTemplate + r[:classname].should eq 'Update' + end + end + end + + describe 'フキダシテンプレート保存に於いて' do + before do + @st = Factory.build :speech_balloon_template + end + context 'つつがなく終わるとき' do + it '保存を問い合わせている' do + SpeechBalloonTemplate.any_instance.should_receive(:save).exactly(1) + @st.store + end + it 'フキダシテンプレートが作成されている' do + lambda { + @st.store + }.should change SpeechBalloonTemplate, :count + end + end + end + + describe 'フキダシテンプレート更新に於いて' do + before do + @st = Factory :speech_balloon_template + @attr = {:name => @st.name, :classname => 'Update', :t => 0, :caption => 'yp', :settings => '{}'} + @newattr = {:name => @st.name, :classname => 'New', :t => 1, :caption => 'nw', :settings => '{}'} + end + context 'つつがなく終わるとき' do + it '対象フキダシテンプレートを問い合わせている' do + SpeechBalloonTemplate.stub(:update_speech_balloon_template).with(any_args).and_return(SpeechBalloonTemplate.new(@attr)) + SpeechBalloonTemplate.should_receive(:update_speech_balloon_template).exactly(1) + SpeechBalloonTemplate.store @st.name, @attr + end + context '新規のとき' do + it 'フキダシテンプレートを保存しようとしている' do + SpeechBalloonTemplate.any_instance.should_receive(:save).exactly(1) + SpeechBalloonTemplate.store 'newtemplate', @newattr + end + it 'フキダシテンプレートが作成されている' do + lambda { + SpeechBalloonTemplate.store 'newtemplate', @newattr + }.should change SpeechBalloonTemplate, :count + end + end + context '更新のとき' do + it 'フキダシテンプレートを保存しようとしている' do + SpeechBalloonTemplate.any_instance.should_receive(:save).exactly(1) + SpeechBalloonTemplate.store @st.name, @attr + end + it 'フキダシテンプレートの数に変化がない' do + lambda { + SpeechBalloonTemplate.store @st.name, @attr + }.should_not change SpeechBalloonTemplate, :count + end + end + it '属性が一致している' do + r = SpeechBalloonTemplate.store 'newtemplate', @newattr + r.classname.should eq 'New' + end + it '保存されたSpeechBalloonTemplateオブジェクトを返す' do + r = SpeechBalloonTemplate.store 'newtemplate', @newattr +p r.errors.full_messages + r.should_not be_a_new SpeechBalloonTemplate + end + end + context 'フキダシテンプレートの作成に失敗するとき' do + before do + SpeechBalloonTemplate.any_instance.stub(:save).with(any_args).and_return(false) + end + context '新規のとき' do + it 'フキダシテンプレートに変化がない' do + lambda { + r = SpeechBalloonTemplate.store 'newtemplate', @newattr + }.should_not change License, :count + end + end + context '更新のとき' do + it 'フキダシテンプレート属性に変化がない' do + lambda { + r = SpeechBalloonTemplate.store @st.name, @attr + }.should_not change License.find(@st.id), :classname + end + end + end + end + + describe 'テキスト取り込みに於いて' do + #成功でTrue、パース失敗でFalse、失敗は保存エラーのモデルを配列で返す + before do + end + context 'つつがなく終わるとき' do + it 'Json解析を依頼する' do + SpeechBalloonTemplate.should_receive(:parse).with(any_args).exactly(1) + SpeechBalloonTemplate.stub(:parse).with(any_args).and_return(@j) + SpeechBalloonTemplate.import(@t) + end + it 'フキダシテンプレート更新を一回依頼する' do + SpeechBalloonTemplate.stub(:store).with(any_args).and_return(SpeechBalloonTemplate.new) + SpeechBalloonTemplate.any_instance.stub(:valid?).with(any_args).and_return(true) + SpeechBalloonTemplate.should_receive(:store).with(any_args).exactly(1) + SpeechBalloonTemplate.import(@t) + end + it 'フキダシテンプレートが追加される' do + lambda { + SpeechBalloonTemplate.import(@t) + }.should change SpeechBalloonTemplate, :count + end + it '[]を返す' do + SpeechBalloonTemplate.import(@t).should eq [] + end + end + context '複数データがつつがなく終わるとき' do + it 'フキダシテンプレート更新を二回依頼する' do + SpeechBalloonTemplate.stub(:store).with(any_args).and_return(SpeechBalloonTemplate.new) + SpeechBalloonTemplate.any_instance.stub(:valid?).with(any_args).and_return(true) + SpeechBalloonTemplate.should_receive(:store).with(any_args).exactly(2) + SpeechBalloonTemplate.import(@ts) + end + it 'フキダシテンプレートが二個追加される' do + lambda { + SpeechBalloonTemplate.import(@ts) + }.should change(SpeechBalloonTemplate, :count).by 2 + end + it '[]を返す' do + SpeechBalloonTemplate.import(@ts).should eq [] + end + end + #例外ケース + context 'Json解析に失敗したとき' do + before do + SpeechBalloonTemplate.stub(:parse).with(any_args).and_return(false) + end + it 'フキダシテンプレートの数に変化がない' do + lambda { + SpeechBalloonTemplate.import(@t) + }.should_not change SpeechBalloonTemplate, :count + end + it 'Falseを返す' do + SpeechBalloonTemplate.import(@t).should be_false + end + end + context 'フキダシテンプレート作成に失敗したとき' do + before do + SpeechBalloonTemplate.any_instance.stub(:save).with(any_args).and_return(false) + SpeechBalloonTemplate.any_instance.stub(:valid?).with(any_args).and_return(false) + end + it 'フキダシテンプレートの数に変化がない' do + lambda { + SpeechBalloonTemplate.import(@t) + }.should_not change SpeechBalloonTemplate, :count + end + it '配列を返す' do + r = SpeechBalloonTemplate.import(@t) + r.is_a?(Array).should be_true + end + it '配列の中身は一件' do + r = SpeechBalloonTemplate.import(@t) + r.should have(1).items + end + it 'フキダシテンプレートオブジェクトが入っている' do + r = SpeechBalloonTemplate.import(@t) + r.first.is_a?(SpeechBalloonTemplate).should be_true + end + end + context '複数のフキダシテンプレート作成に失敗したとき' do + #三件中、二件の失敗、一件を成功させ、成功データは戻り値に含まないことを確認する + it 'フキダシテンプレートの数に変化がない' do + lambda { + SpeechBalloonTemplate.import(@tes) + }.should_not change SpeechBalloonTemplate, :count + end + it '途中で保存に失敗しても全件更新依頼する' do + SpeechBalloonTemplate.stub(:store).with(any_args).and_return(SpeechBalloonTemplate.new) + SpeechBalloonTemplate.should_receive(:store).with(any_args).exactly(3) + SpeechBalloonTemplate.import(@tes) + end + it '配列を返す' do + r = SpeechBalloonTemplate.import(@tes) + r.is_a?(Array).should be_true + end + it '配列の中身は2件' do + r = SpeechBalloonTemplate.import(@tes) + r.should have(2).items + end + it '配列の中身は失敗したフキダシテンプレートオブジェクトが入っている' do + r = SpeechBalloonTemplate.import(@tes) + r[0].is_a?(SpeechBalloonTemplate).should be_true + r[0]["name"].should eq 'fail1' + r[1].is_a?(SpeechBalloonTemplate).should be_true + r[1]["name"].should eq 'fail2' + end + end + end + + describe 'インポートエラーの表示に於いて' do + end + + describe 'ファイル取り込みに於いて' do + before do + SpeechBalloonTemplate.stub(:import).with(any_args).and_return(true) + end + context 'つつがなく終わるとき' do + before do + SpeechBalloonTemplate.stub(:import).with(any_args).and_return(true) + end + it 'ファイルを開いてテキストを読む' do + File.should_receive(:open).with(@f, 'r').exactly(1) + SpeechBalloonTemplate.import_file(@f) + end + it 'テキスト取り込みを依頼する' do + SpeechBalloonTemplate.should_receive(:import).with(any_args).exactly(1) + SpeechBalloonTemplate.import_file(@f) + end + #テキスト取り込み成功でTrueが返る + it 'Trueを返す' do + SpeechBalloonTemplate.import_file(@f).should be_true + end + end + context 'ファイルが開けないとき' do + before do + File.stub(:open).with(any_args).and_raise('StandardError') + end + it 'ファイルエラーのメッセージを出力する' do + pending + end + it 'Falseを返す' do + SpeechBalloonTemplate.import_file(@f).should be_false + end + end + #失敗したときは、失敗したフキダシテンプレートが配列で返る + context 'テキスト取り込みが失敗したとき' do + before do + SpeechBalloonTemplate.stub(:import).with(any_args).and_return(false) + end + it '各フキダシテンプレートのエラーメッセージを出力する' do + pending + end + it 'Falseを返す' do + SpeechBalloonTemplate.import_file(@f).should be_false + end + end + end + end diff --git a/spec/models/system_picture_spec.rb b/spec/models/system_picture_spec.rb index cc056848..626ec474 100644 --- a/spec/models/system_picture_spec.rb +++ b/spec/models/system_picture_spec.rb @@ -1,5 +1,284 @@ +# -*- encoding: utf-8 -*- require 'spec_helper' - +#システム画像 describe SystemPicture do - pending "add some examples to (or delete) #{__FILE__}" + before do + @admin = Factory :admin + @license = Factory :license + end + + describe '検証に於いて' do + before do + end + + it 'オーソドックスなデータなら通る' do + @sp = Factory.build :system_picture + @sp.should be_valid + end + + context 'extを検証するとき' do + before do + @sp = Factory.build :system_picture + end + it 'テストデータの確認' do + @sp.ext = 'jpeg' + @sp.should be_valid + end + it 'nullなら失敗する' do + @sp.ext = '' + @sp.should_not be_valid + end + it '5文字以上なら失敗する' do + @sp.ext = 'a'*5 + @sp.should_not be_valid + end + it 'png,gif,jpeg以外なら失敗する' do + @sp.ext = 'bmp' + @sp.should_not be_valid + end + end + context 'widthを検証するとき' do + before do + @sp = Factory.build :system_picture + end + it 'テストデータの確認' do + @sp.width = 1 + @sp.should be_valid + end + it 'nullなら失敗する' do + @sp.width = nil + @sp.should_not be_valid + end + it '数値でなければ失敗する' do + @sp.width = 'a' + @sp.should_not be_valid + end + it '0なら失敗する' do + @sp.width = '0' + @sp.should_not be_valid + end + it '負でも失敗する' do + @sp.width = -1 + @sp.should_not be_valid + end + end + context 'heightを検証するとき' do + before do + @sp = Factory.build :system_picture + end + it 'テストデータの確認' do + @sp.height = 1 + @sp.should be_valid + end + it 'nullなら失敗する' do + @sp.height = nil + @sp.should_not be_valid + end + it '数値でなければ失敗する' do + @sp.height = 'a' + @sp.should_not be_valid + end + it '0なら失敗する' do + @sp.height = '0' + @sp.should_not be_valid + end + it '負でも失敗する' do + @sp.height = -1 + @sp.should_not be_valid + end + end + context 'filesizeを検証するとき' do + before do + @sp = Factory.build :system_picture + end + it 'テストデータの確認' do + @sp.filesize = 1 + @sp.should be_valid + end + it 'nullなら失敗する' do + @sp.filesize = nil + @sp.should_not be_valid + end + it '数値でなければ失敗する' do + @sp.filesize = 'a' + @sp.should_not be_valid + end + it '負なら失敗する' do + @sp.filesize = '-1' + @sp.should_not be_valid + end + it '2MB以上なら失敗する' do + @sp.filesize = 2000000+1 + @sp.should_not be_valid + end + end + context 'md5を検証するとき' do + before do + @sp = Factory.build :system_picture + end + it 'テストデータの確認' do + @sp.md5 = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' + @sp.should be_valid + end + it 'nullなら失敗する' do + @sp.md5 = '' + @sp.should_not be_valid + end + it '32文字以上なら失敗する' do + @sp.md5 = 'a'*33 + @sp.should_not be_valid + end + end + end + + describe 'データ補充に於いて' do + before do + end + + end + + describe '作成・更新に於いて' do + before do + @sp = Factory.build :system_picture + #RMagickのスタブをおいておく + class Mgk ; class Image ; end ; end + @filesize = 76543 + Mgk::Image.stub(:from_blob).with(any_args).and_return([Mgk.new]) + Mgk.any_instance.stub(:format).with(any_args).and_return('png') + Mgk.any_instance.stub(:rows).with(any_args).and_return(200) + Mgk.any_instance.stub(:columns).with(any_args).and_return(100) + Mgk.any_instance.stub(:filesize).with(any_args).and_return(@filesize) + Mgk.any_instance.stub(:to_blob).with(any_args).and_return('data') + end + context '事前チェック' do + before do + #すべての処理が正常パターンで通過すれば、一番深い分岐まで通る。 + #それで外部のメソッド呼び出しだけに着目してテストする。 + SystemPicture.any_instance.stub(:data_to_mgk).with(any_args).and_return(Mgk.new) + SystemPicture.any_instance.stub(:save).with(any_args).and_return(true) + PictureIO::LocalPicture.any_instance.stub(:put).with(any_args).and_return(true) + end + it 'RMagick変換を依頼している' do + SystemPicture.any_instance.should_receive(:data_to_mgk).exactly(1) + @sp.store 'bindata' + end + it '自身に属性をセットしている' do + SystemPicture.any_instance.should_receive(:attributes=).exactly(1) + @sp.store 'bindata' + end + it '自身が保存されている' do + SystemPicture.any_instance.should_receive(:save).exactly(1) + @sp.store 'bindata' + end + it 'PictureIoに画像データの保存を依頼している' do + PictureIO::LocalPicture.any_instance.should_receive(:put).with(any_args).exactly(1) + @sp.store 'bindata' + end + end + context 'つつがなく終わるとき' do + before do + #すべての処理を正常パターンで通過させ、保存機能をチェックする。 + SystemPicture.any_instance.stub(:data_to_mgk).with(any_args).and_return(Mgk.new) +# SystemPicture.any_instance.stub(:save).with(any_args).and_return(true) + PictureIO::LocalPicture.any_instance.stub(:put).with(any_args).and_return(true) + end + it '自身に属性をセットしている' do + lambda { + @sp.store 'bindata' + }.should change @sp, :filesize + end + it 'システム画像モデルが作成されている' do + lambda { + @sp.store 'bindata' + }.should change SystemPicture, :count + end + it 'システム画像が保存されている' do + @sp.store 'bindata' + SystemPicture.find(@sp).should_not be_nil + end + it 'Trueを返す' do + @sp.store('bindata').should eq true + end + end + #以下から例外ケース。処理先頭から失敗させていく + context 'RMagick変換が失敗したとき' do + before do + SystemPicture.any_instance.stub(:data_to_mgk).with(any_args).and_return(false) + end + it 'falseを返す' do + @sp.store('bindata').should be_false + end + it '自身の保存は呼ばれていない' do + SystemPicture.any_instance.should_not_receive(:save) + end + end + context '自身の保存に失敗したとき' do + before do + SystemPicture.any_instance.stub(:data_to_mgk).with(any_args).and_return(Mgk.new) + SystemPicture.any_instance.stub(:save).with(any_args).and_return(false) + end + it 'falseを返す' do + @sp.store('bindata').should be_false + end + it '更新されていない' do + @sp.store('bindata') + @sp.should be_a_new SystemPicture + end + it '原画の保存は呼ばれていない' do + PictureIO::LocalPicture.any_instance.should_not_receive(:put) + end + end + end + + describe '置換に於いて' do + before do + @sp = Factory :system_picture + end + context '新規のとき' do + before do + SystemPicture.stub(:find_by_md5).with(any_args).and_return(nil) + SystemPicture.any_instance.stub(:store).with(any_args).and_return(true) + end + it '新規オブジェクト生成している' do + r = SystemPicture.store 'bindata' + r.should be_a_new SystemPicture + end + it '作成依頼している' do + SystemPicture.any_instance.should_receive(:store).with('bindata').exactly(1) + SystemPicture.store 'bindata' + end + it '保存された行を返す' do + r = SystemPicture.store 'bindata' + r.should_not eq @sp + end + end + context '既存のとき' do + before do + SystemPicture.stub(:find_by_md5).with(any_args).and_return(@sp) + SystemPicture.any_instance.stub(:store).with(any_args).and_return(true) + end + it '新規オブジェクト生成していない' do + SystemPicture.should_receive(:new).with(any_args).exactly(0) + SystemPicture.store 'bindata' + end + it '作成依頼している' do + SystemPicture.any_instance.should_receive(:store).with('bindata').exactly(1) + SystemPicture.store 'bindata' + end + it '保存された行を返す' do + r = SystemPicture.store 'bindata' + r.should eq @sp + end + end + context '保存失敗のとき' do + before do + SystemPicture.stub(:find_by_md5).with(any_args).and_return(@sp) + SystemPicture.any_instance.stub(:store).with(any_args).and_return(false) + end + it 'nilを返す' do + r = SystemPicture.store 'bindata' + r.should eq nil + end + end + end end -- 2.11.0