From eb397c27a98c59c856b91a5b09d1316b1135a15c Mon Sep 17 00:00:00 2001 From: yasushiito Date: Sun, 22 Sep 2013 10:10:42 +0900 Subject: [PATCH] t#32046: --- .gitignore | 2 +- app/assets/javascripts/sheet_panels.js.coffee | 3 + app/assets/javascripts/sheets.js.coffee | 3 + app/assets/javascripts/story_sheets.js.coffee | 3 + app/assets/stylesheets/sheet_panels.css.scss | 3 + app/assets/stylesheets/sheets.css.scss | 3 + app/assets/stylesheets/story_sheets.css.scss | 3 + app/controllers/comics_controller.rb | 131 ++ app/controllers/sheet_panels_controller.rb | 2 + app/controllers/sheets_controller.rb | 2 + app/controllers/stories_controller.rb | 157 ++ app/controllers/story_sheets_controller.rb | 2 + app/helpers/comics_helper.rb | 2 + app/helpers/sheet_panels_helper.rb | 2 + app/helpers/sheets_helper.rb | 2 + app/helpers/stories_helper.rb | 2 + app/helpers/story_sheets_helper.rb | 2 + app/models/author.rb | 76 + app/models/comic.rb | 165 ++ app/models/sheet.rb | 172 ++ app/models/sheet_panel.rb | 319 ++++ app/models/story.rb | 266 +++ app/models/story_sheet.rb | 289 +++ app/views/comics/_form.html.erb | 23 + app/views/comics/_list_item.html.erb | 25 + app/views/comics/browse.html.erb | 34 + app/views/comics/edit.html.erb | 4 + app/views/comics/edit.js.erb | 1 + app/views/comics/index.atom.builder | 25 + app/views/comics/index.html.erb | 9 + app/views/comics/index.rss.builder | 24 + app/views/comics/list.html.erb | 24 + app/views/comics/new.html.erb | 5 + app/views/comics/new.js.erb | 1 + app/views/comics/show.atom.builder | 25 + app/views/comics/show.html.erb | 35 + app/views/comics/show.rss.builder | 24 + app/views/stories/_append_panel.html.erb | 21 + app/views/stories/_comic_header.html.erb | 40 + app/views/stories/_footer.html.erb | 23 + app/views/stories/_form.html.erb | 20 + app/views/stories/_licensed_pictures.html.erb | 14 + app/views/stories/_list_item.html.erb | 28 + app/views/stories/_order.html.erb | 15 + app/views/stories/browse.html.erb | 28 + app/views/stories/comic.html.erb | 33 + app/views/stories/edit.html.erb | 5 + app/views/stories/edit.js.erb | 1 + app/views/stories/index.html.erb | 8 + app/views/stories/list.html.erb | 29 + app/views/stories/new.html.erb | 3 + app/views/stories/show.html.erb | 41 + config/routes.rb | 72 +- db/migrate/20130914055043_create_sheets.rb | 13 + db/migrate/20130914055219_create_sheet_panels.rb | 15 + db/migrate/20130914061319_restruct_comic.rb | 27 + db/migrate/20130920042226_create_story_sheets.rb | 12 + spec/controllers/artists_controller_spec.rb | 1 + spec/controllers/authors_controller_spec.rb | 1 + spec/controllers/balloons_controller_spec.rb | 1 + spec/controllers/ground_colors_controller_spec.rb | 1 + .../controllers/ground_pictures_controller_spec.rb | 1 + spec/controllers/home_controller_spec.rb | 1 + spec/controllers/panels_controller_spec.rb | 1 + spec/controllers/sheet_panels_controller_spec.rb | 5 + spec/controllers/sheets_controller_spec.rb | 5 + .../speech_balloon_templates_controller_spec.rb | 1 + .../controllers/speech_balloons_controller_spec.rb | 1 + spec/controllers/speeches_controller_spec.rb | 1 + spec/controllers/story_sheets_controller_spec.rb | 5 + .../controllers/system_pictures_controller_spec.rb | 1 + spec/factories.rb | 42 + spec/helpers/sheet_panels_helper_spec.rb | 15 + spec/helpers/sheets_helper_spec.rb | 15 + spec/helpers/story_sheets_helper_spec.rb | 15 + spec/models/artist_spec.rb | 1 + spec/models/author_spec.rb | 75 +- spec/models/balloon_spec.rb | 2 + spec/models/comic_spec.rb | 816 ++++++++ spec/models/ground_color_spec.rb | 1 + spec/models/ground_picture_spec.rb | 1 + spec/models/license_group_spec.rb | 1 + spec/models/original_picture_spec.rb | 1 + spec/models/panel_picture_spec.rb | 1 + spec/models/panel_spec.rb | 1 + spec/models/resource_picture_spec.rb | 1 + spec/models/scroll_panel_spec.rb | 117 +- spec/models/scroll_spec.rb | 63 +- spec/models/sheet_panel_spec.rb | 2002 ++++++++++++++++++++ spec/models/sheet_spec.rb | 675 +++++++ spec/models/speech_balloon_spec.rb | 1 + spec/models/speech_balloon_template_spec.rb | 1 + spec/models/speech_spec.rb | 34 +- spec/models/story_sheet_spec.rb | 1856 ++++++++++++++++++ spec/models/story_spec.rb | 1719 +++++++++++++++++ spec/models/system_picture_spec.rb | 2 + 96 files changed, 9693 insertions(+), 109 deletions(-) create mode 100644 app/assets/javascripts/sheet_panels.js.coffee create mode 100644 app/assets/javascripts/sheets.js.coffee create mode 100644 app/assets/javascripts/story_sheets.js.coffee create mode 100644 app/assets/stylesheets/sheet_panels.css.scss create mode 100644 app/assets/stylesheets/sheets.css.scss create mode 100644 app/assets/stylesheets/story_sheets.css.scss create mode 100644 app/controllers/comics_controller.rb create mode 100644 app/controllers/sheet_panels_controller.rb create mode 100644 app/controllers/sheets_controller.rb create mode 100644 app/controllers/stories_controller.rb create mode 100644 app/controllers/story_sheets_controller.rb create mode 100644 app/helpers/comics_helper.rb create mode 100644 app/helpers/sheet_panels_helper.rb create mode 100644 app/helpers/sheets_helper.rb create mode 100644 app/helpers/stories_helper.rb create mode 100644 app/helpers/story_sheets_helper.rb create mode 100644 app/models/sheet.rb create mode 100644 app/models/sheet_panel.rb create mode 100644 app/models/story_sheet.rb create mode 100644 app/views/comics/_form.html.erb create mode 100644 app/views/comics/_list_item.html.erb create mode 100644 app/views/comics/browse.html.erb create mode 100644 app/views/comics/edit.html.erb create mode 100644 app/views/comics/edit.js.erb create mode 100644 app/views/comics/index.atom.builder create mode 100644 app/views/comics/index.html.erb create mode 100644 app/views/comics/index.rss.builder create mode 100644 app/views/comics/list.html.erb create mode 100644 app/views/comics/new.html.erb create mode 100644 app/views/comics/new.js.erb create mode 100644 app/views/comics/show.atom.builder create mode 100644 app/views/comics/show.html.erb create mode 100644 app/views/comics/show.rss.builder create mode 100644 app/views/stories/_append_panel.html.erb create mode 100644 app/views/stories/_comic_header.html.erb create mode 100644 app/views/stories/_footer.html.erb create mode 100644 app/views/stories/_form.html.erb create mode 100644 app/views/stories/_licensed_pictures.html.erb create mode 100644 app/views/stories/_list_item.html.erb create mode 100644 app/views/stories/_order.html.erb create mode 100644 app/views/stories/browse.html.erb create mode 100644 app/views/stories/comic.html.erb create mode 100644 app/views/stories/edit.html.erb create mode 100644 app/views/stories/edit.js.erb create mode 100644 app/views/stories/index.html.erb create mode 100644 app/views/stories/list.html.erb create mode 100644 app/views/stories/new.html.erb create mode 100644 app/views/stories/show.html.erb create mode 100644 db/migrate/20130914055043_create_sheets.rb create mode 100644 db/migrate/20130914055219_create_sheet_panels.rb create mode 100644 db/migrate/20130914061319_restruct_comic.rb create mode 100644 db/migrate/20130920042226_create_story_sheets.rb create mode 100644 spec/controllers/sheet_panels_controller_spec.rb create mode 100644 spec/controllers/sheets_controller_spec.rb create mode 100644 spec/controllers/story_sheets_controller_spec.rb create mode 100644 spec/helpers/sheet_panels_helper_spec.rb create mode 100644 spec/helpers/sheets_helper_spec.rb create mode 100644 spec/helpers/story_sheets_helper_spec.rb create mode 100644 spec/models/comic_spec.rb create mode 100644 spec/models/sheet_panel_spec.rb create mode 100644 spec/models/sheet_spec.rb create mode 100644 spec/models/story_sheet_spec.rb create mode 100644 spec/models/story_spec.rb diff --git a/.gitignore b/.gitignore index 603100a4..72fab492 100644 --- a/.gitignore +++ b/.gitignore @@ -25,4 +25,4 @@ db/migrate/*_unknown_v??_licenses_attributes.rb db/migrate/*_speech_balloon_speech_balloons.rb db/migrate/*_speech_balloon_balloons.rb db/migrate/*_speech_balloon_speeches.rb -db/migrate/*_speech_balloon_import_*.rb +db/migrate/*_speech_balloon_import*.rb diff --git a/app/assets/javascripts/sheet_panels.js.coffee b/app/assets/javascripts/sheet_panels.js.coffee new file mode 100644 index 00000000..76156794 --- /dev/null +++ b/app/assets/javascripts/sheet_panels.js.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/ diff --git a/app/assets/javascripts/sheets.js.coffee b/app/assets/javascripts/sheets.js.coffee new file mode 100644 index 00000000..76156794 --- /dev/null +++ b/app/assets/javascripts/sheets.js.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/ diff --git a/app/assets/javascripts/story_sheets.js.coffee b/app/assets/javascripts/story_sheets.js.coffee new file mode 100644 index 00000000..76156794 --- /dev/null +++ b/app/assets/javascripts/story_sheets.js.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/ diff --git a/app/assets/stylesheets/sheet_panels.css.scss b/app/assets/stylesheets/sheet_panels.css.scss new file mode 100644 index 00000000..0550fe96 --- /dev/null +++ b/app/assets/stylesheets/sheet_panels.css.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the sheet_panels controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/assets/stylesheets/sheets.css.scss b/app/assets/stylesheets/sheets.css.scss new file mode 100644 index 00000000..bc4b9bf2 --- /dev/null +++ b/app/assets/stylesheets/sheets.css.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the sheets controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/assets/stylesheets/story_sheets.css.scss b/app/assets/stylesheets/story_sheets.css.scss new file mode 100644 index 00000000..557cdb46 --- /dev/null +++ b/app/assets/stylesheets/story_sheets.css.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the story_sheets controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/controllers/comics_controller.rb b/app/controllers/comics_controller.rb new file mode 100644 index 00000000..c5f85468 --- /dev/null +++ b/app/controllers/comics_controller.rb @@ -0,0 +1,131 @@ +class ComicsController < ApplicationController + layout 'test' if MagicNumber['test_layout'] + if MagicNumber['run_mode'] == 0 + before_filter :authenticate_user, :only => [:new, :create, :edit, :update, :destroy] + before_filter :authenticate_author, :only => [:new, :create, :edit, :update, :destroy] + else + before_filter :authenticate_reader, :only => [:top, :index, :show] + before_filter :authenticate_user, :only => [:new, :create, :edit, :update, :destroy] + before_filter :authenticate_author, :only => [:new, :create, :edit, :update, :destroy] + end + before_filter :authenticate_admin!, :only => [:list, :browse] + + def index + @page = Comic.page params[:page] + @page_size = Comic.page_size params[:page_size] + @comics = Comic.list(@page, @page_size) + respond_to do |format| + format.html { + @paginate = Comic.list_paginate(@page, @page_size) + } + format.json { render json: @comics.to_json(Comic.list_json_opt) } + format.atom + format.rss + end + end + + def show + @comic = Comic.show(params[:id], [@user, @admin]) + + respond_to do |format| + format.html # show.html.erb + format.json { render json: @comic.to_json(Comic.show_json_opt) } + format.atom + format.rss + end + end + + def count + @comic = {:count => Comic.visible_count} + respond_to do |format| + format.json { render json: @comic.to_json } + end + end + + def list + @comics = Comic.all + + respond_to do |format| + format.html { render layout: 'system' }# index.html.erb + format.json { render json: @comics } + end + end + + def browse + @comic = Comic.find(params[:id]) + + respond_to do |format| + format.html { render layout: 'system' } # show.html.erb + format.json { render json: @comic } + end + end + + def new + @comic = Comic.new + @comic.supply_default + respond_to do |format| + format.html # new.html.erb + format.js + format.json { render json: @comic.to_json(Comic.show_json_opt) } + end + end + + def edit + @comic = Comic.edit(params[:id], @author) + respond_to do |format| + format.html + format.js + end + end + + def create + @comic = Comic.new + @comic.supply_default + @comic.attributes = params[:comic] + @comic.overwrite @author + + respond_to do |format| + if @comic.save + flash[:notice] = I18n.t('flash.notice.created', :model => Comic.model_name.human) + format.html { redirect_to @comic } + format.json { render json: @comic.to_json(Comic.show_json_opt), status: :created, location: @comic } + else + flash[:notice] = I18n.t('flash.notice.not_created', :model => Comic.model_name.human) + format.html { render action: "new" } + format.json { render json: @comic.errors, status: :unprocessable_entity } + end + end + end + + def update + @comic = Comic.edit(params[:id], @author) + @comic.attributes = params[:comic] + @comic.overwrite @author + respond_to do |format| + if @comic.save + flash[:notice] = I18n.t('flash.notice.updated', :model => Comic.model_name.human) + format.html { redirect_to @comic } + format.json { head :ok } + else + flash[:notice] = I18n.t('flash.notice.not_updated', :model => Comic.model_name.human) + format.html { render action: "edit" } + format.json { render json: @comic.errors, status: :unprocessable_entity } + end + end + end + + def destroy + @comic = Comic.edit(params[:id], @author) + respond_to do |format| + if @comic.destroy_with_story + flash[:notice] = I18n.t('flash.notice.destroyed', :model => Comic.model_name.human) + format.html { redirect_to '/home/comics' } + format.json { head :ok } + else + flash[:notice] = I18n.t('flash.notice.not_destroyed', :model => Comic.model_name.human) + format.html { redirect_to @comic } + format.json { render json: @comic.errors, status: :unprocessable_entity } + end + end + end +end diff --git a/app/controllers/sheet_panels_controller.rb b/app/controllers/sheet_panels_controller.rb new file mode 100644 index 00000000..cece2c7b --- /dev/null +++ b/app/controllers/sheet_panels_controller.rb @@ -0,0 +1,2 @@ +class SheetPanelsController < ApplicationController +end diff --git a/app/controllers/sheets_controller.rb b/app/controllers/sheets_controller.rb new file mode 100644 index 00000000..b24b4231 --- /dev/null +++ b/app/controllers/sheets_controller.rb @@ -0,0 +1,2 @@ +class SheetsController < ApplicationController +end diff --git a/app/controllers/stories_controller.rb b/app/controllers/stories_controller.rb new file mode 100644 index 00000000..ca77f0d6 --- /dev/null +++ b/app/controllers/stories_controller.rb @@ -0,0 +1,157 @@ +class StoriesController < ApplicationController + layout 'test' if MagicNumber['test_layout'] + if MagicNumber['run_mode'] == 0 + before_filter :authenticate_user, :only => [:new, :create, :edit, :update, :destroy] + before_filter :authenticate_author, :only => [:new, :create, :edit, :update, :destroy] + else + before_filter :authenticate_reader, :only => [:index, :show, :comic] + before_filter :authenticate_user, :only => [:new, :create, :edit, :update, :destroy] + before_filter :authenticate_author, :only => [:new, :create, :edit, :update, :destroy] + end + before_filter :authenticate_admin!, :only => [:list, :browse] + + def index + @page = Story.page params[:page] + @page_size = Story.page_size params[:page_size] + @stories = Story.list(@page, @page_size) + + respond_to do |format| + format.html { + @paginate = Story.list_paginate(@page, @page_size) + } + format.json { render :json => @stories.to_json(Story.list_json_opt) } + end + end + + def show + @story = Story.show(params[:id], [@user, @admin]) + + respond_to do |format| + format.html # show.html.erb + format.json { render json: @story.story_as_json(@author) } + end + end + + def comic + @comic = Comic.show(params[:id], [@user, @admin]) + cnt = Story.count(:conditions => ['comic_id = ?', @comic.id]).to_i + @offset = Story.offset cnt, params[:offset] + @panel_count = Story.panel_count cnt, params[:count] + @stories = Story.play_list(@comic, @author, @offset, @panel_count) + respond_to do |format| + format.html { + @prev_offset = if @offset > 0 + if @offset - @panel_count < 0 + 0 + else + @offset - @panel_count + end + else + nil + end + @next_offset = if @offset + @panel_count > cnt + nil + else + @offset + @panel_count + end + if @author + @new_panels = Panel.mylist(@author, 1, 5) + end + } + format.json {render text: Story.list_as_json_text(@stories, @author)} + format.jsonp { + render :json => "callback(" + @stories.to_json_list + ");" + } + end + end + + def list + @stories = Story.all + + respond_to do |format| + format.html { render layout: 'system' }# index.html.erb + format.json { render json: @stories } + end + end + + def browse + @story = Story.find(params[:id]) + + respond_to do |format| + format.html { render layout: 'system' } # show.html.erb + format.json { render json: @story } + end + end + + def new + @story = Story.new + @story.supply_default + respond_to do |format| + format.html # new.html.erb + format.js + format.json { render json: @story.story_as_json(@author) } + end + end + + def edit + @story = Story.edit(params[:id], @author) + respond_to do |format| + format.html + format.js + end + end + + def create + @story = Story.new + @story.supply_default + @story.attributes = params[:story] + @story.overwrite @author + @comic = Comic.edit(@story.comic_id, @author) if @story.comic_id + @panel = Panel.show(@story.panel_id, @author) if @story.panel_id + + respond_to do |format| + if @story.store + flash[:notice] = I18n.t('flash.notice.created', :model => Story.model_name.human) + format.html { redirect_to action: :comic, id: @story.comic_id } + format.json { render json: @story.story_as_json(@author) } + else + flash[:notice] = I18n.t('flash.notice.not_created', :model => Story.model_name.human) + format.html { render action: "new" } + format.json { render json: @story.errors, status: :unprocessable_entity } + end + end + end + + def update + @story = Story.edit(params[:id], @author) + ot = @story.t + @story.attributes = params[:story] + @story.overwrite @author + respond_to do |format| + if @story.store ot + flash[:notice] = I18n.t('flash.notice.updated', :model => Story.model_name.human) + format.html { redirect_to action: :comic, id: @story.comic_id } + format.json { head :ok } + else + flash[:notice] = I18n.t('flash.notice.not_updated', :model => Story.model_name.human) + format.html { render action: "edit" } + format.json { render json: @story.errors, status: :unprocessable_entity } + end + end + end + + def destroy + @story = Story.edit(params[:id], @author) + respond_to do |format| + if @story.destroy_and_shorten + flash[:notice] = I18n.t('flash.notice.destroyed', :model => Story.model_name.human) + format.html { redirect_to :controller => 'stories', :action => :comic, :id => @story.comic_id } + format.json { head :ok } + else + flash[:notice] = I18n.t('flash.notice.not_destroyed', :model => Story.model_name.human) + format.html { redirect_to story_path(@story) } + format.json { render json: @story.errors, status: :unprocessable_entity } + end + end + end +end diff --git a/app/controllers/story_sheets_controller.rb b/app/controllers/story_sheets_controller.rb new file mode 100644 index 00000000..55d1259e --- /dev/null +++ b/app/controllers/story_sheets_controller.rb @@ -0,0 +1,2 @@ +class StorySheetsController < ApplicationController +end diff --git a/app/helpers/comics_helper.rb b/app/helpers/comics_helper.rb new file mode 100644 index 00000000..597e65aa --- /dev/null +++ b/app/helpers/comics_helper.rb @@ -0,0 +1,2 @@ +module ComicsHelper +end diff --git a/app/helpers/sheet_panels_helper.rb b/app/helpers/sheet_panels_helper.rb new file mode 100644 index 00000000..741800d9 --- /dev/null +++ b/app/helpers/sheet_panels_helper.rb @@ -0,0 +1,2 @@ +module SheetPanelsHelper +end diff --git a/app/helpers/sheets_helper.rb b/app/helpers/sheets_helper.rb new file mode 100644 index 00000000..e9eb223a --- /dev/null +++ b/app/helpers/sheets_helper.rb @@ -0,0 +1,2 @@ +module SheetsHelper +end diff --git a/app/helpers/stories_helper.rb b/app/helpers/stories_helper.rb new file mode 100644 index 00000000..43e5cd8f --- /dev/null +++ b/app/helpers/stories_helper.rb @@ -0,0 +1,2 @@ +module StoriesHelper +end diff --git a/app/helpers/story_sheets_helper.rb b/app/helpers/story_sheets_helper.rb new file mode 100644 index 00000000..0a4e02cd --- /dev/null +++ b/app/helpers/story_sheets_helper.rb @@ -0,0 +1,2 @@ +module StorySheetsHelper +end diff --git a/app/models/author.rb b/app/models/author.rb index 12f860a6..40d0c1d6 100644 --- a/app/models/author.rb +++ b/app/models/author.rb @@ -2,6 +2,7 @@ class Author < ActiveRecord::Base has_one :artist belongs_to :user has_many :scrolls + has_many :sheets has_many :panels belongs_to :working_panel, :class_name => "Panel" @@ -146,6 +147,81 @@ class Author < ActiveRecord::Base page_size end + def self.default_comic_page_size + 25 + end + + def self.comic_max_page_size + 100 + end + + def self.comic_page_size prm = self.default_comic_page_size + page_size = prm.to_i + page_size = self.comic_max_page_size if page_size > self.comic_max_page_size + page_size = self.default_comic_page_size if page_size < 1 + page_size + end + + def self.default_story_page_size + 25 + end + + def self.story_max_page_size + 100 + end + + def self.story_page_size prm = self.default_story_page_size + page_size = prm.to_i + page_size = self.story_max_page_size if page_size > self.story_max_page_size + page_size = self.default_story_page_size if page_size < 1 + page_size + end + + def self.default_story_sheet_page_size + 25 + end + + def self.story_sheet_max_page_size + 100 + end + + def self.story_sheet_page_size prm = self.default_story_sheet_page_size + page_size = prm.to_i + page_size = self.story_sheet_max_page_size if page_size > self.story_sheet_max_page_size + page_size = self.default_story_sheet_page_size if page_size < 1 + page_size + end + + def self.default_sheet_page_size + 25 + end + + def self.sheet_max_page_size + 100 + end + + def self.sheet_page_size prm = self.default_sheet_page_size + page_size = prm.to_i + page_size = self.sheet_max_page_size if page_size > self.sheet_max_page_size + page_size = self.default_sheet_page_size if page_size < 1 + page_size + end + + def self.default_sheet_panel_page_size + 25 + end + + def self.sheet_panel_max_page_size + 100 + end + + def self.sheet_panel_page_size prm = self.default_sheet_panel_page_size + page_size = prm.to_i + page_size = self.sheet_panel_max_page_size if page_size > self.sheet_panel_max_page_size + page_size = self.default_sheet_panel_page_size if page_size < 1 + page_size + end + def self.default_panel_page_size 25 end diff --git a/app/models/comic.rb b/app/models/comic.rb index 49cce7b6..7ae8ba8a 100644 --- a/app/models/comic.rb +++ b/app/models/comic.rb @@ -1,3 +1,168 @@ #コミック class Comic < ActiveRecord::Base + has_many :stories + belongs_to :author + + validates :title, :presence => true, :length => {:maximum => 100} + validates :visible, :presence => true, :numericality => true, :inclusion => {:in => 0..1} + before_validation :valid_encode + + def valid_encode + ['title', 'description'].each do |a| + next if attributes[a] == nil + raise Pettanr::BadRequest unless attributes[a].valid_encoding? + end + end + + def supply_default + self.visible = 0 if self.visible.blank? + end + + def overwrite au + return false unless au + self.author_id = au.id + end + + def own? roles + roles = [roles] unless roles.respond_to?(:each) + au = Comic.get_author_from_roles roles + return false unless au + self.author_id == au.id + end + + def visible? roles + if MagicNumber['run_mode'] == 0 + return false unless guest_role_check(roles) + else + return false unless reader_role_check(roles) + end + return true if self.own?(roles) + self.visible > 0 + end + + def self.default_page_size + 25 + end + + def self.max_page_size + 100 + end + + def self.default_panel_size + 30 + end + + def self.max_panel_size + 200 + end + + def self.page prm = nil + page = prm.to_i + page = 1 if page < 1 + page + end + + def self.page_size prm = self.default_page_size + page_size = prm.to_i + page_size = self.max_page_size if page_size > self.max_page_size + page_size = self.default_page_size if page_size < 1 + page_size + end + + def self.list_where + 'comics.visible > 0' + end + + def self.mylist_where au + ['comics.author_id = ?', au.id] + end + + def self.himlist_where au + ['comics.author_id = ? and comics.visible > 0', au.id] + end + + def self.list page = 1, page_size = self.default_page_size + Comic.where(self.list_where()).includes(Comic.list_opt).order('comics.updated_at desc').offset((page -1) * page_size).limit(page_size) + end + + def self.mylist au, page = 1, page_size = Author.default_comic_page_size + Comic.where(self.mylist_where(au)).includes(Comic.list_opt).order('comics.updated_at desc').offset((page -1) * page_size).limit(page_size) + end + + def self.himlist au, page = 1, page_size = Author.default_comic_page_size + Comic.where(self.himlist_where(au)).includes(Comic.list_opt).order('comics.updated_at desc').offset((page -1) * page_size).limit(page_size) + end + + def self.list_paginate page = 1, page_size = self.default_page_size + Kaminari.paginate_array(Array.new(Comic.where(self.list_where()).count, nil)).page(page).per(page_size) + end + + def self.mylist_paginate au, page = 1, page_size = Author.default_comic_page_size + Kaminari.paginate_array(Array.new(Comic.where(self.mylist_where(au)).count, nil)).page(page).per(page_size) + end + + def self.himlist_paginate au, page = 1, page_size = Author.default_comic_page_size + Kaminari.paginate_array(Array.new(Comic.where(self.himlist_where(au)).count, nil)).page(page).per(page_size) + end + + def self.list_opt + {:stories => {}, :author => {} } + end + + def self.list_json_opt + {:include => {:stories => {}, :author => {}} } + end + + def self.show cid, roles + opt = {} + opt.merge!(Comic.show_opt) + res = Comic.find(cid, opt) + raise ActiveRecord::Forbidden unless res.visible?(roles) + res + end + + def self.edit cid, au + opt = {} + opt.merge!(Comic.show_opt) + res = Comic.find(cid, opt) + raise ActiveRecord::Forbidden unless res.own?(au) + res + end + + def self.show_opt + {:include => {:stories => {}, :author => {}} } + end + + def self.show_json_opt + {:include => {:stories => {}, :author => {}} } + end + + def self.visible_count + Comic.count 'visible > 0' + end + + def destroy_with_story + res = false + Comic.transaction do + self.stories.each do |story| + raise ActiveRecord::Rollback unless story.destroy + end + raise ActiveRecord::Rollback unless self.destroy + res = true + end + res + end + + def scenario + panels.map {|panel| + panel.scenario + }.join + end + + def plain_scenario + panels.map {|panel| + panel.plain_scenario + }.join + end + end diff --git a/app/models/sheet.rb b/app/models/sheet.rb new file mode 100644 index 00000000..a3b8bffc --- /dev/null +++ b/app/models/sheet.rb @@ -0,0 +1,172 @@ +class Sheet < ActiveRecord::Base + has_many :sheet_panels + has_many :story_sheets + belongs_to :author + + validates :caption, :presence => true, :length => {:maximum => 100} + validates :visible, :presence => true, :numericality => true, :inclusion => {:in => 0..1} + before_validation :valid_encode + + def valid_encode + ['caption', 'description'].each do |a| + next if attributes[a] == nil + raise Pettanr::BadRequest unless attributes[a].valid_encoding? + end + end + + def supply_default + self.visible = 0 if self.visible.blank? + end + + def overwrite au + return false unless au + self.author_id = au.id + end + + def own? roles + roles = [roles] unless roles.respond_to?(:each) + au = Sheet.get_author_from_roles roles + return false unless au + self.author_id == au.id + end + + def visible? roles + if MagicNumber['run_mode'] == 0 + return false unless guest_role_check(roles) + else + return false unless reader_role_check(roles) + end + return true if self.own?(roles) + self.visible > 0 + end + + def usable? au + visible? au + end + + def self.default_page_size + 25 + end + + def self.max_page_size + 100 + end + + def self.default_panel_size + 30 + end + + def self.max_panel_size + 200 + end + + def self.page prm = nil + page = prm.to_i + page = 1 if page < 1 + page + end + + def self.page_size prm = self.default_page_size + page_size = prm.to_i + page_size = self.max_page_size if page_size > self.max_page_size + page_size = self.default_page_size if page_size < 1 + page_size + end + + def self.list_where + 'sheets.visible > 0' + end + + def self.mylist_where au + ['sheets.author_id = ?', au.id] + end + + def self.himlist_where au + ['sheets.author_id = ? and sheets.visible > 0', au.id] + end + + def self.list page = 1, page_size = self.default_page_size + Sheet.where(self.list_where()).includes(Sheet.list_opt).order('sheets.updated_at desc').offset((page -1) * page_size).limit(page_size) + end + + def self.mylist au, page = 1, page_size = Author.default_sheet_page_size + Sheet.where(self.mylist_where(au)).includes(Sheet.list_opt).order('sheets.updated_at desc').offset((page -1) * page_size).limit(page_size) + end + + def self.himlist au, page = 1, page_size = Author.default_sheet_page_size + Sheet.where(self.himlist_where(au)).includes(Sheet.list_opt).order('sheets.updated_at desc').offset((page -1) * page_size).limit(page_size) + end + + def self.list_paginate page = 1, page_size = self.default_page_size + Kaminari.paginate_array(Array.new(Sheet.where(self.list_where()).count, nil)).page(page).per(page_size) + end + + def self.mylist_paginate au, page = 1, page_size = Author.default_sheet_page_size + Kaminari.paginate_array(Array.new(Sheet.where(self.mylist_where(au)).count, nil)).page(page).per(page_size) + end + + def self.himlist_paginate au, page = 1, page_size = Author.default_sheet_page_size + Kaminari.paginate_array(Array.new(Sheet.where(self.himlist_where(au)).count, nil)).page(page).per(page_size) + end + + def self.list_opt + {:sheet_panels => {:panel => {}}, :author => {} } + end + + def self.list_json_opt + {:include => {:sheet_panels => {:include => {:panel => {}}}, :author => {}}} + end + + def self.show sid, roles + opt = {} + opt.merge!(Sheet.show_opt) + res = Sheet.find(sid, opt) + raise ActiveRecord::Forbidden unless res.visible?(roles) + res + end + + def self.edit sid, au + opt = {} + opt.merge!(Sheet.show_opt) + res = Sheet.find(sid, opt) + raise ActiveRecord::Forbidden unless res.own?(au) + res + end + + def self.show_opt + {:include => {:sheet_panels => {:panel => {}}, :author => {}}} + end + + def self.show_json_opt + {:include => {:sheet_panels => {:include => {:panel => {}}}, :author => {}}} + end + + def self.visible_count + Sheet.count 'visible > 0' + end + + def destroy_with_sheet_panel + res = false + Sheet.transaction do + self.sheet_panels.each do |sheet_panel| + raise ActiveRecord::Rollback unless sheet_panel.destroy + end + raise ActiveRecord::Rollback unless self.destroy + res = true + end + res + end + + def scenario + panels.map {|panel| + panel.scenario + }.join + end + + def plain_scenario + panels.map {|panel| + panel.plain_scenario + }.join + end + +end diff --git a/app/models/sheet_panel.rb b/app/models/sheet_panel.rb new file mode 100644 index 00000000..39d251b7 --- /dev/null +++ b/app/models/sheet_panel.rb @@ -0,0 +1,319 @@ +class SheetPanel < ActiveRecord::Base + belongs_to :author + belongs_to :panel + belongs_to :sheet + + validates :sheet_id, :presence => true, :numericality => true, :existence => {:both => false} + validates :panel_id, :presence => true, :numericality => true, :existence => {:both => false} + validates :author_id, :presence => true, :numericality => true, :existence => {:both => false} + validates :x, :presence => true, :numericality => true + validates :y, :presence => true, :numericality => true + validates :z, :presence => true, :numericality => {:greater_than => 0} + validates :t, :presence => true, :numericality => {:greater_than_or_equal_to => 0} + + def supply_default + self.sheet_id = nil + self.panel_id = nil + self.t = nil + end + + def overwrite au + return false unless au + self.author_id = au.id + end + + def own? roles + roles = [roles] unless roles.respond_to?(:each) + au = SheetPanel.get_author_from_roles roles + return false unless au + self.author_id == au.id + end + + def visible? roles + if MagicNumber['run_mode'] == 0 + return false unless guest_role_check(roles) + else + return false unless reader_role_check(roles) + end + return true if self.sheet.own?(roles) + self.sheet.visible? roles + end + + def self.default_panel_size + 30 + end + + def self.max_panel_size + 200 + end + + def self.offset cnt, prm = nil + offset = prm.to_i + offset = cnt - 1 if offset >= cnt + offset = cnt - offset.abs if offset < 0 + offset = 0 if offset < 0 + offset + end + + def self.panel_count cnt, prm = self.default_panel_size + count = prm.to_i + count = self.max_panel_size if count > self.max_panel_size + count = self.default_panel_size if count < 1 + count + end + + def self.default_page_size + 25 + end + + def self.max_page_size + 100 + end + + def self.page prm = nil + page = prm.to_i + page = 1 if page < 1 + page + end + + def self.page_size prm = self.default_page_size + page_size = prm.to_i + page_size = self.max_page_size if page_size > self.max_page_size + page_size = self.default_page_size if page_size < 1 + page_size + end + + def self.play_list_where cid + ['sheet_panels.sheet_id = ?', cid] + end + + def self.list_where + 'sheets.visible > 0' + end + + def self.mylist_where au + ['sheet_panels.author_id = ?', au.id] + end + + def self.himlist_where au + ['sheet_panels.author_id = ? and sheets.visible > 0', au.id] + end + + def self.play_list sheet, author, offset = 0, limit = SheetPanel.default_panel_size + SheetPanel.where(self.play_list_where(sheet.id)).includes(SheetPanel.list_opt).order('sheet_panels.t').offset(offset).limit(limit) + end + + def self.list page = 1, page_size = self.default_page_size + SheetPanel.where(self.list_where()).includes(SheetPanel.list_opt).order('sheet_panels.updated_at desc').offset((page -1) * page_size).limit(page_size) + end + + def self.mylist au, page = 1, page_size = Author.default_sheet_panel_page_size + SheetPanel.where(self.mylist_where(au)).includes(SheetPanel.list_opt).order('sheet_panels.updated_at desc').offset((page -1) * page_size).limit(page_size) + end + + def self.himlist au, page = 1, page_size = Author.default_sheet_panel_page_size + SheetPanel.where(self.himlist_where(au)).includes(SheetPanel.list_opt).order('sheet_panels.updated_at desc').offset((page -1) * page_size).limit(page_size) + end + + def self.list_paginate page = 1, page_size = self.default_page_size + Kaminari.paginate_array(Array.new(SheetPanel.where(self.list_where()).includes(SheetPanel.list_opt).count, nil)).page(page).per(page_size) + end + + def self.mylist_paginate au, page = 1, page_size = Author.default_sheet_panel_page_size + Kaminari.paginate_array(Array.new(SheetPanel.where(self.mylist_where(au)).includes(SheetPanel.list_opt).count, nil)).page(page).per(page_size) + end + + def self.himlist_paginate au, page = 1, page_size = Author.default_sheet_panel_page_size + Kaminari.paginate_array(Array.new(SheetPanel.where(self.himlist_where(au)).includes(SheetPanel.list_opt).count, nil)).page(page).per(page_size) + end + + def self.list_opt + { + :author => {}, + :sheet => { + :author => {} + }, + :panel => { + :author => {}, + :panel_pictures => {:picture => {:artist => {}, :license => {}}}, + :speech_balloons =>{:balloon => {}, :speech => {}} + } + } + end + + def self.list_json_opt + {:include => { + :author => {}, + :sheet => { + :author => {} + }, + :panel => { + :author => {}, + :panel_pictures => {:picture => {:artist => {}, :license => {}}}, + :speech_balloons =>{:balloon => {}, :speech => {}} + } + }} + end + + def self.show spid, roles + opt = {} + opt.merge!(SheetPanel.show_opt) + res = SheetPanel.find spid, opt + raise ActiveRecord::Forbidden unless res.visible?(roles) + res + end + + def self.edit spid, au + opt = {} + opt.merge!(SheetPanel.show_opt) + res = SheetPanel.find spid, opt + raise ActiveRecord::Forbidden unless res.own?(au) + res + end + + def self.show_opt + {:include => { + :author => {}, + :sheet => { + :author => {} + }, + :panel => { + :author => {}, + :panel_pictures => {:picture => {:artist => {}, :license => {}}}, + :speech_balloons =>{:balloon => {}, :speech => {}} + } + }} + end + + def elements + self.panel.elements + end + + def sheet_panel_as_json au + panel_include = if self.panel and self.panel.visible?(au) + {:include => {:author => {}}, :methods => :elements} + else + {:include => {:author => {}}} + end + self.to_json({:include => {:sheet => {:include => {:author => {}}}, :author => {}, :panel => panel_include}}) + end + + def self.list_as_json_text ary, au + '[' + ary.map {|i| i.sheet_panel_as_json(au) }.join(',') + ']' + end + + def self.licensed_pictures sheet_panels + r = {} + sheet_panels.each do |sheet_panel| + r.merge!(sheet_panel.panel.licensed_pictures) if sheet_panel.panel + end + r + end + + def self.new_t sheet_id + r = SheetPanel.max_t(sheet_id) + r.blank? ? 0 : r.to_i + 1 + end + + def self.max_t sheet_id + SheetPanel.maximum(:t, :conditions => ['sheet_id = ?', sheet_id]) + end + + def self.find_t sheet_id, t + SheetPanel.find(:first, :conditions => ['sheet_id = ? and t = ?', sheet_id, t]) + end + + def self.collect_t sheet_panel + r = SheetPanel.find(:all, :conditions => ['sheet_id = ?', sheet_panel.sheet_id], :order => 't') + r.map {|sp| sp.t} + end + + def self.serial? ary + i = 0 + ary.compact.sort.each do |t| + break false unless t == i + i += 1 + end + ary.compact.size == i + end + + def self.validate_t sheet_panel + SheetPanel.serial?(SheetPanel.collect_t(sheet_panel)) + end + + def insert_shift + SheetPanel.update_all('t = t + 1', ['sheet_id = ? and t >= ?', self.sheet_id, self.t]) + end + + def lesser_shift old_t + self.t = 0 if self.t < 0 + SheetPanel.update_all('t = t + 1', ['sheet_id = ? and (t >= ? and t < ?)', self.sheet_id, self.t, old_t]) + end + + def higher_shift old_t + nf = SheetPanel.find_t(self.sheet_id, self.t) + max_t = SheetPanel.max_t(self.sheet_id).to_i + self.t = max_t if self.t > max_t + SheetPanel.update_all('t = t - 1', ['sheet_id = ? and (t > ? and t <= ?)', self.sheet_id, old_t, self.t]) + end + + def update_shift old_t + if self.t > old_t + higher_shift old_t + else + lesser_shift old_t + end + end + + def rotate old_t = nil + if self.new_record? + if self.t.blank? + self.t = SheetPanel.new_t self.sheet_id + else + self.insert_shift + end + else + if self.t.blank? + else + self.update_shift old_t + end + end + end + + def allow? + return nil if self.sheet_id == nil or self.panel_id == nil + self.sheet.own?(self.author) and self.panel.usable?(self.author) + end + + def store old_t = nil + res = false + SheetPanel.transaction do + case self.allow? + when true + self.rotate old_t + when false + raise ActiveRecord::Forbidden + else + end + res = self.save + raise ActiveRecord::Rollback unless res + res = SheetPanel.validate_t(self) + unless res + self.errors.add :t, 'unserialized' + raise ActiveRecord::Rollback + end + end + res + end + + def destroy_and_shorten + res = false + SheetPanel.transaction do + SheetPanel.update_all('t = t - 1', ['sheet_id = ? and (t > ?)', self.sheet_id, self.t]) + raise ActiveRecord::Rollback unless self.destroy + res = true + end + res + end + +end diff --git a/app/models/story.rb b/app/models/story.rb index 7f646f85..b655b67b 100644 --- a/app/models/story.rb +++ b/app/models/story.rb @@ -1,3 +1,269 @@ #ストーリー class Story < ActiveRecord::Base + belongs_to :author + has_many :story_sheets + belongs_to :comic + + validates :comic_id, :presence => true, :numericality => true, :existence => {:both => false} + validates :title, :presence => true, :length => {:maximum => 100} + validates :visible, :presence => true, :numericality => true, :inclusion => {:in => 0..1} + validates :author_id, :presence => true, :numericality => true, :existence => {:both => false} + validates :t, :presence => true, :numericality => {:greater_than_or_equal_to => 0} + before_validation :valid_encode + + def valid_encode + ['title', 'description'].each do |a| + next if attributes[a] == nil + raise Pettanr::BadRequest unless attributes[a].valid_encoding? + end + end + + def supply_default + self.comic_id = nil + self.visible = 0 if self.visible.blank? + self.t = nil + end + + def overwrite au + return false unless au + self.author_id = au.id + end + + def own? roles + roles = [roles] unless roles.respond_to?(:each) + au = Story.get_author_from_roles roles + return false unless au + self.author_id == au.id + end + + def visible? roles + if MagicNumber['run_mode'] == 0 + return false unless guest_role_check(roles) + else + return false unless reader_role_check(roles) + end + return true if self.own?(roles) + self.visible > 0 + end + + def self.default_page_size + 25 + end + + def self.max_page_size + 100 + end + + def self.default_panel_size + 30 + end + + def self.max_panel_size + 200 + end + + def self.page prm = nil + page = prm.to_i + page = 1 if page < 1 + page + end + + def self.page_size prm = self.default_page_size + page_size = prm.to_i + page_size = self.max_page_size if page_size > self.max_page_size + page_size = self.default_page_size if page_size < 1 + page_size + end + + def self.list_where + 'stories.visible > 0' + end + + def self.mylist_where au + ['stories.author_id = ?', au.id] + end + + def self.himlist_where au + ['stories.author_id = ? and stories.visible > 0', au.id] + end + + def self.list page = 1, page_size = self.default_page_size + Story.where(self.list_where()).includes(Story.list_opt).order('stories.updated_at desc').offset((page -1) * page_size).limit(page_size) + end + + def self.mylist au, page = 1, page_size = Author.default_story_page_size + Story.where(self.mylist_where(au)).includes(Story.list_opt).order('stories.updated_at desc').offset((page -1) * page_size).limit(page_size) + end + + def self.himlist au, page = 1, page_size = Author.default_story_page_size + Story.where(self.himlist_where(au)).includes(Story.list_opt).order('stories.updated_at desc').offset((page -1) * page_size).limit(page_size) + end + + def self.list_paginate page = 1, page_size = self.default_page_size + Kaminari.paginate_array(Array.new(Story.where(self.list_where()).count, nil)).page(page).per(page_size) + end + + def self.mylist_paginate au, page = 1, page_size = Author.default_story_page_size + Kaminari.paginate_array(Array.new(Story.where(self.mylist_where(au)).count, nil)).page(page).per(page_size) + end + + def self.himlist_paginate au, page = 1, page_size = Author.default_story_page_size + Kaminari.paginate_array(Array.new(Story.where(self.himlist_where(au)).count, nil)).page(page).per(page_size) + end + + def self.list_opt + {:author => {}, :story_sheets => {:sheet => {}, :author => {}} } + end + + def self.list_json_opt + {:include => {:author => {}, :story_sheets => {:include => {:sheet => {}, :author => {}}} }} + end + + def self.show sid, roles + opt = {} + opt.merge!(Story.show_opt) + res = Story.find(sid, opt) + raise ActiveRecord::Forbidden unless res.visible?(roles) + res + end + + def self.edit sid, au + opt = {} + opt.merge!(Story.show_opt) + res = Story.find(sid, opt) + raise ActiveRecord::Forbidden unless res.own?(au) + res + end + + def self.show_opt + {:include => {:author => {}, :story_sheets => {:sheet => {}, :author => {}} }} + end + + def self.show_json_opt + {:include => {:author => {}, :story_sheets => {:include => {:sheet => {}, :author => {}}} }} + end + + def self.visible_count + Story.count 'visible > 0' + end + + def destroy_with_story_sheet + res = false + Story.transaction do + self.story_sheets.each do |story_sheet| + raise ActiveRecord::Rollback unless story_sheet.destroy + end + raise ActiveRecord::Rollback unless self.destroy + res = true + end + res + end + + def self.new_t comic_id + r = Story.max_t(comic_id) + r.blank? ? 0 : r.to_i + 1 + end + + def self.max_t comic_id + Story.maximum(:t, :conditions => ['comic_id = ?', comic_id]) + end + + def self.find_t comic_id, t + Story.find(:first, :conditions => ['comic_id = ? and t = ?', comic_id, t]) + end + + def self.collect_t story + r = Story.find(:all, :conditions => ['comic_id = ?', story.comic_id], :order => 't') + r.map {|s| s.t} + end + + def self.serial? ary + i = 0 + ary.compact.sort.each do |t| + break false unless t == i + i += 1 + end + ary.compact.size == i + end + + def self.validate_t story + Story.serial?(Story.collect_t(story)) + end + + def insert_shift + Story.update_all('t = t + 1', ['comic_id = ? and t >= ?', self.comic_id, self.t]) + end + + def lesser_shift old_t + self.t = 0 if self.t < 0 + Story.update_all('t = t + 1', ['comic_id = ? and (t >= ? and t < ?)', self.comic_id, self.t, old_t]) + end + + def higher_shift old_t + nf = Story.find_t(self.comic_id, self.t) + max_t = Story.max_t(self.comic_id).to_i + self.t = max_t if self.t > max_t + Story.update_all('t = t - 1', ['comic_id = ? and (t > ? and t <= ?)', self.comic_id, old_t, self.t]) + end + + def update_shift old_t + if self.t > old_t + higher_shift old_t + else + lesser_shift old_t + end + end + + def rotate old_t = nil + if self.new_record? + if self.t.blank? + self.t = Story.new_t self.comic_id + else + self.insert_shift + end + else + if self.t.blank? + else + self.update_shift old_t + end + end + end + + def allow? + return nil if self.comic_id == nil + self.comic.own?(self.author) + end + + def store old_t = nil + res = false + Story.transaction do + case self.allow? + when true + self.rotate old_t + when false + raise ActiveRecord::Forbidden + else + end + res = self.save + raise ActiveRecord::Rollback unless res + res = Story.validate_t(self) + unless res + self.errors.add :t, 'unserialized' + raise ActiveRecord::Rollback + end + end + res + end + + def destroy_and_shorten + res = false + Story.transaction do + Story.update_all('t = t - 1', ['comic_id = ? and (t > ?)', self.comic_id, self.t]) + raise ActiveRecord::Rollback unless self.destroy_with_story_sheet + res = true + end + res + end + + end diff --git a/app/models/story_sheet.rb b/app/models/story_sheet.rb new file mode 100644 index 00000000..f988d296 --- /dev/null +++ b/app/models/story_sheet.rb @@ -0,0 +1,289 @@ +class StorySheet < ActiveRecord::Base + belongs_to :author + belongs_to :story + belongs_to :sheet + + validates :story_id, :presence => true, :numericality => true, :existence => {:both => false} + validates :sheet_id, :presence => true, :numericality => true, :existence => {:both => false} + validates :author_id, :presence => true, :numericality => true, :existence => {:both => false} + validates :t, :presence => true, :numericality => {:greater_than_or_equal_to => 0} + + def supply_default + self.story_id = nil + self.sheet_id = nil + self.t = nil + end + + def overwrite au + return false unless au + self.author_id = au.id + end + + def own? roles + roles = [roles] unless roles.respond_to?(:each) + au = StorySheet.get_author_from_roles roles + return false unless au + self.author_id == au.id + end + + def visible? roles + if MagicNumber['run_mode'] == 0 + return false unless guest_role_check(roles) + else + return false unless reader_role_check(roles) + end + return true if self.story.own?(roles) + self.story.visible? roles + end + + def self.default_sheet_size + 30 + end + + def self.max_sheet_size + 200 + end + + def self.offset cnt, prm = nil + offset = prm.to_i + offset = cnt - 1 if offset >= cnt + offset = cnt - offset.abs if offset < 0 + offset = 0 if offset < 0 + offset + end + + def self.sheet_count cnt, prm = self.default_sheet_size + count = prm.to_i + count = self.max_sheet_size if count > self.max_sheet_size + count = self.default_sheet_size if count < 1 + count + end + + def self.default_page_size + 25 + end + + def self.max_page_size + 100 + end + + def self.page prm = nil + page = prm.to_i + page = 1 if page < 1 + page + end + + def self.page_size prm = self.default_page_size + page_size = prm.to_i + page_size = self.max_page_size if page_size > self.max_page_size + page_size = self.default_page_size if page_size < 1 + page_size + end + + def self.play_list_where cid + ['story_sheets.story_id = ?', cid] + end + + def self.list_where + 'stories.visible > 0' + end + + def self.mylist_where au + ['story_sheets.author_id = ?', au.id] + end + + def self.himlist_where au + ['story_sheets.author_id = ? and stories.visible > 0', au.id] + end + + def self.play_list story, author, offset = 0, limit = StorySheet.default_sheet_size + StorySheet.where(self.play_list_where(story.id)).includes(StorySheet.list_opt).order('story_sheets.t').offset(offset).limit(limit) + end + + def self.list page = 1, page_size = self.default_page_size + StorySheet.where(self.list_where()).includes(StorySheet.list_opt).order('story_sheets.updated_at desc').offset((page -1) * page_size).limit(page_size) + end + + def self.mylist au, page = 1, page_size = Author.default_story_sheet_page_size + StorySheet.where(self.mylist_where(au)).includes(StorySheet.list_opt).order('story_sheets.updated_at desc').offset((page -1) * page_size).limit(page_size) + end + + def self.himlist au, page = 1, page_size = Author.default_story_sheet_page_size + StorySheet.where(self.himlist_where(au)).includes(StorySheet.list_opt).order('story_sheets.updated_at desc').offset((page -1) * page_size).limit(page_size) + end + + def self.list_paginate page = 1, page_size = self.default_page_size + Kaminari.paginate_array(Array.new(StorySheet.where(self.list_where()).includes(StorySheet.list_opt).count, nil)).page(page).per(page_size) + end + + def self.mylist_paginate au, page = 1, page_size = Author.default_story_sheet_page_size + Kaminari.paginate_array(Array.new(StorySheet.where(self.mylist_where(au)).includes(StorySheet.list_opt).count, nil)).page(page).per(page_size) + end + + def self.himlist_paginate au, page = 1, page_size = Author.default_story_sheet_page_size + Kaminari.paginate_array(Array.new(StorySheet.where(self.himlist_where(au)).includes(StorySheet.list_opt).count, nil)).page(page).per(page_size) + end + + def self.list_opt + { + :author => {}, + :story => { + :author => {} + }, + :sheet => { + :author => {}, + } + } + end + + def self.list_json_opt + {:include => { + :author => {}, + :story => {:include => {:author => {}}} , + :sheet => {:include => {:author => {}}} + }} + end + + def self.show spid, roles + opt = {} + opt.merge!(StorySheet.show_opt) + res = StorySheet.find spid, opt + raise ActiveRecord::Forbidden unless res.visible?(roles) + res + end + + def self.edit spid, au + opt = {} + opt.merge!(StorySheet.show_opt) + res = StorySheet.find spid, opt + raise ActiveRecord::Forbidden unless res.own?(au) + res + end + + def self.show_opt + {:include => { + :author => {}, + :story => { + :author => {} + }, + :sheet => { + :author => {} + } + }} + end + + def self.show_json_opt + {:include => { + :author => {}, + :story => {:include => {:author => {}}} , + :sheet => {:include => {:author => {}}} + }} + end + + def self.new_t story_id + r = StorySheet.max_t(story_id) + r.blank? ? 0 : r.to_i + 1 + end + + def self.max_t story_id + StorySheet.maximum(:t, :conditions => ['story_id = ?', story_id]) + end + + def self.find_t story_id, t + StorySheet.find(:first, :conditions => ['story_id = ? and t = ?', story_id, t]) + end + + def self.collect_t story_sheet + r = StorySheet.find(:all, :conditions => ['story_id = ?', story_sheet.story_id], :order => 't') + r.map {|sp| sp.t} + end + + def self.serial? ary + i = 0 + ary.compact.sort.each do |t| + break false unless t == i + i += 1 + end + ary.compact.size == i + end + + def self.validate_t story_sheet + StorySheet.serial?(StorySheet.collect_t(story_sheet)) + end + + def insert_shift + StorySheet.update_all('t = t + 1', ['story_id = ? and t >= ?', self.story_id, self.t]) + end + + def lesser_shift old_t + self.t = 0 if self.t < 0 + StorySheet.update_all('t = t + 1', ['story_id = ? and (t >= ? and t < ?)', self.story_id, self.t, old_t]) + end + + def higher_shift old_t + nf = StorySheet.find_t(self.story_id, self.t) + max_t = StorySheet.max_t(self.story_id).to_i + self.t = max_t if self.t > max_t + StorySheet.update_all('t = t - 1', ['story_id = ? and (t > ? and t <= ?)', self.story_id, old_t, self.t]) + end + + def update_shift old_t + if self.t > old_t + higher_shift old_t + else + lesser_shift old_t + end + end + + def rotate old_t = nil + if self.new_record? + if self.t.blank? + self.t = StorySheet.new_t self.story_id + else + self.insert_shift + end + else + if self.t.blank? + else + self.update_shift old_t + end + end + end + + def allow? + return nil if self.story_id == nil or self.sheet_id == nil + self.story.own?(self.author) and self.sheet.usable?(self.author) + end + + def store old_t = nil + res = false + StorySheet.transaction do + case self.allow? + when true + self.rotate old_t + when false + raise ActiveRecord::Forbidden + else + end + res = self.save + raise ActiveRecord::Rollback unless res + res = StorySheet.validate_t(self) + unless res + self.errors.add :t, 'unserialized' + raise ActiveRecord::Rollback + end + end + res + end + + def destroy_and_shorten + res = false + StorySheet.transaction do + StorySheet.update_all('t = t - 1', ['story_id = ? and (t > ?)', self.story_id, self.t]) + raise ActiveRecord::Rollback unless self.destroy + res = true + end + res + end + +end diff --git a/app/views/comics/_form.html.erb b/app/views/comics/_form.html.erb new file mode 100644 index 00000000..84b983cc --- /dev/null +++ b/app/views/comics/_form.html.erb @@ -0,0 +1,23 @@ +<%= form_for(@comic) do |f| %> + <%= render 'system/error_explanation', :obj => @comic %> + +
+ <%= f.label :title %>
+ <%= f.text_field :title %> +
+
+ <%= f.label :description %>
+ <%= f.text_area :description %> +
+
+ <%= f.label :visible %>
+ <%= f.collection_select :visible, t_select_items(MagicNumber['comic_visible_items']), :last, :first, :html => {:selected => @comic.visible} %> +
+
+ <%= f.label :author_id %>
+ <%= h @author.name %> +
+
+ <%= f.submit %> +
+<% end %> diff --git a/app/views/comics/_list_item.html.erb b/app/views/comics/_list_item.html.erb new file mode 100644 index 00000000..2e9d719a --- /dev/null +++ b/app/views/comics/_list_item.html.erb @@ -0,0 +1,25 @@ + + + <%= link_to comic_icon(:object => comic, :size => 25), comic_path(comic) %> + <%= link_to h(truncate(comic.title, :length => 40)), :controller => 'stories', :action => :comic, :id => comic.id %> + (<%= comic.stories.size -%>) + + + <%= distance_of_time_in_words_to_now comic.updated_at %> + + + <%= link_to author_icon(:object => comic.author, :size => 25), comic_path(comic.author) %> + <%= link_to h(truncate(comic.author.name, :length => 12)), author_path(comic.author) %> + + + <% if comic.own? author %> + <%= link_to t('link.edit'), edit_comic_path(comic) %> + <%= link_to t('link.destroy'), comic_path(comic), :method => :delete %> + <% end %> + + + + + <%= h(truncate(comic.description, :length => 40)) %> + + diff --git a/app/views/comics/browse.html.erb b/app/views/comics/browse.html.erb new file mode 100644 index 00000000..c93e6224 --- /dev/null +++ b/app/views/comics/browse.html.erb @@ -0,0 +1,34 @@ +

<%= t '.title' -%>

+

+ <%= t_m 'Comic.id' -%>: + <%= h @comic.id %> +

+ +

+ <%= t_m 'Comic.title' -%>: + <%= h @comic.title %> +

+ +

+ <%= t_m 'Comic.visible' -%>: + <%= @comic.visible %> + <%= t_selected_item('comic_visible_items', @comic.visible) %> +

+ +

+ <%= t_m 'Comic.author_id' -%>: + <%= @comic.author_id %> + <%= link_to h(@comic.author.name), browse_author_path(@comic.author) %> +

+ +

+ <%= t_m 'Comic.created_at' -%>: + <%= l @comic.created_at %> +

+ +

+ <%= t_m 'Comic.updated_at' -%>: + <%= l @comic.updated_at %> +

+ +<%= link_to t('link.back'), :action => :list %> diff --git a/app/views/comics/edit.html.erb b/app/views/comics/edit.html.erb new file mode 100644 index 00000000..1d67f75e --- /dev/null +++ b/app/views/comics/edit.html.erb @@ -0,0 +1,4 @@ +

<%= t('.title') %>

+

<%= notice %>

+ +<%= render 'form' %> diff --git a/app/views/comics/edit.js.erb b/app/views/comics/edit.js.erb new file mode 100644 index 00000000..ab2a7d24 --- /dev/null +++ b/app/views/comics/edit.js.erb @@ -0,0 +1 @@ +$("#newcomic").html("<%= escape_javascript(render('form')) -%>"); diff --git a/app/views/comics/index.atom.builder b/app/views/comics/index.atom.builder new file mode 100644 index 00000000..a1e9b0c0 --- /dev/null +++ b/app/views/comics/index.atom.builder @@ -0,0 +1,25 @@ +atom_feed( + :language => 'ja-JP', + :root_url => root_url, + :url => root_url(:format => :atom), + :id => root_url +) do |feed| + feed.title MagicNumber['profile']['users']['caption'] + feed.subtitle sanitize(MagicNumber['profile']['users']['description'], :tags => %w(a p img br)) + feed.updated Time.now + feed.author {|author| author.name(MagicNumber['profile']['web_master'])} + + @comics.each do |comic| + feed.entry( + comic, + :url => comic_url(comic), + :id => comic_url(comic), + :published => comic.updated_at, + :updated => comic.updated_at + ) do |item| + item.title(comic.title) + item.content(comic.description, :type => 'html') + item.author {|author| author.name(comic.author.name)} + end + end +end diff --git a/app/views/comics/index.html.erb b/app/views/comics/index.html.erb new file mode 100644 index 00000000..cef2ab93 --- /dev/null +++ b/app/views/comics/index.html.erb @@ -0,0 +1,9 @@ +

<%= t '.title' -%>

+ + + <% @comics.each do |comic| %> + <%= render 'list_item', :comic => comic, :author => @author %> + <% end %> +
+<%= paginate(@paginate) %> +<%= link_to t('comics.new.title'), new_comic_path %> diff --git a/app/views/comics/index.rss.builder b/app/views/comics/index.rss.builder new file mode 100644 index 00000000..b319a9d0 --- /dev/null +++ b/app/views/comics/index.rss.builder @@ -0,0 +1,24 @@ +xml.instruct! + +xml.rss("version" => "2.0", + "xmlns:dc" => "http://purl.org/dc/elements/1.1/", + "xmlns:atom" => "http://www.w3.org/2005/Atom") do + xml.channel do + xml.title MagicNumber['profile']['users']['caption'] + xml.link root_url + xml.pubDate Time.now.rfc822 + xml.description sanitize(MagicNumber['profile']['users']['description'], :tags => %w(a p img br)) + xml.atom :link, "href" => @rss_url, "rel" => "self", "type" => "application/rss+xml" + + @comics.each do |comic| + xml.item do + xml.title comic.title + xml.link comic_url(comic) + xml.guid comic_url(comic) + xml.description comic.description + xml.pubDate comic.updated_at.to_formatted_s(:rfc822) + xml.dc :creator, comic.author.name + end + end + end +end diff --git a/app/views/comics/list.html.erb b/app/views/comics/list.html.erb new file mode 100644 index 00000000..43fdf7e5 --- /dev/null +++ b/app/views/comics/list.html.erb @@ -0,0 +1,24 @@ +

<%= t '.title' -%>

+ + + + + + + + + + + +<% @comics.each do |comic| %> + + + + + + + + +<% end %> +
<%= t_m 'Comic.id' -%><%= t_m 'Comic.title' -%><%= t_m 'Comic.visible' -%><%= t_m 'Comic.author_id' -%><%= t_m 'Comic.created_at' -%><%= t_m 'Comic.updated_at' -%>
<%= link_to comic.id, browse_comic_path(comic) %><%= h(truncate(comic.title, :length => 12)) %><%= comic.visible %><%= link_to comic.author_id, browse_author_path(comic.author) %><%= l comic.created_at %><%= l comic.updated_at %>
+ diff --git a/app/views/comics/new.html.erb b/app/views/comics/new.html.erb new file mode 100644 index 00000000..7142b57d --- /dev/null +++ b/app/views/comics/new.html.erb @@ -0,0 +1,5 @@ +

<%= t('.title') %>

+ +<%= render 'form' %> + +<%= link_to t('link.back'), comics_path %> diff --git a/app/views/comics/new.js.erb b/app/views/comics/new.js.erb new file mode 100644 index 00000000..ab2a7d24 --- /dev/null +++ b/app/views/comics/new.js.erb @@ -0,0 +1 @@ +$("#newcomic").html("<%= escape_javascript(render('form')) -%>"); diff --git a/app/views/comics/show.atom.builder b/app/views/comics/show.atom.builder new file mode 100644 index 00000000..6f5c967f --- /dev/null +++ b/app/views/comics/show.atom.builder @@ -0,0 +1,25 @@ +atom_feed( + :language => 'ja-JP', + :root_url => root_url, + :url => root_url(:format => :atom), + :id => root_url +) do |feed| + feed.title MagicNumber['profile']['users']['caption'] + feed.subtitle sanitize(MagicNumber['profile']['users']['description'], :tags => %w(a p img br)) + feed.updated Time.now + feed.author {|author| author.name(MagicNumber['profile']['web_master'])} + + @comic.stories.each do |story| + feed.entry( + story.panel, + :url => panel_url(story.panel), + :id => panel_url(story.panel), + :published => story.panel.updated_at, + :updated => story.panel.updated_at + ) do |item| + item.title(story.panel.caption) + item.content(story.panel.scenario, :type => 'html') + item.author {|author| author.name(story.panel.author.name)} + end + end +end diff --git a/app/views/comics/show.html.erb b/app/views/comics/show.html.erb new file mode 100644 index 00000000..81a1bbf3 --- /dev/null +++ b/app/views/comics/show.html.erb @@ -0,0 +1,35 @@ +<% @page_title = t('.title') + ':' + @comic.title %> +

<%= t('.title') %>

+

<%= notice %>

+ +

+ <%= t_m 'Comic.title' -%>: + <%= link_to h(@comic.title), :controller => 'stories', :action => :comic, :id => @comic.id %> +

+ +

+ <%= t_m 'Comic.description' -%>: + <%= h(@comic.description) %> +

+ +

+ <%= t_m 'Comic.visible' -%>: + <%= t_selected_item('comic_visible_items', @comic.visible) %> +

+ +

+ <%= t_m 'Comic.author_id' -%>: + <%= link_to h(@comic.author.name), author_path(@comic.author) %> +

+ +

+ <%= t_m 'Comic.created_at' -%>: + <%= l @comic.created_at %> +

+ +

+ <%= t_m 'Comic.updated_at' -%>: + <%= l @comic.updated_at %> +

+ +<%= link_to t('link.edit'), edit_comic_path(@comic) %> diff --git a/app/views/comics/show.rss.builder b/app/views/comics/show.rss.builder new file mode 100644 index 00000000..553f344f --- /dev/null +++ b/app/views/comics/show.rss.builder @@ -0,0 +1,24 @@ +xml.instruct! + +xml.rss("version" => "2.0", + "xmlns:dc" => "http://purl.org/dc/elements/1.1/", + "xmlns:atom" => "http://www.w3.org/2005/Atom") do + xml.channel do + xml.title MagicNumber['profile']['users']['caption'] + xml.link root_url + xml.pubDate Time.now.rfc822 + xml.description sanitize(MagicNumber['profile']['users']['description'], :tags => %w(a p img br)) + xml.atom :link, "href" => @rss_url, "rel" => "self", "type" => "application/rss+xml" + + @comic.stories.each do |story| + xml.item do + xml.title story.panel.caption + xml.link panel_url(story.panel) + xml.guid panel_url(story.panel) + xml.description story.panel.plain_scenario + xml.pubDate story.panel.updated_at.to_formatted_s(:rfc822) + xml.dc :creator, story.panel.author.name + end + end + end +end diff --git a/app/views/stories/_append_panel.html.erb b/app/views/stories/_append_panel.html.erb new file mode 100644 index 00000000..241bcf84 --- /dev/null +++ b/app/views/stories/_append_panel.html.erb @@ -0,0 +1,21 @@ + + + <%= link_to panel_icon(:object => panel, :size => 25), panel_path(panel) %> + <%= link_to author_icon(:object => panel.author, :size => 17), author_path(panel.author) %> + + + <%= link_to h(truncate(h(panel.caption), :length => 40)), :controller => 'stories', :action => :comic, :id => comic.id %> + + + <%= l panel.updated_at %> + + + <% @story = Story.new :comic_id => comic.id, :panel_id => panel.id -%> + <%= form_for(@story) do |f| %> + <%= f.hidden_field :comic_id %> + <%= f.hidden_field :t %> + <%= f.hidden_field :panel_id %> + <%= f.submit t('stories.comic.append') %> + <% end %> + + diff --git a/app/views/stories/_comic_header.html.erb b/app/views/stories/_comic_header.html.erb new file mode 100644 index 00000000..d1eb9e77 --- /dev/null +++ b/app/views/stories/_comic_header.html.erb @@ -0,0 +1,40 @@ +

+ <%= link_to comic_icon, comic_path(comic) %> + <%= link_to h(comic.title), :controller => 'stories', :action => :comic, :id => comic.id %> +

+<% if comic.own? author -%> + <%= form_for(comic) do |f| %> +
+ <%= f.label :title %>
+ <%= f.text_field :title %> +
+
+ <%= f.label :visible %>
+ <%= f.collection_select :visible, t_select_items(MagicNumber['comic_visible_items']), :last, :first, :html => {:selected => @comic.visible} %> +
+
+ <%= f.submit %> +
+ <% end %> +<% else %> +

+ <%= t_m 'Comic.visible' -%>: + <%= t_selected_item('comic_visible_items', @comic.visible) %> +

+<% end %> + +

+ <%= t_m 'Comic.author_id' -%>: + <%= link_to h(@comic.author.name), author_path(@comic.author) %> +

+ +

+ <%= t_m 'Comic.created_at' -%>: + <%= l @comic.created_at %> +

+ +

+ <%= t_m 'Comic.updated_at' -%>: + <%= l @comic.updated_at %> +

+ diff --git a/app/views/stories/_footer.html.erb b/app/views/stories/_footer.html.erb new file mode 100644 index 00000000..56e93674 --- /dev/null +++ b/app/views/stories/_footer.html.erb @@ -0,0 +1,23 @@ + + + + + + +
+ <% if story.panel -%> + <%= link_to panel_icon(:object => story.panel, :size => 25), panel_path(story.panel) %> + <%= link_to author_icon(:object => story.panel.author, :size => 17), author_path(story.panel.author) %> + <%= distance_of_time_in_words_to_now story.panel.updated_at %> + <% end %> + + <%= link_to story_icon(:object => story, :size => 25), story_path(story) %> + <%= link_to author_icon(:object => story.author, :size => 17), author_path(story.author) %> + <%= l story.updated_at %> + + <% if story.own? author %> + <%= render 'order', :story => story %> + <% else %> + No.<%= story.t %> + <% end %> +
diff --git a/app/views/stories/_form.html.erb b/app/views/stories/_form.html.erb new file mode 100644 index 00000000..8d705f58 --- /dev/null +++ b/app/views/stories/_form.html.erb @@ -0,0 +1,20 @@ +<%= form_for(@story) do |f| %> + <%= render 'system/error_explanation', :obj => @story %> + +
+ <%= f.label :comic_id %>
+ <%= f.number_field :comic_id %> +
+
+ <%= f.label :t %>
+ <%= f.number_field :t %> +
+
+ <%= f.label :panel_id %>
+ <%= f.number_field :panel_id %> +
+ +
+ <%= f.submit %> +
+<% end %> diff --git a/app/views/stories/_licensed_pictures.html.erb b/app/views/stories/_licensed_pictures.html.erb new file mode 100644 index 00000000..1c10cc72 --- /dev/null +++ b/app/views/stories/_licensed_pictures.html.erb @@ -0,0 +1,14 @@ +
+ <% licensed_pictures.each do |pid, picture| %> + + + + + +
+ <%= link_to(tag(:img, picture.tmb_opt_img_tag), picture_path(picture.id)) -%> + + <%= render picture.credit_template, :picture => picture %> +
+ <% end %> +
diff --git a/app/views/stories/_list_item.html.erb b/app/views/stories/_list_item.html.erb new file mode 100644 index 00000000..1b18f0fc --- /dev/null +++ b/app/views/stories/_list_item.html.erb @@ -0,0 +1,28 @@ + + + <%= link_to comic_icon(:object => story.comic, :size => 25), comic_path(story.comic) %> + + + <%= link_to h(story.comic.title), :controller => 'stories', :action => :comic, :id => story.comic.id %> + + + <%= link_to author_icon(:object => story.comic.author, :size => 17), author_path(story.comic.author) %> + + + <%= link_to story_icon(:object => story, :size => 25), story_path(story) %> + + + <%= link_to author_icon(:object => story.author, :size => 17), author_path(story.author) %> + + + No.<%= story.t %> + + + <%= l story.updated_at %> + + + <% if story.panel %> + <%= h story.panel.caption %> + <% end %> + + diff --git a/app/views/stories/_order.html.erb b/app/views/stories/_order.html.erb new file mode 100644 index 00000000..e0ceadfe --- /dev/null +++ b/app/views/stories/_order.html.erb @@ -0,0 +1,15 @@ +<%= form_for(story) do |f| %> + + + + + +
+ No. + <%= f.number_field :t, :size => 3 %> + <%= f.hidden_field :panel_id %> + <%= f.hidden_field :comic_id %> + + <%= f.submit t 'stories.move' %> +
+<% end %> diff --git a/app/views/stories/browse.html.erb b/app/views/stories/browse.html.erb new file mode 100644 index 00000000..24a7a6ca --- /dev/null +++ b/app/views/stories/browse.html.erb @@ -0,0 +1,28 @@ +

<%= notice %>

+ +

+ comic_id: + <%= @story.comic_id %> +

+ +

+ panel_id: + <%= @story.panel_id %> +

+ +

+ t: + <%= @story.t %> +

+ +

+ author_id: + <%= @story.author_id %> +

+ +

+ updated_at: + <%= @story.updated_at %> +

+ +<%= link_to 'Back', :action => :list %> diff --git a/app/views/stories/comic.html.erb b/app/views/stories/comic.html.erb new file mode 100644 index 00000000..631f6f03 --- /dev/null +++ b/app/views/stories/comic.html.erb @@ -0,0 +1,33 @@ +<% @page_title = @comic.title %> +

<%= t '.title' -%>

+

<%= notice %>

+<%= render 'comic_header', :comic => @comic, :author => @author %> + +<% if @stories.empty? -%> +

<%= t('stories.comic.empty') %>

+<% else %> + <% @stories.each do |story| %> + <% if story.panel -%> + <%= render 'panels/body', :panel => story.panel, :author => @author, :spot => nil %> + <% end %> + <%= render 'footer', :story => story, :author => @author %> + <% end %> + <%= render 'licensed_pictures', :licensed_pictures => Story.licensed_pictures(@stories) %> + + <% if @prev_offset -%> + <%= link_to h('< @prev_offset, :count => @panel_count}) %> + <% end %> + + <% if @next_offset -%> + <%= link_to h('next>>'), comic_story_path(@comic, {:offset => @next_offset, :count => @panel_count}) %> + <% end %> + +<% end %> +<% if @comic.own? @author -%> +

<%= t('stories.comic.new_panels') -%>

+ + <% @new_panels.each do |panel| %> + <%= render 'append_panel', :comic => @comic, :panel => panel, :author => @author %> + <% end %> +
+<% end %> diff --git a/app/views/stories/edit.html.erb b/app/views/stories/edit.html.erb new file mode 100644 index 00000000..cee9463d --- /dev/null +++ b/app/views/stories/edit.html.erb @@ -0,0 +1,5 @@ +

<%= t('.title') %>

+

<%= notice %>

+ +<%= render 'form' %> +<%= button_to 'Destroy', @story.panel, confirm: 'Are you sure?', method: :delete %> diff --git a/app/views/stories/edit.js.erb b/app/views/stories/edit.js.erb new file mode 100644 index 00000000..29c687f7 --- /dev/null +++ b/app/views/stories/edit.js.erb @@ -0,0 +1 @@ +$("#story-update-<%= @story.id -%>").html("<%= escape_javascript(render('editform')) -%>"); diff --git a/app/views/stories/index.html.erb b/app/views/stories/index.html.erb new file mode 100644 index 00000000..7b61ab84 --- /dev/null +++ b/app/views/stories/index.html.erb @@ -0,0 +1,8 @@ +

<%= t '.title' -%>

+ + <% @stories.each do |story| %> + <%= render 'list_item', :story => story, :author => @author %> + <% end %> +
+<%= paginate(@paginate) %> +<%= link_to t('stories.new.title'), new_story_path %> diff --git a/app/views/stories/list.html.erb b/app/views/stories/list.html.erb new file mode 100644 index 00000000..6fae81c5 --- /dev/null +++ b/app/views/stories/list.html.erb @@ -0,0 +1,29 @@ +

Listing Story

+ + + + + + + + + + + + + +<% @stories.each do |story| %> + + + + + + + + + + +<% end %> +
idcomic_idpanel_idtauthor_idcreated_atupdated_at
<%= link_to story.id, :action => :browse, :id => story.id %><%= story.comic_id %><%= story.panel_id %><%= story.t %><%= link_to story.author_id, :controller => '/authors', :action => :browse, :id => story.author_id %><%= story.created_at %><%= story.updated_at %> +
+ diff --git a/app/views/stories/new.html.erb b/app/views/stories/new.html.erb new file mode 100644 index 00000000..f33a2f89 --- /dev/null +++ b/app/views/stories/new.html.erb @@ -0,0 +1,3 @@ +

<%= t('.title') %>

+ +<%= render 'form' %> diff --git a/app/views/stories/show.html.erb b/app/views/stories/show.html.erb new file mode 100644 index 00000000..fa0c3a0b --- /dev/null +++ b/app/views/stories/show.html.erb @@ -0,0 +1,41 @@ +

<%= t('.title') %>

+

<%= notice %>

+ +

+ <%= t_m 'Story.comic_id' -%>: + <%= link_to comic_icon(:object => @story.comic), comic_path(@story.comic) %> + <%= link_to h(@story.comic.title), :controller => 'stories', :action => :comic, :id => @story.comic.id %> +

+ +

+ <%= t_m 'Story.panel_id' -%>: + <%= link_to panel_icon(:object => @story.panel), panel_path(@story.panel) %> +

+ +

+ <%= t_m 'Story.t' -%>: + <%= @story.t %> +

+ +

+ <%= t_m 'Story.author_id' -%>: + <%= link_to author_icon(:object => @story.author), author_path(@story.author) %> + <%= link_to h(@story.author.name), author_path(@story.author) %> +

+ +

+ <%= t_m 'Story.created_at' -%>: + <%= l @story.created_at %> +

+ +

+ <%= t_m 'Story.updated_at' -%>: + <%= l @story.updated_at %> +

+<% if @story.own? @author -%> + <%= link_to t('link.edit'), edit_story_path(@story) %> + <%= link_to t('link.destroy'), story_path(@story), :method => :delete %> +<% end %> + +
+<%= render 'panels/standard', :panel => @story.panel, :author => @author %> diff --git a/config/routes.rb b/config/routes.rb index 97644709..48f61d0e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -55,6 +55,77 @@ Pettanr::Application.routes.draw do get :resource_pictures end end + resources :comics do + new do + get :new + end + collection do + get :index + get :show + get :count + post :create + get :list + end + member do + get :play + get :edit + put :update + delete :destroy + get :browse + end + end + resources :stories do + new do + get :new + end + collection do + get :index + get :show + post :create + get :list + end + member do + get :edit + put :update + delete :destroy + get :browse + end + end + resources :sheets do + new do + get :new + end + collection do + get :index + get :show + get :count + post :create + get :list + end + member do + get :edit + put :update + delete :destroy + get :browse + end + end + resources :sheet_panels do + new do + get :new + end + collection do + get :index + get :show + post :create + get :list + end + member do + get :edit + put :update + delete :destroy + get :browse + end + end resources :scrolls do new do get :new @@ -86,7 +157,6 @@ Pettanr::Application.routes.draw do end member do get :edit - get :scroll put :update delete :destroy get :browse diff --git a/db/migrate/20130914055043_create_sheets.rb b/db/migrate/20130914055043_create_sheets.rb new file mode 100644 index 00000000..af8eeb9a --- /dev/null +++ b/db/migrate/20130914055043_create_sheets.rb @@ -0,0 +1,13 @@ +class CreateSheets < ActiveRecord::Migration + def change + create_table :sheets do |t| + t.string :caption, :null => false, :limit => 100 + t.integer :width, :null => false, :default => 839 + t.integer :height, :null => false, :default => 1191 + t.integer :visible, :null => false, :default => 0 + t.integer :author_id, :null => false + + t.timestamps + end + end +end diff --git a/db/migrate/20130914055219_create_sheet_panels.rb b/db/migrate/20130914055219_create_sheet_panels.rb new file mode 100644 index 00000000..06797415 --- /dev/null +++ b/db/migrate/20130914055219_create_sheet_panels.rb @@ -0,0 +1,15 @@ +class CreateSheetPanels < ActiveRecord::Migration + def change + create_table :sheet_panels do |t| + t.integer :sheet_id, :null => false, :default => 0 + t.integer :panel_id, :null => false, :default => 0 + t.integer :author_id, :null => false, :default => 0 + t.integer :x + t.integer :y + t.integer :z, :null => false, :default => 0 + t.integer :t, :null => false, :default => 0 + + t.timestamps + end + end +end diff --git a/db/migrate/20130914061319_restruct_comic.rb b/db/migrate/20130914061319_restruct_comic.rb new file mode 100644 index 00000000..3e3838f7 --- /dev/null +++ b/db/migrate/20130914061319_restruct_comic.rb @@ -0,0 +1,27 @@ +class RestructComic < ActiveRecord::Migration + def up + drop_table :comics + create_table :comics do |t| + t.string :title, :null => false, :limit => 100 + t.integer :visible, :null => false, :default => 0 + t.text :description + t.integer :author_id, :null => false + + t.timestamps + end + drop_table :stories + create_table :stories do |t| + t.integer :comic_id, :null => false, :default => 0 + t.string :title, :null => false, :limit => 100 + t.integer :visible, :null => false, :default => 0 + t.text :description + t.integer :author_id, :null => false, :default => 0 + t.integer :t, :null => false, :default => 0 + + t.timestamps + end + end + + def down + end +end diff --git a/db/migrate/20130920042226_create_story_sheets.rb b/db/migrate/20130920042226_create_story_sheets.rb new file mode 100644 index 00000000..f8bb2cae --- /dev/null +++ b/db/migrate/20130920042226_create_story_sheets.rb @@ -0,0 +1,12 @@ +class CreateStorySheets < ActiveRecord::Migration + def change + create_table :story_sheets do |t| + t.integer :story_id, :null => false, :default => 0 + t.integer :sheet_id, :null => false, :default => 0 + t.integer :author_id, :null => false, :default => 0 + t.integer :t, :null => false, :default => 0 + + t.timestamps + end + end +end diff --git a/spec/controllers/artists_controller_spec.rb b/spec/controllers/artists_controller_spec.rb index f36053e3..54352b95 100644 --- a/spec/controllers/artists_controller_spec.rb +++ b/spec/controllers/artists_controller_spec.rb @@ -4,6 +4,7 @@ require 'spec_helper' describe ArtistsController do before do + SpeechBalloonTemplate.delete_all @admin = FactoryGirl.create :admin @demand_user = FactoryGirl.create :demand_user @sp = FactoryGirl.create :system_picture diff --git a/spec/controllers/authors_controller_spec.rb b/spec/controllers/authors_controller_spec.rb index 53728ca2..29773cab 100644 --- a/spec/controllers/authors_controller_spec.rb +++ b/spec/controllers/authors_controller_spec.rb @@ -4,6 +4,7 @@ require 'spec_helper' describe AuthorsController do before do + SpeechBalloonTemplate.delete_all @admin =FactoryGirl.create :admin @sp = FactoryGirl.create :system_picture @lg = FactoryGirl.create :license_group diff --git a/spec/controllers/balloons_controller_spec.rb b/spec/controllers/balloons_controller_spec.rb index dc92cb7b..98a1be97 100644 --- a/spec/controllers/balloons_controller_spec.rb +++ b/spec/controllers/balloons_controller_spec.rb @@ -4,6 +4,7 @@ require 'spec_helper' describe BalloonsController do before do + SpeechBalloonTemplate.delete_all @admin = FactoryGirl.create :admin @user = FactoryGirl.create( :user_yas) @author = FactoryGirl.create :author, :user_id => @user.id diff --git a/spec/controllers/ground_colors_controller_spec.rb b/spec/controllers/ground_colors_controller_spec.rb index 147aecda..8c166406 100644 --- a/spec/controllers/ground_colors_controller_spec.rb +++ b/spec/controllers/ground_colors_controller_spec.rb @@ -4,6 +4,7 @@ require 'spec_helper' describe GroundColorsController do before do + SpeechBalloonTemplate.delete_all @admin = FactoryGirl.create :admin @user = FactoryGirl.create( :user_yas) @sp = FactoryGirl.create :system_picture diff --git a/spec/controllers/ground_pictures_controller_spec.rb b/spec/controllers/ground_pictures_controller_spec.rb index fbe93956..d46307c7 100644 --- a/spec/controllers/ground_pictures_controller_spec.rb +++ b/spec/controllers/ground_pictures_controller_spec.rb @@ -4,6 +4,7 @@ require 'spec_helper' describe GroundPicturesController do before do + SpeechBalloonTemplate.delete_all @admin = FactoryGirl.create :admin @user = FactoryGirl.create( :user_yas) @sp = FactoryGirl.create :system_picture diff --git a/spec/controllers/home_controller_spec.rb b/spec/controllers/home_controller_spec.rb index b25fa9ff..ae934418 100644 --- a/spec/controllers/home_controller_spec.rb +++ b/spec/controllers/home_controller_spec.rb @@ -4,6 +4,7 @@ require 'spec_helper' describe HomeController do before do + SpeechBalloonTemplate.delete_all @admin =FactoryGirl.create :admin @sp = FactoryGirl.create :system_picture @lg = FactoryGirl.create :license_group diff --git a/spec/controllers/panels_controller_spec.rb b/spec/controllers/panels_controller_spec.rb index 31856222..2107730a 100644 --- a/spec/controllers/panels_controller_spec.rb +++ b/spec/controllers/panels_controller_spec.rb @@ -3,6 +3,7 @@ require 'spec_helper' #コマ describe PanelsController do before do + SpeechBalloonTemplate.delete_all @admin = FactoryGirl.create :admin @sp = FactoryGirl.create :system_picture @lg = FactoryGirl.create :license_group diff --git a/spec/controllers/sheet_panels_controller_spec.rb b/spec/controllers/sheet_panels_controller_spec.rb new file mode 100644 index 00000000..918da853 --- /dev/null +++ b/spec/controllers/sheet_panels_controller_spec.rb @@ -0,0 +1,5 @@ +require 'spec_helper' + +describe SheetPanelsController do + +end diff --git a/spec/controllers/sheets_controller_spec.rb b/spec/controllers/sheets_controller_spec.rb new file mode 100644 index 00000000..8855b14b --- /dev/null +++ b/spec/controllers/sheets_controller_spec.rb @@ -0,0 +1,5 @@ +require 'spec_helper' + +describe SheetsController do + +end diff --git a/spec/controllers/speech_balloon_templates_controller_spec.rb b/spec/controllers/speech_balloon_templates_controller_spec.rb index 2fb447e0..5173dff4 100644 --- a/spec/controllers/speech_balloon_templates_controller_spec.rb +++ b/spec/controllers/speech_balloon_templates_controller_spec.rb @@ -4,6 +4,7 @@ require 'spec_helper' describe SpeechBalloonTemplatesController do before do + SpeechBalloonTemplate.delete_all @admin = FactoryGirl.create :admin @sp = FactoryGirl.create :system_picture @lg = FactoryGirl.create :license_group diff --git a/spec/controllers/speech_balloons_controller_spec.rb b/spec/controllers/speech_balloons_controller_spec.rb index 16859006..bb98036b 100644 --- a/spec/controllers/speech_balloons_controller_spec.rb +++ b/spec/controllers/speech_balloons_controller_spec.rb @@ -3,6 +3,7 @@ require 'spec_helper' describe SpeechBalloonsController do before do + SpeechBalloonTemplate.delete_all @admin = FactoryGirl.create :admin @user = FactoryGirl.create( :user_yas) @author = FactoryGirl.create :author, :user_id => @user.id diff --git a/spec/controllers/speeches_controller_spec.rb b/spec/controllers/speeches_controller_spec.rb index 10d1544e..c3ee16b8 100644 --- a/spec/controllers/speeches_controller_spec.rb +++ b/spec/controllers/speeches_controller_spec.rb @@ -4,6 +4,7 @@ require 'spec_helper' describe SpeechesController do before do + SpeechBalloonTemplate.delete_all @admin = FactoryGirl.create :admin @user = FactoryGirl.create( :user_yas) @author = FactoryGirl.create :author, :user_id => @user.id diff --git a/spec/controllers/story_sheets_controller_spec.rb b/spec/controllers/story_sheets_controller_spec.rb new file mode 100644 index 00000000..1ee00c84 --- /dev/null +++ b/spec/controllers/story_sheets_controller_spec.rb @@ -0,0 +1,5 @@ +require 'spec_helper' + +describe StorySheetsController do + +end diff --git a/spec/controllers/system_pictures_controller_spec.rb b/spec/controllers/system_pictures_controller_spec.rb index b8bd139c..3e7c7266 100644 --- a/spec/controllers/system_pictures_controller_spec.rb +++ b/spec/controllers/system_pictures_controller_spec.rb @@ -4,6 +4,7 @@ require 'spec_helper' describe SystemPicturesController do before do + SpeechBalloonTemplate.delete_all @admin = FactoryGirl.create :admin @demand_user = FactoryGirl.create :demand_user @user = FactoryGirl.create( :user_yas) diff --git a/spec/factories.rb b/spec/factories.rb index 0f29ff86..c35f33cf 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -73,6 +73,7 @@ FactoryGirl.define do scroll.title "scroll" scroll.description 'scroll description' scroll.visible 1 + scroll.author_id 1 end factory :scroll_panel, :class => ScrollPanel do |scroll_panel| @@ -82,6 +83,47 @@ FactoryGirl.define do scroll_panel.t 0 end + factory :comic, :class => Comic do |comic| + comic.title "comic" + comic.description 'comic description' + comic.visible 1 + comic.author_id 1 + end + + factory :story, :class => Story do |story| + story.comic_id 1 + story.title "scroll" + story.description 'scroll description' + story.visible 1 + story.t 0 + story.author_id 1 + end + + factory :story_sheet, :class => StorySheet do |story_sheet| + story_sheet.sheet_id 1 + story_sheet.story_id 1 + story_sheet.t 0 + story_sheet.author_id 1 + end + + factory :sheet, :class => Sheet do |sheet| + sheet.caption "sheet" + sheet.width 222 + sheet.height 111 + sheet.visible 1 + sheet.author_id 1 + end + + factory :sheet_panel, :class => SheetPanel do |sheet_panel| + sheet_panel.sheet_id 1 + sheet_panel.panel_id 1 + sheet_panel.x 111 + sheet_panel.y 200 + sheet_panel.z 1 + sheet_panel.t 0 + sheet_panel.author_id 1 + end + factory :original_picture, :class => OriginalPicture do |op| op.ext 'png' op.width 222 diff --git a/spec/helpers/sheet_panels_helper_spec.rb b/spec/helpers/sheet_panels_helper_spec.rb new file mode 100644 index 00000000..9792472a --- /dev/null +++ b/spec/helpers/sheet_panels_helper_spec.rb @@ -0,0 +1,15 @@ +require 'spec_helper' + +# Specs in this file have access to a helper object that includes +# the SheetPanelsHelper. For example: +# +# describe SheetPanelsHelper do +# describe "string concat" do +# it "concats two strings with spaces" do +# helper.concat_strings("this","that").should == "this that" +# end +# end +# end +describe SheetPanelsHelper do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/helpers/sheets_helper_spec.rb b/spec/helpers/sheets_helper_spec.rb new file mode 100644 index 00000000..7355f012 --- /dev/null +++ b/spec/helpers/sheets_helper_spec.rb @@ -0,0 +1,15 @@ +require 'spec_helper' + +# Specs in this file have access to a helper object that includes +# the SheetsHelper. For example: +# +# describe SheetsHelper do +# describe "string concat" do +# it "concats two strings with spaces" do +# helper.concat_strings("this","that").should == "this that" +# end +# end +# end +describe SheetsHelper do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/helpers/story_sheets_helper_spec.rb b/spec/helpers/story_sheets_helper_spec.rb new file mode 100644 index 00000000..a64e8eec --- /dev/null +++ b/spec/helpers/story_sheets_helper_spec.rb @@ -0,0 +1,15 @@ +require 'spec_helper' + +# Specs in this file have access to a helper object that includes +# the StorySheetsHelper. For example: +# +# describe StorySheetsHelper do +# describe "string concat" do +# it "concats two strings with spaces" do +# helper.concat_strings("this","that").should == "this that" +# end +# end +# end +describe StorySheetsHelper do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/models/artist_spec.rb b/spec/models/artist_spec.rb index e93b28f8..493bd4ec 100644 --- a/spec/models/artist_spec.rb +++ b/spec/models/artist_spec.rb @@ -4,6 +4,7 @@ require 'spec_helper' describe Artist do before do + SpeechBalloonTemplate.delete_all @admin = FactoryGirl.create :admin @user = FactoryGirl.create( :user_yas) @author = FactoryGirl.create :author, :user_id => @user.id diff --git a/spec/models/author_spec.rb b/spec/models/author_spec.rb index 73139cb5..dd652662 100644 --- a/spec/models/author_spec.rb +++ b/spec/models/author_spec.rb @@ -4,6 +4,7 @@ require 'spec_helper' describe Author do before do + SpeechBalloonTemplate.delete_all @admin = FactoryGirl.create :admin @user = FactoryGirl.create( :user_yas) @author = FactoryGirl.create :author, :user_id => @user.id @@ -410,7 +411,7 @@ describe Author do describe 'マイリストページ制御パラメータに於いて' do before do end - context 'コミックpage_size補正について' do + context 'スクロールpage_size補正について' do it '文字列から数値に変換される' do Author.scroll_page_size('7').should eq 7 end @@ -424,7 +425,7 @@ describe Author do Author.scroll_page_size('1000').should eq Author.scroll_max_page_size end end - context 'ストーリーpage_size補正について' do + context 'スクコマpage_size補正について' do it '文字列から数値に変換される' do Author.scroll_panel_page_size('7').should eq 7 end @@ -438,6 +439,76 @@ describe Author do Author.scroll_panel_page_size('1000').should eq Author.scroll_panel_max_page_size end end + context 'コミックpage_size補正について' do + it '文字列から数値に変換される' do + Author.comic_page_size('7').should eq 7 + end + it 'nilの場合はAuthor.default_comic_page_sizeになる' do + Author.comic_page_size().should eq Author.default_comic_page_size + end + it '0以下の場合はAuthor.default_comic_page_sizeになる' do + Author.comic_page_size('0').should eq Author.default_comic_page_size + end + it 'Author.comic_max_page_sizeを超えた場合はAuthor.comic_max_page_sizeになる' do + Author.comic_page_size('1000').should eq Author.comic_max_page_size + end + end + context 'ストーリーpage_size補正について' do + it '文字列から数値に変換される' do + Author.story_page_size('7').should eq 7 + end + it 'nilの場合はAuthor.default_story_page_sizeになる' do + Author.story_page_size().should eq Author.default_story_page_size + end + it '0以下の場合はAuthor.default_story_page_sizeになる' do + Author.story_page_size('0').should eq Author.default_story_page_size + end + it 'Author.story_max_page_sizeを超えた場合はAuthor.story_max_page_sizeになる' do + Author.story_page_size('1000').should eq Author.story_max_page_size + end + end + context 'スト紙page_size補正について' do + it '文字列から数値に変換される' do + Author.story_sheet_page_size('7').should eq 7 + end + it 'nilの場合はAuthor.default_story_sheet_page_sizeになる' do + Author.story_sheet_page_size().should eq Author.default_story_sheet_page_size + end + it '0以下の場合はAuthor.default_story_sheet_page_sizeになる' do + Author.story_sheet_page_size('0').should eq Author.default_story_sheet_page_size + end + it 'Author.story_sheet_max_page_sizeを超えた場合はAuthor.story_sheet_max_page_sizeになる' do + Author.story_sheet_page_size('1000').should eq Author.story_sheet_max_page_size + end + end + context '用紙page_size補正について' do + it '文字列から数値に変換される' do + Author.sheet_page_size('7').should eq 7 + end + it 'nilの場合はAuthor.default_sheet_page_sizeになる' do + Author.sheet_page_size().should eq Author.default_sheet_page_size + end + it '0以下の場合はAuthor.default_sheet_page_sizeになる' do + Author.sheet_page_size('0').should eq Author.default_sheet_page_size + end + it 'Author.sheet_max_page_sizeを超えた場合はAuthor.sheet_max_page_sizeになる' do + Author.sheet_page_size('1000').should eq Author.sheet_max_page_size + end + end + context '紙コマpage_size補正について' do + it '文字列から数値に変換される' do + Author.sheet_panel_page_size('7').should eq 7 + end + it 'nilの場合はAuthor.default_sheet_panel_page_sizeになる' do + Author.sheet_panel_page_size().should eq Author.default_sheet_panel_page_size + end + it '0以下の場合はAuthor.default_sheet_panel_page_sizeになる' do + Author.sheet_panel_page_size('0').should eq Author.default_sheet_panel_page_size + end + it 'Author.sheet_panel_max_page_sizeを超えた場合はAuthor.sheet_panel_max_page_sizeになる' do + Author.sheet_panel_page_size('1000').should eq Author.sheet_panel_max_page_size + end + end context 'コマpage_size補正について' do it '文字列から数値に変換される' do Author.panel_page_size('7').should eq 7 diff --git a/spec/models/balloon_spec.rb b/spec/models/balloon_spec.rb index cf82f80a..a7f8a34d 100644 --- a/spec/models/balloon_spec.rb +++ b/spec/models/balloon_spec.rb @@ -3,6 +3,7 @@ require 'spec_helper' #フキダシ枠 describe Balloon do before do + SpeechBalloonTemplate.delete_all @admin = FactoryGirl.create :admin @user = FactoryGirl.create( :user_yas) @author = FactoryGirl.create :author, :user_id => @user.id @@ -14,6 +15,7 @@ describe Balloon do @lg = FactoryGirl.create :license_group @license = FactoryGirl.create :license, :license_group_id => @lg.id, :system_picture_id => @sp.id + SpeechBalloonTemplate.delete_all @speech_balloon_template = FactoryGirl.create :speech_balloon_template, "name" => "circle@pettan.com", "classname" => "CircleSpeechBalloon", "caption" => "cc", "system_picture_id" => @sp.id, "settings" => '{}' @writing_format = FactoryGirl.create :writing_format @panel = FactoryGirl.create :panel, :author_id => @author.id diff --git a/spec/models/comic_spec.rb b/spec/models/comic_spec.rb new file mode 100644 index 00000000..ce70711d --- /dev/null +++ b/spec/models/comic_spec.rb @@ -0,0 +1,816 @@ +# -*- encoding: utf-8 -*- +require 'spec_helper' +#コミック + +describe Comic do + before do + SpeechBalloonTemplate.delete_all + @admin = FactoryGirl.create :admin + @demand_user = FactoryGirl.create :demand_user + @sp = FactoryGirl.create :system_picture + @lg = FactoryGirl.create :license_group + @license = FactoryGirl.create :license, :license_group_id => @lg.id, :system_picture_id => @sp.id + @user = FactoryGirl.create( :user_yas) + @author = FactoryGirl.create :author, :user_id => @user.id + @artist = FactoryGirl.create :artist_yas, :author_id => @author.id + @other_user = FactoryGirl.create( :user_yas) + @other_author = FactoryGirl.create :author, :user_id => @other_user.id + @other_artist = FactoryGirl.create :artist_yas, :author_id => @other_author.id + end + + describe '検証に於いて' do + before do + @comic = FactoryGirl.build :comic, :author_id => @author.id + end + + context 'オーソドックスなデータのとき' do + it '下限データが通る' do + @comic.title = 'a' + @comic.visible = 0 + @comic.should be_valid + end + it '上限データが通る' do + @comic.title = 'a'*100 + @comic.visible = 1 + @comic.should be_valid + end + end + + context 'titleを検証するとき' do + it 'nullなら失敗する' do + @comic.title = nil + @comic.should_not be_valid + end + it '100文字以上なら失敗する' do + @comic.title = 'a'*101 + @comic.should_not be_valid + end + end + context 'visibleを検証するとき' do + it 'nullなら失敗する' do + @comic.visible = nil + @comic.should_not be_valid + end + it '負なら失敗する' do + @comic.visible = -1 + @comic.should_not be_valid + end + it '2以上なら失敗する' do + @comic.visible = 2 + @comic.should_not be_valid + end + end + end + + describe '文字コード検証に於いて' do + before do + @comic = FactoryGirl.build :comic, :author_id => @author.id + end + + context 'titleを検証するとき' do + it 'Shift JISなら失敗する' do + @comic.title = "\x83G\x83r\x83]\x83D" + lambda{ + @comic.valid_encode + }.should raise_error(Pettanr::BadRequest) + end + end + + context 'descriptionを検証するとき' do + it 'Shift JISなら失敗する' do + @comic.description = "\x83G\x83r\x83]\x83D" + lambda{ + @comic.valid_encode + }.should raise_error(Pettanr::BadRequest) + end + end + end + + describe 'デフォルト値補充に於いて' do + it 'visibleが0になっている' do + @comic = FactoryGirl.build :comic, :visible => nil + @comic.supply_default + @comic.visible.should eq 0 + end + end + + describe '上書き補充に於いて' do + it '作家idが設定されている' do + @comic = FactoryGirl.build :comic, :author_id => nil + @comic.overwrite @author + @comic.author_id.should eq @author.id + end + end + + describe 'ロールリストからの作家取得に於いて' do + context 'ロールがユーザのとき' do + it 'ユーザから作家を取得して、それを返す' do + r = Comic.get_author_from_roles([@user]) + r.should eq @author + end + end + context 'ロールが作家のとき' do + it '作家を返す' do + r = Comic.get_author_from_roles([@author]) + r.should eq @author + end + end + context 'ロールが絵師のとき' do + it '絵師から作家を取得できれば、それをを返す' do + r = Comic.get_author_from_roles([@artist]) + r.should eq @author + end + it '絵師から作家を取得できないときnilを返す' do + @artist.author_id = nil + @artist.save! + r = Comic.get_author_from_roles([@artist]) + r.should be_nil + end + end + context 'ロールが管理者のとき' do + it 'nilを返す' do + r = Comic.get_author_from_roles([@admin]) + r.should be_nil + end + end + end + + describe 'ロールリストからの絵師取得に於いて' do + context 'ロールがユーザのとき' do + it 'ユーザから作家を取得して、そこから絵師を取得できれば、それを返す' do + r = Comic.get_artist_from_roles([@user]) + r.should eq @artist + end + it '作家から絵師を取得できないときnilを返す' do + @artist.author_id = nil + @artist.save! + r = Comic.get_artist_from_roles([@user]) + r.should be_nil + end + end + context 'ロールが作家のとき' do + it 'そこから絵師を取得できれば、それを返す' do + r = Comic.get_artist_from_roles([@author]) + r.should eq @artist + end + it '作家から絵師を取得できないときnilを返す' do + @artist.author_id = nil + @artist.save! + r = Comic.get_artist_from_roles([@author]) + r.should be_nil + end + end + context 'ロールが絵師のとき' do + it 'それを返す' do + r = Comic.get_artist_from_roles([@artist]) + r.should eq @artist + end + end + context 'ロールが管理者のとき' do + it 'nilを返す' do + r = Comic.get_artist_from_roles([@admin]) + r.should be_nil + end + end + end + + describe '所持判定に於いて' do + before do + @comic = FactoryGirl.build :comic, :author_id => @author.id + end + context '事前チェックする' do + it '自身にロールリストからの作家取得を依頼している' do + Comic.should_receive(:get_author_from_roles).with(any_args).exactly(1) + r = @comic.own?([@author]) + end + end + context 'ロール内作家が取得できるとき' do + before do + end + it 'ロール内作家のidが自身の作家idと一致するなら許可する' do + Comic.stub(:get_author_from_roles).with(any_args).and_return(@author) + r = @comic.own?([@author]) + r.should be_true + end + it 'ロール内作家のidが自身の作家idと一致しないならno' do + Comic.stub(:get_author_from_roles).with(any_args).and_return(@other_author) + @comic.own?(@other_author).should be_false + end + end + context 'ロール内作家が取得できないとき' do + before do + Comic.stub(:get_author_from_roles).with(any_args).and_return(nil) + end + it 'Falseを返す' do + r = @comic.own?([@author]) + r.should be_false + end + end + end + + describe '読者用ロールチェックに於いて' do + before do + @comic = FactoryGirl.build :comic, :author_id => @author.id + end + context 'ロールリストに作家が含まれるとき' do + it 'ロールリストがリストではないとき、リストにする trueを返す' do + r = @comic.reader_role_check(@author) + r.should be_true + end + it 'trueを返す' do + r = @comic.reader_role_check([@author]) + r.should be_true + end + end + context 'ロールリストに絵師が含まれるとき' do + it 'trueを返す' do + r = @comic.reader_role_check([@artist]) + r.should be_true + end + end + context 'ロールリストにユーザが含まれるとき' do + it 'trueを返す' do + r = @comic.reader_role_check([@user]) + r.should be_true + end + end + context 'ロールリストに管理者が含まれるとき' do + it 'trueを返す' do + r = @comic.reader_role_check([@admin]) + r.should be_true + end + end + context 'ロールリストにユーザ、管理者、作家、絵師が含まれないとき' do + it 'falseを返す' do + r = @comic.reader_role_check([nil]) + r.should be_false + end + end + end + + describe '素材読者用ロールチェックに於いて' do + before do + @comic = FactoryGirl.build :comic, :author_id => @author.id + end + context 'ロールリストに作家が含まれるとき' do + it 'ロールリストがリストではないとき、リストにする trueを返す' do + r = @comic.resource_reader_role_check(@author) + r.should be_true + end + it 'trueを返す' do + r = @comic.resource_reader_role_check([@author]) + r.should be_true + end + end + context 'ロールリストに絵師が含まれるとき' do + it 'trueを返す' do + r = @comic.resource_reader_role_check([@artist]) + r.should be_true + end + end + context 'ロールリストにユーザが含まれるとき' do + it 'trueを返す' do + r = @comic.resource_reader_role_check([@user]) + r.should be_true + end + end + context 'ロールリストに管理者が含まれるとき' do + it 'trueを返す' do + r = @comic.resource_reader_role_check([@admin]) + r.should be_true + end + end + context 'ロールリストに借手が含まれるとき' do + it 'trueを返す' do + r = @comic.resource_reader_role_check([@demand_user]) + r.should be_true + end + end + context 'ロールリストにユーザ、管理者、作家、絵師、借手が含まれないとき' do + it 'falseを返す' do + r = @comic.resource_reader_role_check([nil]) + r.should be_false + end + end + end + + describe '閲覧許可に於いて' do + before do + @comic = FactoryGirl.build :comic, :author_id => @author.id + end + context 'オープンモードのとき' do + before do + MagicNumber['run_mode'] = 0 + end + it '自身にゲスト用ロールチェックを問い合わせしている' do + Comic.any_instance.stub(:guest_role_check).and_return(true) + Comic.any_instance.should_receive(:guest_role_check).with(any_args).exactly(1) + r = @comic.visible?([@author]) + end + it 'ゲスト用ロールチェックが失敗したとき、falseを返す' do + Comic.any_instance.stub(:guest_role_check).and_return(false) + r = @comic.visible?([@author]) + r.should be_false + end + end + context 'クローズドモードのとき' do + before do + MagicNumber['run_mode'] = 1 + end + it '自身に読者用ロールチェックを問い合わせしている' do + Comic.any_instance.stub(:reader_role_check).and_return(true) + Comic.any_instance.should_receive(:reader_role_check).with(any_args).exactly(1) + r = @comic.visible?([@author]) + end + it '読者用ロールチェックが失敗したとき、falseを返す' do + Comic.any_instance.stub(:reader_role_check).and_return(false) + r = @comic.visible?([@author]) + r.should be_false + end + end + context '事前チェックする' do + before do + MagicNumber['run_mode'] = 1 + Comic.any_instance.stub(:reader_role_check).and_return(true) + Comic.any_instance.stub(:own?).and_return(true) + end + it '自身に所持判定を問い合わせしている' do + Comic.any_instance.should_receive(:own?).with(any_args).exactly(1) + r = @comic.visible?([@author]) + end + end + context 'つつがなく終わるとき' do + before do + MagicNumber['run_mode'] = 1 + Comic.any_instance.stub(:reader_role_check).and_return(true) + end + it '自分のコミックなら許可する' do + Comic.any_instance.stub(:own?).and_return(true) + Comic.any_instance.stub(:visible).and_return(0) + r = @comic.visible?([@author]) + r.should be_true + end + it '他人の非公開コミックなら許可しない' do + Comic.any_instance.stub(:own?).and_return(false) + Comic.any_instance.stub(:visible).and_return(0) + r = @comic.visible?([@author]) + r.should be_false + end + it '他人のコミックでも公開なら許可する' do + Comic.any_instance.stub(:own?).and_return(false) + Comic.any_instance.stub(:visible).and_return(1) + r = @comic.visible?([@author]) + r.should be_true + end + end + end + + describe '一覧取得に於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + end + context 'page補正について' do + it '文字列から数値に変換される' do + Comic.page('8').should eq 8 + end + it 'nilの場合は1になる' do + Comic.page().should eq 1 + end + it '0以下の場合は1になる' do + Comic.page('0').should eq 1 + end + end + context 'page_size補正について' do + it '文字列から数値に変換される' do + Comic.page_size('7').should eq 7 + end + it 'nilの場合はComic.default_page_sizeになる' do + Comic.page_size().should eq Comic.default_page_size + end + it '0以下の場合はComic.default_page_sizeになる' do + Comic.page_size('0').should eq Comic.default_page_size + end + it 'Comic.max_page_sizeを超えた場合はComic.max_page_sizeになる' do + Comic.page_size('1000').should eq Comic.max_page_size + end + end + context 'つつがなく終わるとき' do + it '一覧取得オプションを利用している' do + Comic.stub(:list_opt).with(any_args).and_return({}) + Comic.should_receive(:list_opt).with(any_args).exactly(1) + r = Comic.list + end + end + it 'リストを返す' do + c = Comic.list + c.should eq [@comic] + end + it '非公開コミックは(自分のコミックであっても)含んでいない' do + FactoryGirl.create :comic, :author_id => @author.id, :visible => 0 + c = Comic.list + c.should eq [@comic] + end + it '時系列で並んでいる' do + #公開コミックは(他人のコミックであっても)含んでいる + v = FactoryGirl.create :comic, :author_id => @other_author.id, :updated_at => Time.now + 100 + c = Comic.list + c.should eq [v, @comic] + end + context 'DBに5件あって1ページの件数を2件に変えたとして' do + before do + @comic2 = FactoryGirl.create :comic, :author_id => @author.id, :updated_at => Time.now + 100 + @comic3 = FactoryGirl.create :comic, :author_id => @author.id, :updated_at => Time.now + 200 + @comic4 = FactoryGirl.create :comic, :author_id => @author.id, :updated_at => Time.now + 300 + @comic5 = FactoryGirl.create :comic, :author_id => @author.id, :updated_at => Time.now + 400 + Comic.stub(:default_page_size).and_return(2) + end + it '通常は2件を返す' do + c = Comic.list + c.should have(2).items + end + it 'page=1なら末尾2件を返す' do + #時系列で並んでいる + c = Comic.list(1) + c.should eq [@comic5, @comic4] + end + it 'page=2なら中間2件を返す' do + c = Comic.list(2) + c.should eq [@comic3, @comic2] + end + it 'page=3なら先頭1件を返す' do + c = Comic.list(3) + c.should eq [@comic] + end + end + end + + describe '自分のコミック一覧取得に於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + end + context 'つつがなく終わるとき' do + it '一覧取得オプションを利用している' do + Comic.stub(:list_opt).with(any_args).and_return({}) + Comic.should_receive(:list_opt).with(any_args).exactly(1) + r = Comic.mylist @author + end + end + it 'リストを返す' do + c = Comic.mylist @author + c.should eq [@comic] + end + it '時系列で並んでいる' do + nc = FactoryGirl.create :comic, :author_id => @author.id, :updated_at => Time.now + 100 + cl = Comic.mylist @author + cl.should eq [nc, @comic] + end + it '他人のコミックは公開でも含まない' do + nc = FactoryGirl.create :comic, :author_id => @other_author.id, :visible => 1 + cl = Comic.mylist @author + cl.should eq [@comic] + end + it '自分のコミックは非公開でも含んでいる' do + nc = FactoryGirl.create :comic, :author_id => @author.id, :visible => 0, :updated_at => Time.now + 100 + cl = Comic.mylist @author + cl.should eq [nc, @comic] + end + context 'DBに5件あって1ページの件数を2件に変えたとして' do + before do + @comic2 = FactoryGirl.create :comic, :author_id => @author.id, :updated_at => Time.now + 100 + @comic3 = FactoryGirl.create :comic, :author_id => @author.id, :updated_at => Time.now + 200 + @comic4 = FactoryGirl.create :comic, :author_id => @author.id, :updated_at => Time.now + 300 + @comic5 = FactoryGirl.create :comic, :author_id => @author.id, :updated_at => Time.now + 400 + end + it '通常は2件を返す' do + c = Comic.mylist @author, 1, 2 + c.should have(2).items + end + it 'page=1なら末尾2件を返す' do + #時系列で並んでいる + c = Comic.mylist(@author, 1, 2) + c.should eq [@comic5, @comic4] + end + it 'page=2なら中間2件を返す' do + c = Comic.mylist(@author, 2, 2) + c.should eq [@comic3, @comic2] + end + it 'page=3なら先頭1件を返す' do + c = Comic.mylist(@author, 3, 2) + c.should eq [@comic] + end + end + end + + describe '他作家のコミック一覧取得に於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @other_comic = FactoryGirl.create :comic, :author_id => @other_author.id, :visible => 1 + end + context 'つつがなく終わるとき' do + it '一覧取得オプションを利用している' do + Comic.stub(:list_opt).with(any_args).and_return({}) + Comic.should_receive(:list_opt).with(any_args).exactly(1) + r = Comic.himlist @other_author + end + end + it '指定した作家のリストを返す' do + r = Comic.himlist @other_author + r.should eq [@other_comic] + end + it '時系列で並んでいる' do + nc = FactoryGirl.create :comic, :author_id => @other_author.id, :updated_at => Time.now + 100 + r = Comic.himlist @other_author + r.should eq [nc, @other_comic] + end + it '公開コミックに限る ' do + hidden = FactoryGirl.create :comic, :author_id => @other_author.id, :visible => 0 + r = Comic.himlist @other_author + r.should eq [@other_comic] + end + context 'DBに5件あって1ページの件数を2件に変えたとして' do + before do + @other_comic2 = FactoryGirl.create :comic, :author_id => @other_author.id, :updated_at => Time.now + 100 + @other_comic3 = FactoryGirl.create :comic, :author_id => @other_author.id, :updated_at => Time.now + 200 + @other_comic4 = FactoryGirl.create :comic, :author_id => @other_author.id, :updated_at => Time.now + 300 + @other_comic5 = FactoryGirl.create :comic, :author_id => @other_author.id, :updated_at => Time.now + 400 + end + it '通常は2件を返す' do + c = Comic.himlist @other_author, 1, 2 + c.should have(2).items + end + it 'page=1なら末尾2件を返す' do + #時系列で並んでいる + c = Comic.himlist(@other_author, 1, 2) + c.should eq [@other_comic5, @other_comic4] + end + it 'page=2なら中間2件を返す' do + c = Comic.himlist(@other_author, 2, 2) + c.should eq [@other_comic3, @other_comic2] + end + it 'page=3なら先頭1件を返す' do + c = Comic.himlist(@other_author, 3, 2) + c.should eq [@other_comic] + end + end + end + + describe 'コミック一覧ページ制御に於いて' do + before do + Comic.stub(:count).with(any_args).and_return(100) + end + it 'ページ制御を返す' do + r = Comic.list_paginate + r.is_a?(Kaminari::PaginatableArray).should be_true + end + it 'コミック一覧の取得条件を利用している' do + Comic.stub(:list_where).with(any_args).and_return('') + Comic.should_receive(:list_where).with(any_args).exactly(1) + r = Comic.list_paginate + end + it 'ページ件数10のとき、3ページ目のオフセットは20から始まる' do + r = Comic.list_paginate 3, 10 + r.limit_value.should eq 10 + r.offset_value.should eq 20 + end + end + + describe '自分のコミック一覧ページ制御に於いて' do + before do + Comic.stub(:count).with(any_args).and_return(100) + end + it 'ページ制御を返す' do + r = Comic.mylist_paginate @author + r.is_a?(Kaminari::PaginatableArray).should be_true + end + it '自分のコミック一覧の取得条件を利用している' do + Comic.stub(:mylist_where).with(any_args).and_return('') + Comic.should_receive(:mylist_where).with(any_args).exactly(1) + r = Comic.mylist_paginate @author + end + it 'ページ件数10のとき、3ページ目のオフセットは20から始まる' do + r = Comic.mylist_paginate @author, 3, 10 + r.limit_value.should eq 10 + r.offset_value.should eq 20 + end + end + + describe '他作家のコミック一覧ページ制御に於いて' do + before do + Comic.stub(:count).with(any_args).and_return(100) + end + it 'ページ制御を返す' do + r = Comic.himlist_paginate @other_author + r.is_a?(Kaminari::PaginatableArray).should be_true + end + it '他作家のコミック一覧の取得条件を利用している' do + Comic.stub(:himlist_where).with(any_args).and_return('') + Comic.should_receive(:himlist_where).with(any_args).exactly(1) + r = Comic.himlist_paginate @other_author + end + it 'ページ件数10のとき、3ページ目のオフセットは20から始まる' do + r = Comic.himlist_paginate @other_author, 3, 10 + r.limit_value.should eq 10 + r.offset_value.should eq 20 + end + end + + describe '一覧取得オプションに於いて' do + it '2つの項目を含んでいる' do + r = Comic.list_opt + r.should have(2).items + end + it 'ストーリーを含んでいる' do + r = Comic.list_opt + r.has_key?(:stories).should be_true + end + it '作家を含んでいる' do + r = Comic.list_opt + r.has_key?(:author).should be_true + end + end + describe 'json一覧出力オプションに於いて' do + before do + @op = FactoryGirl.create :original_picture, :artist_id => @artist.id + @p = FactoryGirl.create :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id + @rp = FactoryGirl.create :resource_picture, :artist_id => @artist.id, :license_id => @license.id, :original_picture_id => @op.id, :picture_id => @p.id + @sbt = FactoryGirl.create :speech_balloon_template + @comic = FactoryGirl.create :comic, :author_id => @author.id, :visible => 1 + @story = FactoryGirl.create :story, :author_id => @author.id, :comic_id => @comic.id + end + it 'ストーリーを含んでいる' do + r = Comic.list.to_json Comic.list_json_opt + j = JSON.parse r + i = j.first + i.has_key?('stories').should be_true + end + it '作家を含んでいる' do + r = Comic.list.to_json Comic.list_json_opt + j = JSON.parse r + i = j.first + i.has_key?('author').should be_true + end + end + + describe '単体取得に於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + end + context 'つつがなく終わるとき' do + it '単体取得オプションを利用している' do + Comic.stub(:show_opt).with(any_args).and_return({}) + Comic.should_receive(:show_opt).with(any_args).exactly(1) + r = Comic.show @comic.id, @author + end + it '閲覧許可を問い合わせている' do + Comic.any_instance.stub(:visible?).with(any_args).and_return(true) + Comic.any_instance.should_receive(:visible?).with(any_args).exactly(1) + r = Comic.show @comic.id, @author + end + end + it '指定のコミックを返す' do + c = Comic.show @comic.id, @author + c.should eq @comic + end + context '閲覧許可が出なかったとき' do + it '403Forbidden例外を返す' do + Comic.any_instance.stub(:visible?).and_return(false) + lambda{ + Comic.show @comic.id, @author + }.should raise_error(ActiveRecord::Forbidden) + end + end + context '存在しないコミックを開こうとしたとき' do + it '404RecordNotFound例外を返す' do + lambda{ + Comic.show 110, @author + }.should raise_error(ActiveRecord::RecordNotFound) + end + end + end + + describe '編集取得に於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + end + context 'つつがなく終わるとき' do + it '単体取得オプションを利用している' do + Comic.stub(:show_opt).with(any_args).and_return({}) + Comic.should_receive(:show_opt).with(any_args).exactly(1) + r = Comic.edit @comic.id, @author + end + it '所持判定を問い合わせている' do + Comic.any_instance.stub(:own?).with(any_args).and_return(true) + Comic.any_instance.should_receive(:own?).with(any_args).exactly(1) + r = Comic.edit @comic.id, @author + end + end + it '指定のコミックを返す' do + Comic.any_instance.stub(:own?).and_return(true) + c = Comic.edit @comic.id, @author.id + c.should eq @comic + end + context '他人のコミックを開こうとしたとき' do + it '403Forbidden例外を返す' do + Comic.any_instance.stub(:own?).and_return(false) + lambda{ + Comic.edit @comic.id, @author + }.should raise_error(ActiveRecord::Forbidden) + end + end + context '存在しないコミックを開こうとしたとき' do + it '404RecordNotFound例外を返す' do + lambda{ + Comic.edit 110, @author + }.should raise_error(ActiveRecord::RecordNotFound) + end + end + end + describe '単体取得オプションに於いて' do + it 'includeキーを含んでいる' do + r = Comic.show_opt + r.has_key?(:include).should be_true + end + it '2つの項目を含んでいる' do + r = Comic.show_opt[:include] + r.should have(2).items + end + it '作家を含んでいる' do + r = Comic.show_opt[:include] + r.has_key?(:author).should be_true + end + it 'ストーリーを含んでいる' do + r = Comic.show_opt[:include] + r.has_key?(:stories).should be_true + end + end + describe 'json単体出力オプションに於いて' do + before do + @op = FactoryGirl.create :original_picture, :artist_id => @artist.id + @p = FactoryGirl.create :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id + @rp = FactoryGirl.create :resource_picture, :artist_id => @artist.id, :license_id => @license.id, :original_picture_id => @op.id, :picture_id => @p.id + @sbt = FactoryGirl.create :speech_balloon_template + @comic = FactoryGirl.create :comic, :author_id => @author.id, :visible => 1 + @story = FactoryGirl.create :story, :author_id => @author.id, :comic_id => @comic.id + end + it 'ストーリーを含んでいる' do + r = Comic.show(@comic.id, @author).to_json Comic.show_json_opt + j = JSON.parse r + i = j + i.has_key?('stories').should be_true + end + it '作家を含んでいる' do + r = Comic.show(@comic.id, @author).to_json Comic.show_json_opt + j = JSON.parse r + i = j + i.has_key?('author').should be_true + end + end + + describe '削除に於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @story = FactoryGirl.create :story, :author_id => @author.id, :comic_id => @comic.id + @other_comic = FactoryGirl.create :comic, :author_id => @author.id + @other_story = FactoryGirl.create :story, :author_id => @author.id, :comic_id => @other_comic.id + end + context 'つつがなく終わるとき' do + it '自身を削除する' do + lambda { + r = @comic.destroy_with_story + }.should change(Comic, :count).by(-1) + lambda { + r = Comic.find @comic.id + }.should raise_error + end + it '自身にリンクしているストーリーをすべて削除する' do + lambda { + r = @comic.destroy_with_story + }.should change(Story, :count).by(-1) + lambda { + r = Story.find @story.id + }.should raise_error + end + it 'Trueを返す' do + r = @comic.destroy_with_story + r.should be_true + end + end + context '削除に失敗したとき' do + before do + Story.any_instance.stub(:destroy).with(any_args).and_return(false) + end + it 'Falseを返す' do + r = @comic.destroy_with_story + r.should be_false + end + it 'ロールバックしている' do + lambda { + r = @comic.destroy_with_story + }.should_not change(Comic, :count) + lambda { + r = @comic.destroy_with_story + }.should_not change(Story, :count) + end + end + end +end diff --git a/spec/models/ground_color_spec.rb b/spec/models/ground_color_spec.rb index 8debd825..7f0567e1 100644 --- a/spec/models/ground_color_spec.rb +++ b/spec/models/ground_color_spec.rb @@ -4,6 +4,7 @@ require 'spec_helper' describe GroundColor do before do + SpeechBalloonTemplate.delete_all @admin = FactoryGirl.create :admin @user = FactoryGirl.create( :user_yas) @author = FactoryGirl.create :author, :user_id => @user.id diff --git a/spec/models/ground_picture_spec.rb b/spec/models/ground_picture_spec.rb index 680b5034..886982ae 100644 --- a/spec/models/ground_picture_spec.rb +++ b/spec/models/ground_picture_spec.rb @@ -4,6 +4,7 @@ require 'spec_helper' describe GroundPicture do before do + SpeechBalloonTemplate.delete_all @admin = FactoryGirl.create :admin @user = FactoryGirl.create( :user_yas) @author = FactoryGirl.create :author, :user_id => @user.id diff --git a/spec/models/license_group_spec.rb b/spec/models/license_group_spec.rb index 685c69a5..482ecc62 100644 --- a/spec/models/license_group_spec.rb +++ b/spec/models/license_group_spec.rb @@ -4,6 +4,7 @@ require 'spec_helper' describe LicenseGroup do before do + SpeechBalloonTemplate.delete_all #テストデータを用意してね @f = Rails.root + 'spec/json/license_group.json' @t = File.open(@f, 'r').read diff --git a/spec/models/original_picture_spec.rb b/spec/models/original_picture_spec.rb index cc587fc3..ede81d9c 100644 --- a/spec/models/original_picture_spec.rb +++ b/spec/models/original_picture_spec.rb @@ -4,6 +4,7 @@ require 'spec_helper' describe OriginalPicture do before do + SpeechBalloonTemplate.delete_all @admin = FactoryGirl.create :admin @user = FactoryGirl.create( :user_yas) @author = FactoryGirl.create :author, :user_id => @user.id diff --git a/spec/models/panel_picture_spec.rb b/spec/models/panel_picture_spec.rb index 364a032f..77eb490a 100644 --- a/spec/models/panel_picture_spec.rb +++ b/spec/models/panel_picture_spec.rb @@ -3,6 +3,7 @@ require 'spec_helper' #コマ絵 describe PanelPicture do before do + SpeechBalloonTemplate.delete_all @admin = FactoryGirl.create :admin @user = FactoryGirl.create( :user_yas) @author = FactoryGirl.create :author, :user_id => @user.id diff --git a/spec/models/panel_spec.rb b/spec/models/panel_spec.rb index a1582eed..416fb177 100644 --- a/spec/models/panel_spec.rb +++ b/spec/models/panel_spec.rb @@ -3,6 +3,7 @@ require 'spec_helper' #コマ describe Panel do before do + SpeechBalloonTemplate.delete_all @admin = FactoryGirl.create :admin @sp = FactoryGirl.create :system_picture @lg = FactoryGirl.create :license_group diff --git a/spec/models/resource_picture_spec.rb b/spec/models/resource_picture_spec.rb index fd3433bc..cccfb5a8 100644 --- a/spec/models/resource_picture_spec.rb +++ b/spec/models/resource_picture_spec.rb @@ -4,6 +4,7 @@ require 'spec_helper' describe ResourcePicture do before do + SpeechBalloonTemplate.delete_all @admin = FactoryGirl.create :admin @user = FactoryGirl.create( :user_yas) @author = FactoryGirl.create :author, :user_id => @user.id diff --git a/spec/models/scroll_panel_spec.rb b/spec/models/scroll_panel_spec.rb index bc3fcb2d..c0927a1d 100644 --- a/spec/models/scroll_panel_spec.rb +++ b/spec/models/scroll_panel_spec.rb @@ -1,12 +1,13 @@ # -*- encoding: utf-8 -*- require 'spec_helper' -#ストーリー +#スクコマ describe ScrollPanel do before do @admin = FactoryGirl.create :admin @sp = FactoryGirl.create :system_picture @lg = FactoryGirl.create :license_group @license = FactoryGirl.create :license, :license_group_id => @lg.id, :system_picture_id => @sp.id + SpeechBalloonTemplate.delete_all @speech_balloon_template = FactoryGirl.create :speech_balloon_template, "name" => "circle@pettan.com", "classname" => "CircleSpeechBalloon", "caption" => "cc", "system_picture_id" => @sp.id, "settings" => '{}' @writing_format = FactoryGirl.create :writing_format @user = FactoryGirl.create( :user_yas) @@ -46,7 +47,7 @@ describe ScrollPanel do @scroll_panel.scroll_id = 'a' @scroll_panel.should_not be_valid end - it '存在するコミックでなければ失敗する' do + it '存在するスクロールでなければ失敗する' do @scroll_panel.scroll_id = 0 @scroll_panel.should_not be_valid end @@ -212,12 +213,12 @@ describe ScrollPanel do MagicNumber['run_mode'] = 1 ScrollPanel.any_instance.stub(:reader_role_check).and_return(true) end - it '自身のコミックに所持判定を問い合わせしている' do + it '自身のスクロールに所持判定を問い合わせしている' do Scroll.any_instance.stub(:own?).and_return(true) Scroll.any_instance.should_receive(:own?).with(any_args).exactly(1) r = @scroll_panel.visible?([@author]) end - it '自身のコミックに閲覧許可を問い合わせしている' do + it '自身のスクロールに閲覧許可を問い合わせしている' do Scroll.any_instance.stub(:own?).and_return(false) Scroll.any_instance.stub(:visible?).and_return(true) Scroll.any_instance.should_receive(:visible?).with(any_args).exactly(1) @@ -229,19 +230,19 @@ describe ScrollPanel do MagicNumber['run_mode'] = 1 ScrollPanel.any_instance.stub(:reader_role_check).and_return(true) end - it '自分のコミックのストーリーなら許可する' do + it '自分のスクロールのスクコマなら許可する' do Scroll.any_instance.stub(:own?).and_return(true) Scroll.any_instance.stub(:visible).and_return(0) r = @scroll_panel.visible?([@author]) r.should be_true end - it '他人の非公開コミックのストーリーなら許可しない' do + it '他人の非公開スクロールのスクコマなら許可しない' do Scroll.any_instance.stub(:own?).and_return(false) Scroll.any_instance.stub(:visible).and_return(0) r = @scroll_panel.visible?([@author]) r.should be_false end - it '他人のコミックのストーリーでも公開なら許可する' do + it '他人のスクロールのスクコマでも公開なら許可する' do Scroll.any_instance.stub(:own?).and_return(false) Scroll.any_instance.stub(:visible).and_return(1) r = @scroll_panel.visible?([@author]) @@ -306,7 +307,7 @@ describe ScrollPanel do c.should eq [@scroll_panel] end it 't順で並んでいる' do - #公開コミックの公開コマは(他人のコミックであっても)含んでいる + #公開スクロールの公開コマは(他人のスクロールであっても)含んでいる v = FactoryGirl.create :scroll_panel, :author_id => @author.id, :scroll_id => @scroll.id, :panel_id => @panel.id, :t => 1 c = ScrollPanel.play_list @scroll, @author c.should eq [ @scroll_panel, v] @@ -378,12 +379,12 @@ describe ScrollPanel do c.should eq [@scroll_panel] end it '時系列で並んでいる' do - #公開コミックのScrollPanelは(他人のScrollPanelであっても)含んでいる + #公開スクロールのScrollPanelは(他人のScrollPanelであっても)含んでいる v = FactoryGirl.create :scroll_panel, :author_id => @other_author.id, :scroll_id => @other_scroll.id, :panel_id => @other_panel.id, :t => 0, :updated_at => Time.now + 100 c = ScrollPanel.list c.should eq [ v, @scroll_panel] end - it '非公開のストーリーは(自分のストーリーであっても)含まない' do + it '非公開のスクコマは(自分のスクコマであっても)含まない' do h = FactoryGirl.create :scroll_panel, :author_id => @author.id, :scroll_id => @hidden_scroll.id, :panel_id => @panel.id, :t => 0 c = ScrollPanel.list c.should eq [ @scroll_panel] @@ -415,7 +416,7 @@ describe ScrollPanel do end end - describe '自分のストーリー一覧取得に於いて' do + describe '自分のスクコマ一覧取得に於いて' do before do @scroll = FactoryGirl.create :scroll, :author_id => @author.id, :visible => 1 @panel = FactoryGirl.create :panel, :author_id => @author.id, :publish => 1 @@ -441,12 +442,12 @@ describe ScrollPanel do sl = ScrollPanel.mylist @author sl.should eq [ns, @scroll_panel] end - it '他人のストーリーはコマコミックともに公開でも含まない' do + it '他人のスクコマはコマスクロールともに公開でも含まない' do so = FactoryGirl.create :scroll_panel, :author_id => @other_author.id, :scroll_id => @other_scroll.id, :panel_id => @other_panel.id sl = ScrollPanel.mylist @author sl.should eq [@scroll_panel] end - it '自分のストーリーはコマコミックともに非公開でも含んでいる' do + it '自分のスクコマはコマスクロールともに非公開でも含んでいる' do hs = FactoryGirl.create :scroll_panel, :author_id => @author.id, :scroll_id => @hscroll.id, :panel_id => @hpanel.id, :updated_at => Time.now + 100 sl = ScrollPanel.mylist @author sl.should eq [hs, @scroll_panel] @@ -479,7 +480,7 @@ describe ScrollPanel do end end - describe '他作家のストーリー一覧取得に於いて' do + describe '他作家のスクコマ一覧取得に於いて' do before do @scroll = FactoryGirl.create :scroll, :author_id => @author.id, :visible => 1 @panel = FactoryGirl.create :panel, :author_id => @author.id, :publish => 1 @@ -497,7 +498,7 @@ describe ScrollPanel do r = ScrollPanel.himlist @other_author r.should eq [ns, @other_scroll_panel] end - it '公開コミックのストーリー' do + it '公開スクロールのスクコマ' do @hscroll = FactoryGirl.create :scroll, :author_id => @other_author.id, :visible => 0 ns = FactoryGirl.create :scroll_panel, :author_id => @other_author.id, :scroll_id => @hscroll.id, :panel_id => @other_panel.id, :t => 1, :updated_at => Time.now + 100 r = ScrollPanel.himlist @other_author @@ -531,7 +532,7 @@ describe ScrollPanel do end end - describe 'ストーリー一覧ページ制御に於いて' do + describe 'スクコマ一覧ページ制御に於いて' do before do ScrollPanel.stub(:count).with(any_args).and_return(100) end @@ -539,7 +540,7 @@ describe ScrollPanel do r = ScrollPanel.list_paginate r.is_a?(Kaminari::PaginatableArray).should be_true end - it 'ストーリー一覧の取得条件を利用している' do + it 'スクコマ一覧の取得条件を利用している' do ScrollPanel.stub(:list_where).with(any_args).and_return('') ScrollPanel.should_receive(:list_where).with(any_args).exactly(1) r = ScrollPanel.list_paginate @@ -551,7 +552,7 @@ describe ScrollPanel do end end - describe '自分のストーリー一覧ページ制御に於いて' do + describe '自分のスクコマ一覧ページ制御に於いて' do before do ScrollPanel.stub(:count).with(any_args).and_return(100) end @@ -559,7 +560,7 @@ describe ScrollPanel do r = ScrollPanel.mylist_paginate @author r.is_a?(Kaminari::PaginatableArray).should be_true end - it '自分のストーリー一覧の取得条件を利用している' do + it '自分のスクコマ一覧の取得条件を利用している' do ScrollPanel.stub(:mylist_where).with(any_args).and_return('') ScrollPanel.should_receive(:mylist_where).with(any_args).exactly(1) r = ScrollPanel.mylist_paginate @author @@ -571,7 +572,7 @@ describe ScrollPanel do end end - describe '他作家のストーリー一覧ページ制御に於いて' do + describe '他作家のスクコマ一覧ページ制御に於いて' do before do ScrollPanel.stub(:count).with(any_args).and_return(100) end @@ -579,7 +580,7 @@ describe ScrollPanel do r = ScrollPanel.himlist_paginate @other_author r.is_a?(Kaminari::PaginatableArray).should be_true end - it '他作家のストーリー一覧の取得条件を利用している' do + it '他作家のスクコマ一覧の取得条件を利用している' do ScrollPanel.stub(:himlist_where).with(any_args).and_return('') ScrollPanel.should_receive(:himlist_where).with(any_args).exactly(1) r = ScrollPanel.himlist_paginate @other_author @@ -596,11 +597,11 @@ describe ScrollPanel do r = ScrollPanel.list_opt r.should have(3).items end - it 'コミックを含んでいる' do + it 'スクロールを含んでいる' do r = ScrollPanel.list_opt r.has_key?(:scroll).should be_true end - it 'コミックは作家を含んでいる' do + it 'スクロールは作家を含んでいる' do r = ScrollPanel.list_opt r[:scroll].has_key?(:author).should be_true end @@ -666,11 +667,11 @@ describe ScrollPanel do r = ScrollPanel.show @scroll_panel.id, @author end end - it '指定のストーリーを返す' do + it '指定のスクコマを返す' do l = ScrollPanel.show @scroll_panel.id, @author l.should eq @scroll_panel end - context '他人のストーリーを開こうとしたとき' do + context '他人のスクコマを開こうとしたとき' do it '403Forbidden例外を返す' do ScrollPanel.any_instance.stub(:visible?).with(@other_author).and_return(false) lambda{ @@ -678,7 +679,7 @@ describe ScrollPanel do }.should raise_error(ActiveRecord::Forbidden) end end - context '存在しないストーリーを開こうとしたとき' do + context '存在しないスクコマを開こうとしたとき' do it '404RecordNotFound例外を返す' do lambda{ ScrollPanel.show 110, @author @@ -705,11 +706,11 @@ describe ScrollPanel do r = ScrollPanel.edit @scroll_panel.id, @author end end - it '指定のストーリーを返す' do + it '指定のスクコマを返す' do l = ScrollPanel.edit @scroll_panel.id, @author l.should eq @scroll_panel end - context '他人のストーリーを開こうとしたとき' do + context '他人のスクコマを開こうとしたとき' do it '403Forbidden例外を返す' do ScrollPanel.any_instance.stub(:own?).and_return(false) lambda{ @@ -717,7 +718,7 @@ describe ScrollPanel do }.should raise_error(ActiveRecord::Forbidden) end end - context '存在しないストーリーを開こうとしたとき' do + context '存在しないスクコマを開こうとしたとき' do it '404RecordNotFound例外を返す' do lambda{ ScrollPanel.edit 110, @author @@ -735,11 +736,11 @@ describe ScrollPanel do r = ScrollPanel.show_opt[:include] r.should have(3).items end - it 'コミックを含んでいる' do + it 'スクロールを含んでいる' do r = ScrollPanel.show_opt[:include] r.has_key?(:scroll).should be_true end - it 'コミックは作家を含んでいる' do + it 'スクロールは作家を含んでいる' do r = ScrollPanel.show_opt[:include] r[:scroll].has_key?(:author).should be_true end @@ -787,7 +788,7 @@ describe ScrollPanel do describe 'json単体取得オプションに於いて' do end - describe 'ストーリーのjson出力に於いて' do + describe 'スクコマのjson出力に於いて' do before do #コマを作成しておく。 @panel = FactoryGirl.create :panel, :author_id => @author.id @@ -854,7 +855,7 @@ describe ScrollPanel do end end - describe 'ストーリーリストのjson出力に於いて' do + describe 'スクコマリストのjson出力に於いて' do before do @panel = FactoryGirl.create :panel, :author_id => @author.id @scroll = FactoryGirl.create :scroll, :author_id => @author.id @@ -862,7 +863,7 @@ describe ScrollPanel do ScrollPanel.any_instance.stub(:scroll_panel_as_json).with(@author).and_return('{"s": 5}') end context 'つつがなく終わるとき' do - it 'ストーリーのjson出力を依頼している' do + it 'スクコマのjson出力を依頼している' do ScrollPanel.any_instance.should_receive(:scroll_panel_as_json).with(@author).exactly(1) r = ScrollPanel.list_as_json_text [@scroll_panel], @author end @@ -872,7 +873,7 @@ describe ScrollPanel do j = JSON.parse r j.is_a?(Array).should be_true end - it 'ストーリーを含んでいる' do + it 'スクコマを含んでいる' do r = ScrollPanel.list_as_json_text [@scroll_panel], @author j = JSON.parse r j.first.has_key?('s').should be_true @@ -927,7 +928,7 @@ describe ScrollPanel do @panel = FactoryGirl.create :panel, :author_id => @author.id end - context 'コミック初のコマなら' do + context 'スクロール初のコマなら' do it '0を補充値とする' do @scroll_panel = FactoryGirl.build :scroll_panel, :author_id => @author.id, :scroll_id => @scroll.id, :panel_id => @panel.id @scroll_panel.t = nil @@ -935,7 +936,7 @@ describe ScrollPanel do r.should eq 0 end end - context 'コミックに一個コマがあるとき' do + context 'スクロールに一個コマがあるとき' do it '1を補充値とする' do FactoryGirl.create :scroll_panel, :author_id => @author.id, :scroll_id => @scroll.id, :panel_id => @panel.id, :t => 0 @scroll_panel = FactoryGirl.build :scroll_panel, :author_id => @author.id, :scroll_id => @scroll.id, :panel_id => @panel.id @@ -944,7 +945,7 @@ describe ScrollPanel do r.should eq 1 end end - context 'コミックに2個コマがあるとき' do + context 'スクロールに2個コマがあるとき' do it '2を補充値とする' do FactoryGirl.create :scroll_panel, :author_id => @author.id, :scroll_id => @scroll.id, :panel_id => @panel.id, :t => 0 FactoryGirl.create :scroll_panel, :author_id => @author.id, :scroll_id => @scroll.id, :panel_id => @panel.id, :t => 1 @@ -994,20 +995,20 @@ describe ScrollPanel do @c2scroll_panel = FactoryGirl.create :scroll_panel, :t => 0, :scroll_id => @scroll2.id, :panel_id => @panel.id, :author_id => @author.id end context 'つつがなく終わるとき' do - it 'ストーリーから同一コミックのtだけを収集している' do + it 'スクコマから同一スクロールのtだけを収集している' do r = ScrollPanel.collect_t @scroll_panel r.should eq [0] end end context '複数コマのとき' do - it 'ストーリーから同一コミックのtだけを収集している' do + it 'スクコマから同一スクロールのtだけを収集している' do @scroll_panel2 = FactoryGirl.create :scroll_panel, :t => 1, :scroll_id => @scroll.id, :panel_id => @panel.id, :author_id => @author.id r = ScrollPanel.collect_t @scroll_panel r.sort.should eq [0, 1] end end - context '複数コマでヨソのコミックも混じっているとき' do - it 'ストーリーから同一コミックのtだけを収集している' do + context '複数コマでヨソのスクロールも混じっているとき' do + it 'スクコマから同一スクロールのtだけを収集している' do @scroll_panel2 = FactoryGirl.create :scroll_panel, :t => 1, :scroll_id => @scroll.id, :panel_id => @panel.id, :author_id => @author.id r = ScrollPanel.collect_t @scroll_panel r.sort.should eq [0, 1] @@ -1109,7 +1110,7 @@ describe ScrollPanel do l.sort.should eq [0, 1, 3, 4, 5] end end - context '先ほどのケース+他のコミック1件で挿入したとき' do + context '先ほどのケース+他のスクロール1件で挿入したとき' do before do @scroll2 = FactoryGirl.create :scroll, :author_id => @author.id @scroll_panelc2 = FactoryGirl.create :scroll_panel, :t => 0, :scroll_id => @scroll2.id, :panel_id => @panel.id, :author_id => @author.id @@ -1125,7 +1126,7 @@ describe ScrollPanel do l = ScrollPanel.find(:all, :conditions => ['scroll_id = ?', @scroll.id]).map {|s| s.t } l.sort.should eq [0, 1, 3, 4, 5] end - it '他のコミックに影響がない' do + it '他のスクロールに影響がない' do ot = @scroll_panelc2.t @scroll_panel6.insert_shift @scroll_panelc2.reload @@ -1225,7 +1226,7 @@ describe ScrollPanel do @scroll_panel3.t.should eq 3 end end - context '先ほどのケース+他のコミック1件で挿入したとき' do + context '先ほどのケース+他のスクロール1件で挿入したとき' do before do @scroll2 = FactoryGirl.create :scroll, :author_id => @author.id @scroll_panelc2 = FactoryGirl.create :scroll_panel, :t => 0, :scroll_id => @scroll2.id, :panel_id => @panel.id, :author_id => @author.id @@ -1262,7 +1263,7 @@ describe ScrollPanel do @scroll_panel3.reload @scroll_panel3.t.should eq 3 end - it '他のコミックに影響がない' do + it '他のスクロールに影響がない' do @scroll_panel4.lesser_shift @ot @scroll_panelc2.reload @scroll_panelc2.t.should eq 0 @@ -1386,7 +1387,7 @@ describe ScrollPanel do @scroll_panel4.t.should eq 2 end end - context '先ほどのケース+他のコミック1件で挿入したとき' do + context '先ほどのケース+他のスクロール1件で挿入したとき' do before do @scroll2 = FactoryGirl.create :scroll, :author_id => @author.id @scroll_panelc2 = FactoryGirl.create :scroll_panel, :t => 0, :scroll_id => @scroll2.id, :panel_id => @panel.id, :author_id => @author.id @@ -1424,7 +1425,7 @@ describe ScrollPanel do @scroll_panel4.reload @scroll_panel4.t.should eq 2 end - it '他のコミックに影響がない' do + it '他のスクロールに影響がない' do @scroll_panel2.higher_shift @ot @scroll_panelc2.reload @scroll_panelc2.t.should eq 0 @@ -1533,7 +1534,7 @@ describe ScrollPanel do r.should be_true end end - context 'コミックで引っかかるとき' do + context 'スクロールで引っかかるとき' do it 'falseを返す' do Panel.any_instance.stub(:usable?).with(any_args).and_return(true) Scroll.any_instance.stub(:own?).with(any_args).and_return(false) @@ -1549,7 +1550,7 @@ describe ScrollPanel do r.should be_false end end - context 'コミックまたはコマが指定されていなかったとき' do + context 'スクロールまたはコマが指定されていなかったとき' do it 'nilを返す' do Scroll.any_instance.stub(:own?).with(any_args).and_return(true) @scroll_panel.panel_id = nil @@ -1599,7 +1600,7 @@ describe ScrollPanel do end end #入れ替えテストと同じテストを実施。こちらはシフトだけでなく本尊も更新されている - context 'テーブルに5件(t:0,1,2,3,4)+他のコミック1件で2に挿入したとき' do + context 'テーブルに5件(t:0,1,2,3,4)+他のスクロール1件で2に挿入したとき' do before do @scroll2 = FactoryGirl.create :scroll, :author_id => @author.id @scroll_panelc2 = FactoryGirl.create :scroll_panel, :t => 0, :scroll_id => @scroll2.id, :panel_id => @panel.id, :author_id => @author.id @@ -1640,14 +1641,14 @@ describe ScrollPanel do @scroll_panel6.reload @scroll_panel6.t.should eq 2 end - it '他のコミックに影響がない' do + it '他のスクロールに影響がない' do @ot = @scroll_panelc2.t @scroll_panel6.store @scroll_panelc2.reload @scroll_panelc2.t.should eq @ot end end - context 'テーブルに5件(t:0,1,2,3,4)+他のコミック1件で3を1に移動したとき' do + context 'テーブルに5件(t:0,1,2,3,4)+他のスクロール1件で3を1に移動したとき' do before do @scroll2 = FactoryGirl.create :scroll, :author_id => @author.id @scroll_panelc2 = FactoryGirl.create :scroll_panel, :t => 0, :scroll_id => @scroll2.id, :panel_id => @panel.id, :author_id => @author.id @@ -1684,13 +1685,13 @@ describe ScrollPanel do @scroll_panel4.reload @scroll_panel4.t.should eq 1 end - it '他のコミックに影響がない' do + it '他のスクロールに影響がない' do @scroll_panel4.store @ot @scroll_panelc2.reload @scroll_panelc2.t.should eq 0 end end - context 'テーブルに5件(t:0,1,2,3,4)+他のコミック1件で1を3に移動したとき' do + context 'テーブルに5件(t:0,1,2,3,4)+他のスクロール1件で1を3に移動したとき' do before do @scroll2 = FactoryGirl.create :scroll, :author_id => @author.id @scroll_panelc2 = FactoryGirl.create :scroll_panel, :t => 0, :scroll_id => @scroll2.id, :panel_id => @panel.id, :author_id => @author.id @@ -1727,14 +1728,14 @@ describe ScrollPanel do @scroll_panel4.reload @scroll_panel4.t.should eq 2 end - it '他のコミックに影響がない' do + it '他のスクロールに影響がない' do @scroll_panel2.store @ot @scroll_panelc2.reload @scroll_panelc2.t.should eq 0 end end #ロールバックテスト。入れ替えが直接DBをいじるので、すべてのケースで確実にロールバックを確認する - context 'テーブルに5件(t:0,1,2,3,4)+他のコミック1件で2に挿入したが保存に失敗したとき' do + context 'テーブルに5件(t:0,1,2,3,4)+他のスクロール1件で2に挿入したが保存に失敗したとき' do before do ScrollPanel.any_instance.stub(:save).with(any_args).and_return(false) @scroll2 = FactoryGirl.create :scroll, :author_id => @author.id @@ -1766,7 +1767,7 @@ describe ScrollPanel do r.should be_false end end - context 'テーブルに5件(t:0,1,2,3,4)+他のコミック1件で3を1に移動したがシリアルチェックに失敗したとき' do + context 'テーブルに5件(t:0,1,2,3,4)+他のスクロール1件で3を1に移動したがシリアルチェックに失敗したとき' do before do ScrollPanel.stub(:validate_t).with(any_args).and_return(false) @scroll2 = FactoryGirl.create :scroll, :author_id => @author.id diff --git a/spec/models/scroll_spec.rb b/spec/models/scroll_spec.rb index 3b76b142..74796895 100644 --- a/spec/models/scroll_spec.rb +++ b/spec/models/scroll_spec.rb @@ -1,9 +1,10 @@ # -*- encoding: utf-8 -*- require 'spec_helper' -#コミック +#スクロール describe Scroll do before do + SpeechBalloonTemplate.delete_all @admin = FactoryGirl.create :admin @demand_user = FactoryGirl.create :demand_user @sp = FactoryGirl.create :system_picture @@ -343,19 +344,19 @@ describe Scroll do MagicNumber['run_mode'] = 1 Scroll.any_instance.stub(:reader_role_check).and_return(true) end - it '自分のコミックなら許可する' do + it '自分のスクロールなら許可する' do Scroll.any_instance.stub(:own?).and_return(true) Scroll.any_instance.stub(:visible).and_return(0) r = @scroll.visible?([@author]) r.should be_true end - it '他人の非公開コミックなら許可しない' do + it '他人の非公開スクロールなら許可しない' do Scroll.any_instance.stub(:own?).and_return(false) Scroll.any_instance.stub(:visible).and_return(0) r = @scroll.visible?([@author]) r.should be_false end - it '他人のコミックでも公開なら許可する' do + it '他人のスクロールでも公開なら許可する' do Scroll.any_instance.stub(:own?).and_return(false) Scroll.any_instance.stub(:visible).and_return(1) r = @scroll.visible?([@author]) @@ -404,13 +405,13 @@ describe Scroll do c = Scroll.list c.should eq [@scroll] end - it '非公開コミックは(自分のコミックであっても)含んでいない' do + it '非公開スクロールは(自分のスクロールであっても)含んでいない' do FactoryGirl.create :scroll, :author_id => @author.id, :visible => 0 c = Scroll.list c.should eq [@scroll] end it '時系列で並んでいる' do - #公開コミックは(他人のコミックであっても)含んでいる + #公開スクロールは(他人のスクロールであっても)含んでいる v = FactoryGirl.create :scroll, :author_id => @other_author.id, :updated_at => Time.now + 100 c = Scroll.list c.should eq [v, @scroll] @@ -443,7 +444,7 @@ describe Scroll do end end - describe '自分のコミック一覧取得に於いて' do + describe '自分のスクロール一覧取得に於いて' do before do @scroll = FactoryGirl.create :scroll, :author_id => @author.id end @@ -463,12 +464,12 @@ describe Scroll do cl = Scroll.mylist @author cl.should eq [nc, @scroll] end - it '他人のコミックは公開でも含まない' do + it '他人のスクロールは公開でも含まない' do nc = FactoryGirl.create :scroll, :author_id => @other_author.id, :visible => 1 cl = Scroll.mylist @author cl.should eq [@scroll] end - it '自分のコミックは非公開でも含んでいる' do + it '自分のスクロールは非公開でも含んでいる' do nc = FactoryGirl.create :scroll, :author_id => @author.id, :visible => 0, :updated_at => Time.now + 100 cl = Scroll.mylist @author cl.should eq [nc, @scroll] @@ -500,7 +501,7 @@ describe Scroll do end end - describe '他作家のコミック一覧取得に於いて' do + describe '他作家のスクロール一覧取得に於いて' do before do @scroll = FactoryGirl.create :scroll, :author_id => @author.id @other_scroll = FactoryGirl.create :scroll, :author_id => @other_author.id, :visible => 1 @@ -521,7 +522,7 @@ describe Scroll do r = Scroll.himlist @other_author r.should eq [nc, @other_scroll] end - it '公開コミックに限る ' do + it '公開スクロールに限る ' do hidden = FactoryGirl.create :scroll, :author_id => @other_author.id, :visible => 0 r = Scroll.himlist @other_author r.should eq [@other_scroll] @@ -553,7 +554,7 @@ describe Scroll do end end - describe 'コミック一覧ページ制御に於いて' do + describe 'スクロール一覧ページ制御に於いて' do before do Scroll.stub(:count).with(any_args).and_return(100) end @@ -561,7 +562,7 @@ describe Scroll do r = Scroll.list_paginate r.is_a?(Kaminari::PaginatableArray).should be_true end - it 'コミック一覧の取得条件を利用している' do + it 'スクロール一覧の取得条件を利用している' do Scroll.stub(:list_where).with(any_args).and_return('') Scroll.should_receive(:list_where).with(any_args).exactly(1) r = Scroll.list_paginate @@ -573,7 +574,7 @@ describe Scroll do end end - describe '自分のコミック一覧ページ制御に於いて' do + describe '自分のスクロール一覧ページ制御に於いて' do before do Scroll.stub(:count).with(any_args).and_return(100) end @@ -581,7 +582,7 @@ describe Scroll do r = Scroll.mylist_paginate @author r.is_a?(Kaminari::PaginatableArray).should be_true end - it '自分のコミック一覧の取得条件を利用している' do + it '自分のスクロール一覧の取得条件を利用している' do Scroll.stub(:mylist_where).with(any_args).and_return('') Scroll.should_receive(:mylist_where).with(any_args).exactly(1) r = Scroll.mylist_paginate @author @@ -593,7 +594,7 @@ describe Scroll do end end - describe '他作家のコミック一覧ページ制御に於いて' do + describe '他作家のスクロール一覧ページ制御に於いて' do before do Scroll.stub(:count).with(any_args).and_return(100) end @@ -601,7 +602,7 @@ describe Scroll do r = Scroll.himlist_paginate @other_author r.is_a?(Kaminari::PaginatableArray).should be_true end - it '他作家のコミック一覧の取得条件を利用している' do + it '他作家のスクロール一覧の取得条件を利用している' do Scroll.stub(:himlist_where).with(any_args).and_return('') Scroll.should_receive(:himlist_where).with(any_args).exactly(1) r = Scroll.himlist_paginate @other_author @@ -618,11 +619,11 @@ describe Scroll do r = Scroll.list_opt r.should have(2).items end - it 'ストーリーを含んでいる' do + it 'スクコマを含んでいる' do r = Scroll.list_opt r.has_key?(:scroll_panels).should be_true end - it 'ストーリーはコマを含んでいる' do + it 'スクコマはコマを含んでいる' do r = Scroll.list_opt r[:scroll_panels].has_key?(:panel).should be_true end @@ -641,13 +642,13 @@ describe Scroll do @panel = FactoryGirl.create :panel, :author_id => @author.id, :publish => 1 @scroll_panel = FactoryGirl.create :scroll_panel, :author_id => @author.id, :scroll_id => @scroll.id, :panel_id => @panel.id end - it 'ストーリーを含んでいる' do + it 'スクコマを含んでいる' do r = Scroll.list.to_json Scroll.list_json_opt j = JSON.parse r i = j.first i.has_key?('scroll_panels').should be_true end - it 'ストーリーはコマを含んでいる' do + it 'スクコマはコマを含んでいる' do r = Scroll.list.to_json Scroll.list_json_opt j = JSON.parse r i = j.first @@ -678,7 +679,7 @@ describe Scroll do r = Scroll.show @scroll.id, @author end end - it '指定のコミックを返す' do + it '指定のスクロールを返す' do c = Scroll.show @scroll.id, @author c.should eq @scroll end @@ -690,7 +691,7 @@ describe Scroll do }.should raise_error(ActiveRecord::Forbidden) end end - context '存在しないコミックを開こうとしたとき' do + context '存在しないスクロールを開こうとしたとき' do it '404RecordNotFound例外を返す' do lambda{ Scroll.show 110, @author @@ -715,12 +716,12 @@ describe Scroll do r = Scroll.edit @scroll.id, @author end end - it '指定のコミックを返す' do + it '指定のスクロールを返す' do Scroll.any_instance.stub(:own?).and_return(true) c = Scroll.edit @scroll.id, @author.id c.should eq @scroll end - context '他人のコミックを開こうとしたとき' do + context '他人のスクロールを開こうとしたとき' do it '403Forbidden例外を返す' do Scroll.any_instance.stub(:own?).and_return(false) lambda{ @@ -728,7 +729,7 @@ describe Scroll do }.should raise_error(ActiveRecord::Forbidden) end end - context '存在しないコミックを開こうとしたとき' do + context '存在しないスクロールを開こうとしたとき' do it '404RecordNotFound例外を返す' do lambda{ Scroll.edit 110, @author @@ -749,11 +750,11 @@ describe Scroll do r = Scroll.show_opt[:include] r.has_key?(:author).should be_true end - it 'ストーリーを含んでいる' do + it 'スクコマを含んでいる' do r = Scroll.show_opt[:include] r.has_key?(:scroll_panels).should be_true end - it 'ストーリーはコマを含んでいる' do + it 'スクコマはコマを含んでいる' do r = Scroll.show_opt[:include] r[:scroll_panels].has_key?(:panel).should be_true end @@ -768,13 +769,13 @@ describe Scroll do @panel = FactoryGirl.create :panel, :author_id => @author.id, :publish => 1 @scroll_panel = FactoryGirl.create :scroll_panel, :author_id => @author.id, :scroll_id => @scroll.id, :panel_id => @panel.id end - it 'ストーリーを含んでいる' do + it 'スクコマを含んでいる' do r = Scroll.show(@scroll.id, @author).to_json Scroll.show_json_opt j = JSON.parse r i = j i.has_key?('scroll_panels').should be_true end - it 'ストーリーはコマを含んでいる' do + it 'スクコマはコマを含んでいる' do r = Scroll.show(@scroll.id, @author).to_json Scroll.show_json_opt j = JSON.parse r i = j @@ -806,7 +807,7 @@ describe Scroll do r = Scroll.find @scroll.id }.should raise_error end - it '自身にリンクしているストーリーをすべて削除する' do + it '自身にリンクしているスクコマをすべて削除する' do lambda { r = @scroll.destroy_with_scroll_panel }.should change(ScrollPanel, :count).by(-1) diff --git a/spec/models/sheet_panel_spec.rb b/spec/models/sheet_panel_spec.rb new file mode 100644 index 00000000..33cba57f --- /dev/null +++ b/spec/models/sheet_panel_spec.rb @@ -0,0 +1,2002 @@ +# -*- encoding: utf-8 -*- +require 'spec_helper' +#紙コマ +describe SheetPanel do + before do + SpeechBalloonTemplate.delete_all + @admin = FactoryGirl.create :admin + @sp = FactoryGirl.create :system_picture + @lg = FactoryGirl.create :license_group + @license = FactoryGirl.create :license, :license_group_id => @lg.id, :system_picture_id => @sp.id + SpeechBalloonTemplate.delete_all + @speech_balloon_template = FactoryGirl.create(:speech_balloon_template, "name" => "circle@pettan.com", "classname" => "CircleSpeechBalloon", "caption" => "cc", "system_picture_id" => @sp.id, "settings" => '{}') + @writing_format = FactoryGirl.create :writing_format + @user = FactoryGirl.create( :user_yas) + @author = FactoryGirl.create :author, :user_id => @user.id + @artist = FactoryGirl.create :artist_yas, :author_id => @author.id + @other_user = FactoryGirl.create( :user_yas) + @other_author = FactoryGirl.create :author, :user_id => @other_user.id + @op = FactoryGirl.create :original_picture, :artist_id => @artist.id + @p = FactoryGirl.create :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id + @rp = FactoryGirl.create :resource_picture, :artist_id => @artist.id, :license_id => @license.id, :original_picture_id => @op.id, :picture_id => @p.id + end + + describe '検証に於いて' do + before do + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @panel = FactoryGirl.create :panel, :author_id => @author.id + @sheet_panel = FactoryGirl.build :sheet_panel, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + end + + context 'オーソドックスなデータのとき' do + it '下限データが通る' do + @sheet_panel.x = -99999 + @sheet_panel.y = -99999 + @sheet_panel.z = 1 + @sheet_panel.t = 0 + @sheet_panel.should be_valid + end + it '上限データが通る' do + @sheet_panel.x = 99999 + @sheet_panel.y = 99999 + @sheet_panel.z = 99999 + @sheet_panel.t = 99999 + @sheet_panel.should be_valid + end + end + + context 'sheet_idを検証するとき' do + it 'nullなら失敗する' do + @sheet_panel.sheet_id = nil + @sheet_panel.should_not be_valid + end + it '数値でなければ失敗する' do + @sheet_panel.sheet_id = 'a' + @sheet_panel.should_not be_valid + end + it '存在する用紙でなければ失敗する' do + @sheet_panel.sheet_id = 0 + @sheet_panel.should_not be_valid + end + end + + context 'panel_idを検証するとき' do + it 'nullなら失敗する' do + @sheet_panel.panel_id = nil + @sheet_panel.should_not be_valid + end + it '数値でなければ失敗する' do + @sheet_panel.panel_id = 'a' + @sheet_panel.should_not be_valid + end + it '存在するコマでなければ失敗する' do + @sheet_panel.panel_id = 0 + @sheet_panel.should_not be_valid + end + end + + context 'xを検証するとき' do + it 'nullなら失敗する' do + @sheet_panel.x = nil + @sheet_panel.should_not be_valid + end + it '数値でなければ失敗する' do + @sheet_panel.x = 'a' + @sheet_panel.should_not be_valid + end + it '0なら通る' do + @sheet_panel.x = '0' + @sheet_panel.should be_valid + end + it '負でも通る' do + @sheet_panel.x = -1 + @sheet_panel.should be_valid + end + end + context 'yを検証するとき' do + it 'nullなら失敗する' do + @sheet_panel.y = nil + @sheet_panel.should_not be_valid + end + it '数値でなければ失敗する' do + @sheet_panel.y = 'a' + @sheet_panel.should_not be_valid + end + it '0なら通る' do + @sheet_panel.y = '0' + @sheet_panel.should be_valid + end + it '負でも通る' do + @sheet_panel.y = -1 + @sheet_panel.should be_valid + end + end + context 'zを検証するとき' do + it 'nullなら失敗する' do + @sheet_panel.z = nil + @sheet_panel.should_not be_valid + end + it '数値でなければ失敗する' do + @sheet_panel.z = 'a' + @sheet_panel.should_not be_valid + end + it '負なら失敗する' do + @sheet_panel.z = -1 + @sheet_panel.should_not be_valid + end + it '0なら失敗する' do + @sheet_panel.z = 0 + @sheet_panel.should_not be_valid + end + end + context 'tを検証するとき' do + it 'nullなら失敗する' do + @sheet_panel.t = nil + @sheet_panel.should_not be_valid + end + it '数値でなければ失敗する' do + @sheet_panel.t = 'a' + @sheet_panel.should_not be_valid + end + it '負なら失敗する' do + @sheet_panel.t = -1 + @sheet_panel.should_not be_valid + end + end + + context 'author_idを検証するとき' do + it 'nullなら失敗する' do + @sheet_panel.author_id = nil + @sheet_panel.should_not be_valid + end + it '数値でなければ失敗する' do + @sheet_panel.author_id = 'a' + @sheet_panel.should_not be_valid + end + it '存在する作家でなければ失敗する' do + @sheet_panel.author_id = 0 + @sheet_panel.should_not be_valid + end + end + context '全体を検証するとき' do + end + end + + describe 'デフォルト値補充に於いて' do + before do + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @panel = FactoryGirl.create :panel, :author_id => @author.id + end + + #dbのデフォルト値が0だから明示的にnilにしないと追加ができない + it 'tをnilにする' do + @sheet_panel = FactoryGirl.build :sheet_panel, :sheet_id => @sheet.id, :panel_id => @panel.id + @sheet_panel.supply_default + @sheet_panel.t.should be_nil + end + + end + + describe '上書き補充に於いて' do + before do + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @panel = FactoryGirl.create :panel, :author_id => @author.id + end + + context 'author_idを補充' do + it '問答無用でauthor_idを補充する' do + @sheet_panel = FactoryGirl.build :sheet_panel, :sheet_id => @sheet.id, :panel_id => @panel.id + @sheet_panel.author_id = nil + @sheet_panel.overwrite @author + @sheet_panel.author_id.should eq @author.id + end + end + + end + + describe '所持判定に於いて' do + before do + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @panel = FactoryGirl.create :panel, :author_id => @author.id + @sheet_panel = FactoryGirl.create :sheet_panel, :author_id => @author.id, :sheet_id => @sheet.id, :panel_id => @panel.id + @sheeto = FactoryGirl.create :sheet, :author_id => @other_author.id + @panelo = FactoryGirl.create :panel, :author_id => @other_author.id + @sheet_panelo = FactoryGirl.create :sheet_panel, :author_id => @other_author.id, :sheet_id => @sheeto.id, :panel_id => @panelo.id + end + context '事前チェックする' do + it '自身にロールリストからの作家取得を依頼している' do + SheetPanel.should_receive(:get_author_from_roles).with(any_args).exactly(1) + r = @sheet_panel.own?([@author]) + end + end + context 'ロール内作家が取得できるとき' do + before do + end + it 'ロール内作家のidが自身の作家idと一致するなら許可する' do + SheetPanel.stub(:get_author_from_roles).with(any_args).and_return(@author) + r = @sheet_panel.own?([@author]) + r.should be_true + end + it 'ロール内作家のidが自身の作家idと一致しないならno' do + SheetPanel.stub(:get_author_from_roles).with(any_args).and_return(@other_author) + @sheet_panel.own?(@other_author).should be_false + end + end + context 'ロール内作家が取得できないとき' do + before do + SheetPanel.stub(:get_author_from_roles).with(any_args).and_return(nil) + end + it 'Falseを返す' do + r = @sheet_panel.own?([@author]) + r.should be_false + end + end + end + + describe '閲覧許可に於いて' do + before do + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @panel = FactoryGirl.create :panel, :author_id => @author.id + @sheet_panel = FactoryGirl.create :sheet_panel, :author_id => @author.id, :sheet_id => @sheet.id, :panel_id => @panel.id + end + context 'オープンモードのとき' do + before do + MagicNumber['run_mode'] = 0 + end + it '自身にゲスト用ロールチェックを問い合わせしている' do + SheetPanel.any_instance.stub(:guest_role_check).and_return(true) + SheetPanel.any_instance.should_receive(:guest_role_check).with(any_args).exactly(1) + r = @sheet_panel.visible?([@author]) + end + it 'ゲスト用ロールチェックが失敗したとき、falseを返す' do + SheetPanel.any_instance.stub(:guest_role_check).and_return(false) + r = @sheet_panel.visible?([@author]) + r.should be_false + end + end + context 'クローズドモードのとき' do + before do + MagicNumber['run_mode'] = 1 + end + it '自身に読者用ロールチェックを問い合わせしている' do + SheetPanel.any_instance.stub(:reader_role_check).and_return(true) + SheetPanel.any_instance.should_receive(:reader_role_check).with(any_args).exactly(1) + r = @sheet_panel.visible?([@author]) + end + it '読者用ロールチェックが失敗したとき、falseを返す' do + SheetPanel.any_instance.stub(:reader_role_check).and_return(false) + r = @sheet_panel.visible?([@author]) + r.should be_false + end + end + context '事前チェックする' do + before do + MagicNumber['run_mode'] = 1 + SheetPanel.any_instance.stub(:reader_role_check).and_return(true) + end + it '自身の用紙に所持判定を問い合わせしている' do + Sheet.any_instance.stub(:own?).and_return(true) + Sheet.any_instance.should_receive(:own?).with(any_args).exactly(1) + r = @sheet_panel.visible?([@author]) + end + it '自身の用紙に閲覧許可を問い合わせしている' do + Sheet.any_instance.stub(:own?).and_return(false) + Sheet.any_instance.stub(:visible?).and_return(true) + Sheet.any_instance.should_receive(:visible?).with(any_args).exactly(1) + r = @sheet_panel.visible?([@author]) + end + end + context 'つつがなく終わるとき' do + before do + MagicNumber['run_mode'] = 1 + SheetPanel.any_instance.stub(:reader_role_check).and_return(true) + end + it '自分の用紙の紙コマなら許可する' do + Sheet.any_instance.stub(:own?).and_return(true) + Sheet.any_instance.stub(:visible).and_return(0) + r = @sheet_panel.visible?([@author]) + r.should be_true + end + it '他人の非公開用紙の紙コマなら許可しない' do + Sheet.any_instance.stub(:own?).and_return(false) + Sheet.any_instance.stub(:visible).and_return(0) + r = @sheet_panel.visible?([@author]) + r.should be_false + end + it '他人の用紙の紙コマでも公開なら許可する' do + Sheet.any_instance.stub(:own?).and_return(false) + Sheet.any_instance.stub(:visible).and_return(1) + r = @sheet_panel.visible?([@author]) + r.should be_true + end + end + end + + describe 'プレイリスト取得に於いて' do + before do + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @panel = FactoryGirl.create :panel, :author_id => @author.id + @sheet_panel = FactoryGirl.create :sheet_panel, :author_id => @author.id, :sheet_id => @sheet.id, :panel_id => @panel.id + @panel2 = FactoryGirl.create :panel, :author_id => @author.id, :publish => 0 + @other_sheet = FactoryGirl.create :sheet, :author_id => @other_author.id, :visible => 1 + @other_panel = FactoryGirl.create :panel, :author_id => @other_author.id, :publish => 1 + end + context 'offset補正について' do + it '文字列から数値に変換される' do + SheetPanel.offset(100, '8').should eq 8 + end + it 'nilの場合は0になる' do + SheetPanel.offset(100).should eq 0 + end + #投稿されたコマ数以上の値が指定されたときは、最後のコマだけになる + #最後のコマとは、コマ数‐1. + it '1件のときオフセット1なら0になる' do + SheetPanel.offset(1, '1').should eq 0 + end + it '5件のときオフセット5なら4になる' do + SheetPanel.offset(5, '5').should eq 4 + end + # 負の値が指定されたときは、最後のコマから数えてコマを飛ばして表示する。 + #-4のときは、最後から4つのコマを表示する。 + it '2件のときオフセット-1なら1になる' do + SheetPanel.offset(2, '-1').should eq 1 + end + it '5件のときオフセット-2なら3になる' do + SheetPanel.offset(5, '-2').should eq 3 + end + # 最終的なが負になるなど、不正な値が入ったときは0となる。 + it '2件のときオフセット-5なら0になる' do + SheetPanel.offset(2, '-5').should eq 0 + end + end + context 'panel_count補正について' do + it '文字列から数値に変換される' do + SheetPanel.panel_count(100, '7').should eq 7 + end + it 'nilの場合はSheetPanel.default_panel_sizeになる' do + SheetPanel.panel_count(100).should eq SheetPanel.default_panel_size + end + it '0以下の場合はSheetPanel.default_panel_sizeになる' do + SheetPanel.panel_count(100, '0').should eq SheetPanel.default_panel_size + end + it 'SheetPanel.max_panel_sizeを超えた場合はSheetPanel.max_panel_sizeになる' do + SheetPanel.panel_count(100, '1000').should eq SheetPanel.max_panel_size + end + end + it 'リストを返す' do + c = SheetPanel.play_list @sheet, @author + c.should eq [@sheet_panel] + end + it 't順で並んでいる' do + #公開用紙の公開コマは(他人の用紙であっても)含んでいる + v = FactoryGirl.create :sheet_panel, :author_id => @author.id, :sheet_id => @sheet.id, :panel_id => @panel.id, :t => 1 + c = SheetPanel.play_list @sheet, @author + c.should eq [ @sheet_panel, v] + end + it '非公開のコマは含んでいる' do + h = FactoryGirl.create :sheet_panel, :author_id => @author.id, :sheet_id => @sheet.id, :panel_id => @panel2.id, :t => 1 + c = SheetPanel.play_list @sheet, @author + c.should eq [ @sheet_panel, h] + end + context 'DBに5件あって1ページの件数を2件に変えたとして' do + before do + @sheet_panel2 = FactoryGirl.create :sheet_panel, :author_id => @author.id, :sheet_id => @sheet.id, :panel_id => @panel.id, :t => 1 + @sheet_panel3 = FactoryGirl.create :sheet_panel, :author_id => @author.id, :sheet_id => @sheet.id, :panel_id => @panel.id, :t => 2 + @sheet_panel4 = FactoryGirl.create :sheet_panel, :author_id => @author.id, :sheet_id => @sheet.id, :panel_id => @panel.id, :t => 3 + @sheet_panel5 = FactoryGirl.create :sheet_panel, :author_id => @author.id, :sheet_id => @sheet.id, :panel_id => @panel.id, :t => 4 + end + it 'offset=0なら末尾2件を返す' do + #時系列で並んでいる + c = SheetPanel.play_list( @sheet, @author, 0, 2) + c.should eq [@sheet_panel, @sheet_panel2] + end + it 'offset=2なら中間2件を返す' do + c = SheetPanel.play_list(@sheet, @author, 2, 2) + c.should eq [@sheet_panel3, @sheet_panel4] + end + it 'offset=4なら先頭1件を返す' do + c = SheetPanel.play_list(@sheet, @author, 4, 2) + c.should eq [@sheet_panel5] + end + end + end + + describe '一覧取得に於いて' do + before do + @sheet = FactoryGirl.create :sheet, :author_id => @author.id, :visible => 1 + @panel = FactoryGirl.create :panel, :author_id => @author.id + @sheet_panel = FactoryGirl.create :sheet_panel, :author_id => @author.id, :sheet_id => @sheet.id, :panel_id => @panel.id + @other_sheet = FactoryGirl.create :sheet, :author_id => @other_author.id, :visible => 1 + @other_panel = FactoryGirl.create :panel, :author_id => @other_author.id, :publish => 1 + @hidden_sheet = FactoryGirl.create :sheet, :author_id => @author.id, :visible => 0 + end + context 'page補正について' do + it '文字列から数値に変換される' do + SheetPanel.page('8').should eq 8 + end + it 'nilの場合は1になる' do + SheetPanel.page().should eq 1 + end + it '0以下の場合は1になる' do + SheetPanel.page('0').should eq 1 + end + end + context 'page_size補正について' do + it '文字列から数値に変換される' do + SheetPanel.page_size('7').should eq 7 + end + it 'nilの場合はSheetPanel.default_page_sizeになる' do + SheetPanel.page_size().should eq SheetPanel.default_page_size + end + it '0以下の場合はSheetPanel.default_page_sizeになる' do + SheetPanel.page_size('0').should eq SheetPanel.default_page_size + end + it 'SheetPanel.max_page_sizeを超えた場合はSheetPanel.max_page_sizeになる' do + SheetPanel.page_size('1000').should eq SheetPanel.max_page_size + end + end + it 'リストを返す' do + c = SheetPanel.list + c.should eq [@sheet_panel] + end + it '時系列で並んでいる' do + #公開用紙のSheetPanelは(他人のSheetPanelであっても)含んでいる + v = FactoryGirl.create :sheet_panel, :author_id => @other_author.id, :sheet_id => @other_sheet.id, :panel_id => @other_panel.id, :t => 0, :updated_at => Time.now + 100 + c = SheetPanel.list + c.should eq [ v, @sheet_panel] + end + it '非公開の紙コマは(自分の紙コマであっても)含まない' do + h = FactoryGirl.create :sheet_panel, :author_id => @author.id, :sheet_id => @hidden_sheet.id, :panel_id => @panel.id, :t => 0 + c = SheetPanel.list + c.should eq [ @sheet_panel] + end + context 'DBに5件あって1ページの件数を2件に変えたとして' do + before do + @sheet_panel2 = FactoryGirl.create :sheet_panel, :author_id => @author.id, :sheet_id => @sheet.id, :panel_id => @panel.id, :t => 1, :updated_at => Time.now + 100 + @sheet_panel3 = FactoryGirl.create :sheet_panel, :author_id => @author.id, :sheet_id => @sheet.id, :panel_id => @panel.id, :t => 2, :updated_at => Time.now + 200 + @sheet_panel4 = FactoryGirl.create :sheet_panel, :author_id => @author.id, :sheet_id => @sheet.id, :panel_id => @panel.id, :t => 3, :updated_at => Time.now + 300 + @sheet_panel5 = FactoryGirl.create :sheet_panel, :author_id => @author.id, :sheet_id => @sheet.id, :panel_id => @panel.id, :t => 4, :updated_at => Time.now + 400 + end + it '通常は2件を返す' do + l = SheetPanel.list 1, 2 + l.should have(2).items + end + it 'page=1なら末尾2件を返す' do + #時系列で並んでいる + l = SheetPanel.list 1, 2 + l.should eq [@sheet_panel5, @sheet_panel4] + end + it 'page=2なら中間2件を返す' do + l = SheetPanel.list 2, 2 + l.should eq [@sheet_panel3, @sheet_panel2] + end + it 'page=3なら先頭1件を返す' do + l = SheetPanel.list 3, 2 + l.should eq [@sheet_panel] + end + end + end + + describe '自分の紙コマ一覧取得に於いて' do + before do + @sheet = FactoryGirl.create :sheet, :author_id => @author.id, :visible => 1 + @panel = FactoryGirl.create :panel, :author_id => @author.id, :publish => 1 + @sheet_panel = FactoryGirl.create :sheet_panel, :author_id => @author.id, :sheet_id => @sheet.id, :panel_id => @panel.id + @other_sheet = FactoryGirl.create :sheet, :author_id => @other_author.id, :visible => 1 + @other_panel = FactoryGirl.create :panel, :author_id => @other_author.id, :publish => 1 + @hsheet = FactoryGirl.create :sheet, :author_id => @author.id, :visible => 0 + @hpanel = FactoryGirl.create :panel, :author_id => @author.id, :publish => 0 + end + context 'つつがなく終わるとき' do + it '一覧取得オプションを利用している' do + SheetPanel.stub(:list_opt).with(any_args).and_return({}) + SheetPanel.should_receive(:list_opt).with(any_args).exactly(1) + r = SheetPanel.mylist @author + end + end + it 'リストを返す' do + s = SheetPanel.mylist @author + s.should eq [@sheet_panel] + end + it '時系列で並んでいる' do + ns = FactoryGirl.create :sheet_panel, :author_id => @author.id, :sheet_id => @sheet.id, :panel_id => @panel.id, :t => 1, :updated_at => Time.now + 100 + sl = SheetPanel.mylist @author + sl.should eq [ns, @sheet_panel] + end + it '他人の紙コマはコマ用紙ともに公開でも含まない' do + so = FactoryGirl.create :sheet_panel, :author_id => @other_author.id, :sheet_id => @other_sheet.id, :panel_id => @other_panel.id + sl = SheetPanel.mylist @author + sl.should eq [@sheet_panel] + end + it '自分の紙コマはコマ用紙ともに非公開でも含んでいる' do + hs = FactoryGirl.create :sheet_panel, :author_id => @author.id, :sheet_id => @hsheet.id, :panel_id => @hpanel.id, :updated_at => Time.now + 100 + sl = SheetPanel.mylist @author + sl.should eq [hs, @sheet_panel] + end + context 'DBに5件あって1ページの件数を2件に変えたとして' do + before do + @sheet_panel2 = FactoryGirl.create :sheet_panel, :author_id => @author.id, :sheet_id => @sheet.id, :panel_id => @panel.id, :t => 1, :updated_at => Time.now + 100 + @sheet_panel3 = FactoryGirl.create :sheet_panel, :author_id => @author.id, :sheet_id => @sheet.id, :panel_id => @panel.id, :t => 2, :updated_at => Time.now + 200 + @sheet_panel4 = FactoryGirl.create :sheet_panel, :author_id => @author.id, :sheet_id => @sheet.id, :panel_id => @panel.id, :t => 3, :updated_at => Time.now + 300 + @sheet_panel5 = FactoryGirl.create :sheet_panel, :author_id => @author.id, :sheet_id => @sheet.id, :panel_id => @panel.id, :t => 4, :updated_at => Time.now + 400 + SheetPanel.stub(:default_page_size).and_return(2) + end + it '通常は2件を返す' do + l = SheetPanel.mylist @author, 1, 2 + l.should have(2).items + end + it 'page=1なら末尾2件を返す' do + #時系列で並んでいる + l = SheetPanel.mylist @author, 1, 2 + l.should eq [@sheet_panel5, @sheet_panel4] + end + it 'page=2なら中間2件を返す' do + l = SheetPanel.mylist @author, 2, 2 + l.should eq [@sheet_panel3, @sheet_panel2] + end + it 'page=3なら先頭1件を返す' do + l = SheetPanel.mylist @author, 3, 2 + l.should eq [@sheet_panel] + end + end + end + + describe '他作家の紙コマ一覧取得に於いて' do + before do + @sheet = FactoryGirl.create :sheet, :author_id => @author.id, :visible => 1 + @panel = FactoryGirl.create :panel, :author_id => @author.id, :publish => 1 + @sheet_panel = FactoryGirl.create :sheet_panel, :author_id => @author.id, :sheet_id => @sheet.id, :panel_id => @panel.id + @other_sheet = FactoryGirl.create :sheet, :author_id => @other_author.id, :visible => 1 + @other_panel = FactoryGirl.create :panel, :author_id => @other_author.id, :publish => 1 + @other_sheet_panel = FactoryGirl.create :sheet_panel, :author_id => @other_author.id, :sheet_id => @other_sheet.id, :panel_id => @other_panel.id + end + it 'リストを返す' do + r = SheetPanel.himlist @other_author + r.should eq [@other_sheet_panel] + end + it '時系列で並んでいる' do + ns = FactoryGirl.create :sheet_panel, :author_id => @other_author.id, :sheet_id => @other_sheet.id, :panel_id => @other_panel.id, :t => 1, :updated_at => Time.now + 100 + r = SheetPanel.himlist @other_author + r.should eq [ns, @other_sheet_panel] + end + it '公開用紙の紙コマ' do + @hsheet = FactoryGirl.create :sheet, :author_id => @other_author.id, :visible => 0 + ns = FactoryGirl.create :sheet_panel, :author_id => @other_author.id, :sheet_id => @hsheet.id, :panel_id => @other_panel.id, :t => 1, :updated_at => Time.now + 100 + r = SheetPanel.himlist @other_author + r.should eq [@other_sheet_panel] + end + context 'DBに5件あって1ページの件数を2件に変えたとして' do + before do + @other_sheet_panel2 = FactoryGirl.create :sheet_panel, :author_id => @other_author.id, :sheet_id => @other_sheet.id, :panel_id => @other_panel.id, :t => 1, :updated_at => Time.now + 100 + @other_sheet_panel3 = FactoryGirl.create :sheet_panel, :author_id => @other_author.id, :sheet_id => @other_sheet.id, :panel_id => @other_panel.id, :t => 2, :updated_at => Time.now + 200 + @other_sheet_panel4 = FactoryGirl.create :sheet_panel, :author_id => @other_author.id, :sheet_id => @other_sheet.id, :panel_id => @other_panel.id, :t => 3, :updated_at => Time.now + 300 + @other_sheet_panel5 = FactoryGirl.create :sheet_panel, :author_id => @other_author.id, :sheet_id => @other_sheet.id, :panel_id => @other_panel.id, :t => 4, :updated_at => Time.now + 400 + SheetPanel.stub(:default_page_size).and_return(2) + end + it '通常は2件を返す' do + l = SheetPanel.himlist @other_author, 1, 2 + l.should have(2).items + end + it 'page=1なら末尾2件を返す' do + #時系列で並んでいる + l = SheetPanel.himlist @other_author, 1, 2 + l.should eq [@other_sheet_panel5, @other_sheet_panel4] + end + it 'page=2なら中間2件を返す' do + l = SheetPanel.himlist @other_author, 2, 2 + l.should eq [@other_sheet_panel3, @other_sheet_panel2] + end + it 'page=3なら先頭1件を返す' do + l = SheetPanel.himlist @other_author, 3, 2 + l.should eq [@other_sheet_panel] + end + end + end + + describe '紙コマ一覧ページ制御に於いて' do + before do + SheetPanel.stub(:count).with(any_args).and_return(100) + end + it 'ページ制御を返す' do + r = SheetPanel.list_paginate + r.is_a?(Kaminari::PaginatableArray).should be_true + end + it '紙コマ一覧の取得条件を利用している' do + SheetPanel.stub(:list_where).with(any_args).and_return('') + SheetPanel.should_receive(:list_where).with(any_args).exactly(1) + r = SheetPanel.list_paginate + end + it 'ページ件数10のとき、3ページ目のオフセットは20から始まる' do + r = SheetPanel.list_paginate 3, 10 + r.limit_value.should eq 10 + r.offset_value.should eq 20 + end + end + + describe '自分の紙コマ一覧ページ制御に於いて' do + before do + SheetPanel.stub(:count).with(any_args).and_return(100) + end + it 'ページ制御を返す' do + r = SheetPanel.mylist_paginate @author + r.is_a?(Kaminari::PaginatableArray).should be_true + end + it '自分の紙コマ一覧の取得条件を利用している' do + SheetPanel.stub(:mylist_where).with(any_args).and_return('') + SheetPanel.should_receive(:mylist_where).with(any_args).exactly(1) + r = SheetPanel.mylist_paginate @author + end + it 'ページ件数10のとき、3ページ目のオフセットは20から始まる' do + r = SheetPanel.mylist_paginate @author, 3, 10 + r.limit_value.should eq 10 + r.offset_value.should eq 20 + end + end + + describe '他作家の紙コマ一覧ページ制御に於いて' do + before do + SheetPanel.stub(:count).with(any_args).and_return(100) + end + it 'ページ制御を返す' do + r = SheetPanel.himlist_paginate @other_author + r.is_a?(Kaminari::PaginatableArray).should be_true + end + it '他作家の紙コマ一覧の取得条件を利用している' do + SheetPanel.stub(:himlist_where).with(any_args).and_return('') + SheetPanel.should_receive(:himlist_where).with(any_args).exactly(1) + r = SheetPanel.himlist_paginate @other_author + end + it 'ページ件数10のとき、3ページ目のオフセットは20から始まる' do + r = SheetPanel.himlist_paginate @other_author, 3, 10 + r.limit_value.should eq 10 + r.offset_value.should eq 20 + end + end + + describe 'list関連テーブルプションに於いて' do + it '3つの項目を含んでいる' do + r = SheetPanel.list_opt + r.should have(3).items + end + it '用紙を含んでいる' do + r = SheetPanel.list_opt + r.has_key?(:sheet).should be_true + end + it '用紙は作家を含んでいる' do + r = SheetPanel.list_opt + r[:sheet].has_key?(:author).should be_true + end + it '作家を含んでいる' do + r = SheetPanel.list_opt + r.has_key?(:author).should be_true + end + it 'コマを含んでいる' do + r = SheetPanel.list_opt + r.has_key?(:panel).should be_true + end + it 'コマは作家を含んでいる' do + r = SheetPanel.list_opt + r[:panel].has_key?(:author).should be_true + end + it 'コマはコマ絵を含んでいる' do + r = SheetPanel.list_opt + r[:panel].has_key?(:panel_pictures).should be_true + end + it 'コマ絵は実素材を含んでいる' do + r = SheetPanel.list_opt + r[:panel][:panel_pictures].has_key?(:picture).should be_true + end + it '実素材は絵師を含んでいる' do + r = SheetPanel.list_opt + r[:panel][:panel_pictures][:picture].has_key?(:artist).should be_true + end + it '実素材はライセンスを含んでいる' do + r = SheetPanel.list_opt + r[:panel][:panel_pictures][:picture].has_key?(:license).should be_true + end + it 'コマはフキダシを含んでいる' do + r = SheetPanel.list_opt + r[:panel].has_key?(:speech_balloons).should be_true + end + it 'フキダシはフキダシ枠を含んでいる' do + r = SheetPanel.list_opt + r[:panel][:speech_balloons].has_key?(:balloon).should be_true + end + it 'フキダシはセリフを含んでいる' do + r = SheetPanel.list_opt + r[:panel][:speech_balloons].has_key?(:speech).should be_true + end + end + describe 'json一覧出力オプションに於いて' do + end + + describe '単体取得に於いて' do + before do + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @panel = FactoryGirl.create :panel, :author_id => @author.id + @sheet_panel = FactoryGirl.create :sheet_panel, :author_id => @author.id, :sheet_id => @sheet.id, :panel_id => @panel.id + end + context 'つつがなく終わるとき' do + it '単体取得オプションを利用している' do + SheetPanel.stub(:show_opt).with(any_args).and_return({}) + SheetPanel.should_receive(:show_opt).with(any_args).exactly(1) + r = SheetPanel.show @sheet_panel.id, @author + end + it '閲覧許可を問い合わせている' do + SheetPanel.any_instance.stub(:visible?).with(@author).and_return(true) + SheetPanel.any_instance.should_receive(:visible?).with(@author).exactly(1) + r = SheetPanel.show @sheet_panel.id, @author + end + end + it '指定の紙コマを返す' do + l = SheetPanel.show @sheet_panel.id, @author + l.should eq @sheet_panel + end + context '他人の紙コマを開こうとしたとき' do + it '403Forbidden例外を返す' do + SheetPanel.any_instance.stub(:visible?).with(@other_author).and_return(false) + lambda{ + SheetPanel.show @sheet_panel.id, @other_author + }.should raise_error(ActiveRecord::Forbidden) + end + end + context '存在しない紙コマを開こうとしたとき' do + it '404RecordNotFound例外を返す' do + lambda{ + SheetPanel.show 110, @author + }.should raise_error(ActiveRecord::RecordNotFound) + end + end + end + + describe '編集取得に於いて' do + before do + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @panel = FactoryGirl.create :panel, :author_id => @author.id + @sheet_panel = FactoryGirl.create :sheet_panel, :author_id => @author.id, :sheet_id => @sheet.id, :panel_id => @panel.id + end + context 'つつがなく終わるとき' do + it '単体取得オプションを利用している' do + SheetPanel.stub(:show_opt).with(any_args).and_return({}) + SheetPanel.should_receive(:show_opt).with(any_args).exactly(1) + r = SheetPanel.edit @sheet_panel.id, @author + end + it '所持判定を問い合わせている' do + SheetPanel.any_instance.stub(:own?).with(any_args).and_return(true) + SheetPanel.any_instance.should_receive(:own?).with(any_args).exactly(1) + r = SheetPanel.edit @sheet_panel.id, @author + end + end + it '指定の紙コマを返す' do + l = SheetPanel.edit @sheet_panel.id, @author + l.should eq @sheet_panel + end + context '他人の紙コマを開こうとしたとき' do + it '403Forbidden例外を返す' do + SheetPanel.any_instance.stub(:own?).and_return(false) + lambda{ + SheetPanel.edit @sheet_panel.id, @author + }.should raise_error(ActiveRecord::Forbidden) + end + end + context '存在しない紙コマを開こうとしたとき' do + it '404RecordNotFound例外を返す' do + lambda{ + SheetPanel.edit 110, @author + }.should raise_error(ActiveRecord::RecordNotFound) + end + end + end + + describe '単体取得オプションに於いて' do + it 'includeキーを含んでいる' do + r = SheetPanel.show_opt + r.has_key?(:include).should be_true + end + it '3つの項目を含んでいる' do + r = SheetPanel.show_opt[:include] + r.should have(3).items + end + it '用紙を含んでいる' do + r = SheetPanel.show_opt[:include] + r.has_key?(:sheet).should be_true + end + it '用紙は作家を含んでいる' do + r = SheetPanel.show_opt[:include] + r[:sheet].has_key?(:author).should be_true + end + it '作家を含んでいる' do + r = SheetPanel.show_opt[:include] + r.has_key?(:author).should be_true + end + it 'コマを含んでいる' do + r = SheetPanel.show_opt[:include] + r.has_key?(:panel).should be_true + end + it 'コマは作家を含んでいる' do + r = SheetPanel.show_opt[:include] + r[:panel].has_key?(:author).should be_true + end + it 'コマはコマ絵を含んでいる' do + r = SheetPanel.show_opt[:include] + r[:panel].has_key?(:panel_pictures).should be_true + end + it 'コマ絵は実素材を含んでいる' do + r = SheetPanel.show_opt[:include] + r[:panel][:panel_pictures].has_key?(:picture).should be_true + end + it '実素材は絵師を含んでいる' do + r = SheetPanel.show_opt[:include] + r[:panel][:panel_pictures][:picture].has_key?(:artist).should be_true + end + it '実素材はライセンスを含んでいる' do + r = SheetPanel.show_opt[:include] + r[:panel][:panel_pictures][:picture].has_key?(:license).should be_true + end + it 'コマはフキダシを含んでいる' do + r = SheetPanel.show_opt[:include] + r[:panel].has_key?(:speech_balloons).should be_true + end + it 'フキダシはフキダシ枠を含んでいる' do + r = SheetPanel.show_opt[:include] + r[:panel][:speech_balloons].has_key?(:balloon).should be_true + end + it 'フキダシはセリフを含んでいる' do + r = SheetPanel.show_opt[:include] + r[:panel][:speech_balloons].has_key?(:speech).should be_true + end + end + describe 'json単体取得オプションに於いて' do + end + + describe '紙コマのjson出力に於いて' do + before do + #コマを作成しておく。 + @panel = FactoryGirl.create :panel, :author_id => @author.id + @pp = FactoryGirl.create :panel_picture, :panel_id => @panel.id, :t => 1, :width => @p.width, :height => @p.height + @sb = FactoryGirl.build :speech_balloon, :panel_id => @panel.id, :speech_balloon_template_id => @speech_balloon_template.id + @speech = @sb.build_speech( + FactoryGirl.attributes_for(:speech, :writing_format_id => @writing_format.id) + ) + @balloon = @sb.build_balloon( + FactoryGirl.attributes_for(:balloon, :system_picture_id => @sp.id) + ) + @sb.boost + @sb.save! + @gc = @panel.ground_colors.create( + FactoryGirl.attributes_for(:ground_color, :panel_id => @panel.id) + ) + @gp = @panel.ground_pictures.create( + FactoryGirl.attributes_for(:ground_picture, :panel_id => @panel.id, :picture_id => @p.id) + ) + @panel.reload + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @sheet_panel = FactoryGirl.create :sheet_panel, :author_id => @author.id, :sheet_id => @sheet.id, :panel_id => @panel.id + end + context '事前チェックする' do + before do + Panel.any_instance.stub(:elements).and_return('{}') + end + it 'コマ要素のjson出力を依頼している' do + Panel.any_instance.stub(:visible?).with(any_args).and_return(true) + Panel.any_instance.should_receive(:elements).with(any_args).exactly(1) + r = @sheet_panel.sheet_panel_as_json @author + end + end + it 'json textを返している' do + r = JSON.parse @sheet_panel.sheet_panel_as_json(@author) + r.is_a?(Hash).should be_true + end + it 'sheet,author,panel,コマ要素を含んでいる' do + r = JSON.parse @sheet_panel.sheet_panel_as_json(@author) + r.has_key?('sheet').should be_true + r['sheet'].has_key?('author').should be_true + r.has_key?('author').should be_true + r.has_key?('panel').should be_true + r['panel'].has_key?('author').should be_true + end + context 'コマ閲覧許可のとき' do + before do + Panel.any_instance.stub(:visible?).with(any_args).and_return(true) + end + it 'コマ要素にコマ要素を追加している' do + r = JSON.parse @sheet_panel.sheet_panel_as_json(@author) + r['panel'].has_key?('elements').should be_true + r['panel']['elements'].should_not be_empty + end + end + context 'コマ閲覧不許可のとき' do + before do + Panel.any_instance.stub(:visible?).with(any_args).and_return(false) + end + it 'コマ要素にデータを含ませない' do + r = JSON.parse @sheet_panel.sheet_panel_as_json(@author) + r['panel'].has_key?('elements').should be_false + end + end + end + + describe '紙コマリストのjson出力に於いて' do + before do + @panel = FactoryGirl.create :panel, :author_id => @author.id + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @sheet_panel = FactoryGirl.create :sheet_panel, :author_id => @author.id, :sheet_id => @sheet.id, :panel_id => @panel.id + SheetPanel.any_instance.stub(:sheet_panel_as_json).with(@author).and_return('{"s": 5}') + end + context 'つつがなく終わるとき' do + it '紙コマのjson出力を依頼している' do + SheetPanel.any_instance.should_receive(:sheet_panel_as_json).with(@author).exactly(1) + r = SheetPanel.list_as_json_text [@sheet_panel], @author + end + end + it 'json textを返している' do + r = SheetPanel.list_as_json_text [@sheet_panel], @author + j = JSON.parse r + j.is_a?(Array).should be_true + end + it '紙コマを含んでいる' do + r = SheetPanel.list_as_json_text [@sheet_panel], @author + j = JSON.parse r + j.first.has_key?('s').should be_true + end + end + + describe 'ライセンス素材に於いて' do + before do + #コマを作成しておく。 + @op2 = FactoryGirl.create :original_picture, :artist_id => @artist.id + @p2 = FactoryGirl.create :picture, :original_picture_id => @op2.id, :license_id => @license.id, :artist_id => @artist.id + @rp2 = FactoryGirl.create :resource_picture, :artist_id => @artist.id, :license_id => @license.id, :original_picture_id => @op2.id, :picture_id => @p2.id + @panel = FactoryGirl.create :panel, :author_id => @author.id + @pp = FactoryGirl.create :panel_picture, :panel_id => @panel.id, :t => 0, :width => @p.width, :height => @p.height, :picture_id => @p.id + @panel.reload + @panel2 = FactoryGirl.create :panel, :author_id => @author.id + @pp2= FactoryGirl.create :panel_picture, :panel_id => @panel2.id, :t => 0, :width => @p2.width, :height => @p2.height, :picture_id => @p2.id + @panel2.reload + + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @sheet_panel = FactoryGirl.create :sheet_panel, :author_id => @author.id, :sheet_id => @sheet.id, :panel_id => @panel.id + @sheet_panel2 = FactoryGirl.create :sheet_panel, :author_id => @author.id, :sheet_id => @sheet.id, :panel_id => @panel2.id + end + context '事前チェック' do + end + context 'つつがなく終わるとき' do + end + it '連想配列(値は実素材、キーは実素材id)を返している' do + r = SheetPanel.licensed_pictures [@sheet_panel, @sheet_panel2] + r.is_a?(Hash).should be_true + r.should have(2).items + r[@pp.picture_id].should eq @p + r[@pp2.picture_id].should eq @p2 + end + context 'コマが削除されているときき' do + before do + @panel2.destroy + end + it '削除されているコマは無視する' do + r = SheetPanel.licensed_pictures [@sheet_panel, @sheet_panel2] + r.is_a?(Hash).should be_true + r.should have(1).items + r[@pp.picture_id].should eq @p + r[@pp2.picture_id].should be_nil + end + end + end + + describe 't補充値に於いて' do + before do + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @panel = FactoryGirl.create :panel, :author_id => @author.id + end + + context '用紙初のコマなら' do + it '0を補充値とする' do + @sheet_panel = FactoryGirl.build :sheet_panel, :author_id => @author.id, :sheet_id => @sheet.id, :panel_id => @panel.id + @sheet_panel.t = nil + r = SheetPanel.new_t @sheet_panel.sheet_id + r.should eq 0 + end + end + context '用紙に一個コマがあるとき' do + it '1を補充値とする' do + FactoryGirl.create :sheet_panel, :author_id => @author.id, :sheet_id => @sheet.id, :panel_id => @panel.id, :t => 0 + @sheet_panel = FactoryGirl.build :sheet_panel, :author_id => @author.id, :sheet_id => @sheet.id, :panel_id => @panel.id + @sheet_panel.t = nil + r = SheetPanel.new_t @sheet_panel.sheet_id + r.should eq 1 + end + end + context '用紙に2個コマがあるとき' do + it '2を補充値とする' do + FactoryGirl.create :sheet_panel, :author_id => @author.id, :sheet_id => @sheet.id, :panel_id => @panel.id, :t => 0 + FactoryGirl.create :sheet_panel, :author_id => @author.id, :sheet_id => @sheet.id, :panel_id => @panel.id, :t => 1 + @sheet_panel = FactoryGirl.build :sheet_panel, :author_id => @author.id, :sheet_id => @sheet.id, :panel_id => @panel.id + @sheet_panel.t = nil + r = SheetPanel.new_t @sheet_panel.sheet_id + r.should eq 2 + end + end + end + describe 'シリアライズチェックに於いて' do + context 'つつがなく終わるとき' do + it '0からシリアライズされているならTrueを返す' do + r = SheetPanel.serial? [0, 1, 2] + r.should be_true + end + it '見た目はシリアライズされてなくてもソート結果が無事ならtrueを返す' do + r = SheetPanel.serial? [0, 2, 1] + r.should be_true + end + it '見た目はシリアライズされてなくてもソート結果が無事ならtrueを返す' do + r = SheetPanel.serial? [ 2, 1, 4, 3, 0] + r.should be_true + end + end + context '異常なとき' do + it '0から始まらないならFalseを返す' do + r = SheetPanel.serial? [1, 2, 3] + r.should be_false + end + it '連続していないならFalseを返す' do + r = SheetPanel.serial? [0, 1, 2, 4] + r.should be_false + end + it '連続していないならFalseを返す' do + r = SheetPanel.serial? [0, 1, 2, 4, 5] + r.should be_false + end + end + end + describe 't収集に於いて' do + before do + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @panel = FactoryGirl.create :panel, :author_id => @author.id + @sheet_panel = FactoryGirl.create :sheet_panel, :t => 0, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet2 = FactoryGirl.create :sheet, :author_id => @author.id + @c2sheet_panel = FactoryGirl.create :sheet_panel, :t => 0, :sheet_id => @sheet2.id, :panel_id => @panel.id, :author_id => @author.id + end + context 'つつがなく終わるとき' do + it '紙コマから同一用紙のtだけを収集している' do + r = SheetPanel.collect_t @sheet_panel + r.should eq [0] + end + end + context '複数コマのとき' do + it '紙コマから同一用紙のtだけを収集している' do + @sheet_panel2 = FactoryGirl.create :sheet_panel, :t => 1, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + r = SheetPanel.collect_t @sheet_panel + r.sort.should eq [0, 1] + end + end + context '複数コマでヨソの用紙も混じっているとき' do + it '紙コマから同一用紙のtだけを収集している' do + @sheet_panel2 = FactoryGirl.create :sheet_panel, :t => 1, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + r = SheetPanel.collect_t @sheet_panel + r.sort.should eq [0, 1] + end + end + end + describe 'tチェックに於いて' do + before do + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @panel = FactoryGirl.create :panel, :author_id => @author.id + @sheet_panel = FactoryGirl.build :sheet_panel, :t => 1, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + end + context 'つつがなく終わるとき' do + it 't収集を依頼している' do + SheetPanel.should_receive(:collect_t).with(any_args).exactly(1) + SheetPanel.stub(:collect_t).with(any_args).and_return([]) + SheetPanel.stub(:serial?).with(any_args).and_return(true) + r = SheetPanel.validate_t @sheet_panel + end + it '収集したtをシリアライズチェック依頼している' do + SheetPanel.stub(:collect_t).with(any_args).and_return([]) + SheetPanel.should_receive(:serial?).with(any_args).exactly(1) + SheetPanel.stub(:serial?).with(any_args).and_return(true) + r = SheetPanel.validate_t @sheet_panel + end + end + #実データでチェック + #依頼チェックだけでは不安なので最低限のチェックを + context '新規のとき' do + it '一件だけで正常通過している' do + @sheet_panel = FactoryGirl.build :sheet_panel, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id, :t => 0 + r = SheetPanel.validate_t @sheet_panel + r.should be_true + end + end + context '既存のとき' do + it '2件目を作っても正常通過している' do + @sheet_panel = FactoryGirl.create :sheet_panel, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id, :t => 0 + @sheet_panel2 = FactoryGirl.build :sheet_panel, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id, :t => 1 + r = SheetPanel.validate_t @sheet_panel2 + r.should be_true + end + end + end + describe '挿入シフトに於いて' do + before do + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @panel = FactoryGirl.create :panel, :author_id => @author.id + end + context '依頼チェック' do + #テーブルが空で0に挿入 + it 'Updateを依頼している' do + SheetPanel.stub(:update_all).with(any_args) + SheetPanel.should_receive(:update_all).with(any_args).exactly(1) + @sheet_panel = FactoryGirl.build :sheet_panel, :t => 0, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel.insert_shift + end + end + context 'テーブルに1件(t:0)で0に挿入したとき' do + before do + @sheet_panel = FactoryGirl.create :sheet_panel, :t => 0, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel2 = FactoryGirl.build :sheet_panel, :t => 0, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + end + it '既存の行を1にシフトしている' do + @sheet_panel2.insert_shift + l = SheetPanel.find :all + l.first.t.should eq 1 + end + it 'これから挿入するt(0)が欠番になっている' do + @sheet_panel2.insert_shift + l = SheetPanel.find(:all).map {|s| s.t } + l.include?(0).should_not be_true + end + end + context 'テーブルに2件(t:0,1)で1に挿入したとき' do + before do + @sheet_panel = FactoryGirl.create :sheet_panel, :t => 0, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel2 = FactoryGirl.create :sheet_panel, :t => 1, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel3 = FactoryGirl.build :sheet_panel, :t => 1, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + end + it '既存のt1を2にシフトしてこれから挿入するt(1)が欠番になっている' do + @sheet_panel3.insert_shift + l = SheetPanel.find(:all).map {|s| s.t } + l.sort.should eq [0, 2] + end + end + context 'テーブルに5件(t:0,1,2,3,4)で2に挿入したとき' do + before do + @sheet_panel = FactoryGirl.create :sheet_panel, :t => 0, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel2 = FactoryGirl.create :sheet_panel, :t => 1, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel3 = FactoryGirl.create :sheet_panel, :t => 2, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel4 = FactoryGirl.create :sheet_panel, :t => 3, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel5 = FactoryGirl.create :sheet_panel, :t => 4, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel6 = FactoryGirl.build :sheet_panel, :t => 2, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + end + it '既存のt1を2にシフトしてこれから挿入するt(1)が欠番になっている' do + @sheet_panel6.insert_shift + l = SheetPanel.find(:all).map {|s| s.t } + l.sort.should eq [0, 1, 3, 4, 5] + end + end + context '先ほどのケース+他の用紙1件で挿入したとき' do + before do + @sheet2 = FactoryGirl.create :sheet, :author_id => @author.id + @sheet_panelc2 = FactoryGirl.create :sheet_panel, :t => 0, :sheet_id => @sheet2.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel = FactoryGirl.create :sheet_panel, :t => 0, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel2 = FactoryGirl.create :sheet_panel, :t => 1, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel3 = FactoryGirl.create :sheet_panel, :t => 2, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel4 = FactoryGirl.create :sheet_panel, :t => 3, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel5 = FactoryGirl.create :sheet_panel, :t => 4, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel6 = FactoryGirl.build :sheet_panel, :t => 2, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + end + it '既存のt1を2にシフトしてこれから挿入するt(1)が欠番になっている' do + @sheet_panel6.insert_shift + l = SheetPanel.find(:all, :conditions => ['sheet_id = ?', @sheet.id]).map {|s| s.t } + l.sort.should eq [0, 1, 3, 4, 5] + end + it '他の用紙に影響がない' do + ot = @sheet_panelc2.t + @sheet_panel6.insert_shift + @sheet_panelc2.reload + @sheet_panelc2.t.should eq ot + end + end + end + describe '少ない方に移動に於いて' do + before do + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @panel = FactoryGirl.create :panel, :author_id => @author.id + end + context '依頼チェック' do + it 'Updateを依頼している' do + @sheet_panel = FactoryGirl.create :sheet_panel, :t => 0, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel2 = FactoryGirl.create :sheet_panel, :t => 1, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + SheetPanel.stub(:update_all).with(any_args) + SheetPanel.should_receive(:update_all).with(any_args).exactly(1) + ot = @sheet_panel2.t + @sheet_panel2.t = 0 + @sheet_panel2.lesser_shift ot + end + end + context 'テーブルに2件(t:0,1)で1を0に移動したとき' do + before do + @sheet_panel = FactoryGirl.create :sheet_panel, :t => 0, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel2 = FactoryGirl.create :sheet_panel, :t => 1, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @ot = @sheet_panel2.t + @sheet_panel2.t = 0 + end + it '既存のt0を1にシフトしてこれから挿入するt(0)が欠番になっている' do + #移動させたい行はそのまま残る + @sheet_panel2.lesser_shift @ot + l = SheetPanel.find(:all).map {|s| s.t } + l.sort.should eq [1, 1] + end + it '既存のt0を1にシフトしている' do + @sheet_panel2.lesser_shift @ot + @sheet_panel.reload + @sheet_panel.t.should eq 1 + end + end + context 'テーブルに3件(t:0,1,2)で2を1に移動したとき' do + before do + @sheet_panel = FactoryGirl.create :sheet_panel, :t => 0, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel2 = FactoryGirl.create :sheet_panel, :t => 1, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel3 = FactoryGirl.create :sheet_panel, :t => 2, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @ot = @sheet_panel3.t + @sheet_panel3.t = 1 + end + it '既存のt1を2にシフトしてこれから挿入するt(1)が欠番になっている' do + #移動させたい行はそのまま残る + @sheet_panel3.lesser_shift @ot + l = SheetPanel.find(:all).map {|s| s.t } + l.sort.should eq [0, 2, 2] + end + it '既存のt1を2にシフトしている' do + @sheet_panel3.lesser_shift @ot + @sheet_panel2.reload + @sheet_panel2.t.should eq 2 + end + end + context 'テーブルに5件(t:0,1,2,3,4)で3を1に移動したとき' do + before do + @sheet_panel = FactoryGirl.create :sheet_panel, :t => 0, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel2 = FactoryGirl.create :sheet_panel, :t => 1, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel3 = FactoryGirl.create :sheet_panel, :t => 2, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel4 = FactoryGirl.create :sheet_panel, :t => 3, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel5 = FactoryGirl.create :sheet_panel, :t => 4, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @ot = @sheet_panel4.t + @sheet_panel4.t = 1 + end + it 'これから挿入するt(1)が欠番になっている' do + #移動させたい行はそのまま残る + @sheet_panel4.lesser_shift @ot + l = SheetPanel.find(:all).map {|s| s.t } + l.sort.should eq [0, 2, 3, 3, 4] + end + it '既存のt0には変化がない' do + @sheet_panel4.lesser_shift @ot + @sheet_panel.reload + @sheet_panel.t.should eq 0 + end + it '既存のt4には変化がない' do + @sheet_panel4.lesser_shift @ot + @sheet_panel5.reload + @sheet_panel5.t.should eq 4 + end + it '既存のt1を2にシフトしている' do + @sheet_panel4.lesser_shift @ot + @sheet_panel2.reload + @sheet_panel2.t.should eq 2 + end + it '既存のt2を3にシフトしている' do + @sheet_panel4.lesser_shift @ot + @sheet_panel3.reload + @sheet_panel3.t.should eq 3 + end + end + context '先ほどのケース+他の用紙1件で挿入したとき' do + before do + @sheet2 = FactoryGirl.create :sheet, :author_id => @author.id + @sheet_panelc2 = FactoryGirl.create :sheet_panel, :t => 0, :sheet_id => @sheet2.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel = FactoryGirl.create :sheet_panel, :t => 0, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel2 = FactoryGirl.create :sheet_panel, :t => 1, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel3 = FactoryGirl.create :sheet_panel, :t => 2, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel4 = FactoryGirl.create :sheet_panel, :t => 3, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel5 = FactoryGirl.create :sheet_panel, :t => 4, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @ot = @sheet_panel4.t + @sheet_panel4.t = 1 + end + it 'これから挿入するt(1)が欠番になっている' do + @sheet_panel4.lesser_shift @ot + l = SheetPanel.find(:all).map {|s| s.t } + l.sort.should eq [0, 0, 2, 3, 3, 4] + end + it '既存のt0には変化がない' do + @sheet_panel4.lesser_shift @ot + @sheet_panel.reload + @sheet_panel.t.should eq 0 + end + it '既存のt4には変化がない' do + @sheet_panel4.lesser_shift @ot + @sheet_panel5.reload + @sheet_panel5.t.should eq 4 + end + it '既存のt1を2にシフトしている' do + @sheet_panel4.lesser_shift @ot + @sheet_panel2.reload + @sheet_panel2.t.should eq 2 + end + it '既存のt2を3にシフトしている' do + @sheet_panel4.lesser_shift @ot + @sheet_panel3.reload + @sheet_panel3.t.should eq 3 + end + it '他の用紙に影響がない' do + @sheet_panel4.lesser_shift @ot + @sheet_panelc2.reload + @sheet_panelc2.t.should eq 0 + end + end + #例外ケース。 + #負のときは0として正常扱い + context 'テーブルに2件(t:0,1)で1を-1に移動したとき' do + before do + @sheet_panel = FactoryGirl.create :sheet_panel, :t => 0, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel2 = FactoryGirl.create :sheet_panel, :t => 1, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @ot = @sheet_panel2.t + @sheet_panel2.t = -1 + end + it '既存のt0を1にシフトしてこれから挿入するt(0)が欠番になっている' do + #移動させたい行はそのまま残る + @sheet_panel2.lesser_shift @ot + l = SheetPanel.find(:all).map {|s| s.t } + l.sort.should eq [1, 1] + end + it '既存のt0を1にシフトしている' do + @sheet_panel2.lesser_shift @ot + @sheet_panel.reload + @sheet_panel.t.should eq 1 + end + it '既存のt1は0に補正されている' do + @sheet_panel2.lesser_shift @ot + @sheet_panel2.t.should eq 0 + end + end + end + describe '大きい方に移動に於いて' do + before do + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @panel = FactoryGirl.create :panel, :author_id => @author.id + end + context '依頼チェック' do + it 'Updateを依頼している' do + @sheet_panel = FactoryGirl.create :sheet_panel, :t => 0, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel2 = FactoryGirl.create :sheet_panel, :t => 1, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + SheetPanel.stub(:update_all).with(any_args) + SheetPanel.should_receive(:update_all).with(any_args).exactly(1) + ot = @sheet_panel.t + @sheet_panel.t = 1 + @sheet_panel.higher_shift ot + end + end + context 'テーブルに2件(t:0,1)で0を1に移動したとき' do + before do + @sheet_panel = FactoryGirl.create :sheet_panel, :t => 0, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel2 = FactoryGirl.create :sheet_panel, :t => 1, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @ot = @sheet_panel.t + @sheet_panel.t = 1 + end + it '既存のt1を0にシフトしてこれから挿入するt(1)が欠番になっている' do + #移動させたい行はそのまま残る + @sheet_panel.higher_shift @ot + l = SheetPanel.find(:all).map {|s| s.t } + l.sort.should eq [0, 0] + end + it '既存のt1を0にシフトしている' do + @sheet_panel.higher_shift @ot + @sheet_panel2.reload + @sheet_panel2.t.should eq 0 + end + end + context 'テーブルに3件(t:0,1,2)で0を1に移動したとき' do + before do + @sheet_panel = FactoryGirl.create :sheet_panel, :t => 0, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel2 = FactoryGirl.create :sheet_panel, :t => 1, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel3 = FactoryGirl.create :sheet_panel, :t => 2, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @ot = @sheet_panel.t + @sheet_panel.t = 1 + end + it '既存のt1を0にシフトしてこれから挿入するt(1)が欠番になっている' do + #移動させたい行はそのまま残る + @sheet_panel.higher_shift @ot + l = SheetPanel.find(:all).map {|s| s.t } + l.sort.should eq [0, 0, 2] + end + it '既存のt1を0にシフトしている' do + @sheet_panel.higher_shift @ot + @sheet_panel2.reload + @sheet_panel2.t.should eq 0 + end + end + context 'テーブルに5件(t:0,1,2,3,4)で1を3に移動したとき' do + before do + @sheet_panel = FactoryGirl.create :sheet_panel, :t => 0, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel2 = FactoryGirl.create :sheet_panel, :t => 1, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel3 = FactoryGirl.create :sheet_panel, :t => 2, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel4 = FactoryGirl.create :sheet_panel, :t => 3, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel5 = FactoryGirl.create :sheet_panel, :t => 4, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @ot = @sheet_panel2.t + @sheet_panel2.t = 3 + end + it 'これから挿入するt(3)が欠番になっている' do + #移動させたい行はそのまま残る + @sheet_panel2.higher_shift @ot + l = SheetPanel.find(:all).map {|s| s.t } + l.sort.should eq [0, 1, 1, 2, 4] + end + it '既存のt0には変化がない' do + @sheet_panel2.higher_shift @ot + @sheet_panel.reload + @sheet_panel.t.should eq 0 + end + it '既存のt4には変化がない' do + @sheet_panel2.higher_shift @ot + @sheet_panel5.reload + @sheet_panel5.t.should eq 4 + end + it '既存のt2を1にシフトしている' do + @sheet_panel2.higher_shift @ot + @sheet_panel3.reload + @sheet_panel3.t.should eq 1 + end + it '既存のt3を2にシフトしている' do + @sheet_panel2.higher_shift @ot + @sheet_panel4.reload + @sheet_panel4.t.should eq 2 + end + end + context '先ほどのケース+他の用紙1件で挿入したとき' do + before do + @sheet2 = FactoryGirl.create :sheet, :author_id => @author.id + @sheet_panelc2 = FactoryGirl.create :sheet_panel, :t => 0, :sheet_id => @sheet2.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel = FactoryGirl.create :sheet_panel, :t => 0, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel2 = FactoryGirl.create :sheet_panel, :t => 1, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel3 = FactoryGirl.create :sheet_panel, :t => 2, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel4 = FactoryGirl.create :sheet_panel, :t => 3, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel5 = FactoryGirl.create :sheet_panel, :t => 4, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @ot = @sheet_panel2.t + @sheet_panel2.t = 3 + end + it 'これから挿入するt(3)が欠番になっている' do + #移動させたい行はそのまま残る + @sheet_panel2.higher_shift @ot + l = SheetPanel.find(:all).map {|s| s.t } + l.sort.should eq [0, 0, 1, 1, 2, 4] + end + it '既存のt0には変化がない' do + @sheet_panel2.higher_shift @ot + @sheet_panel.reload + @sheet_panel.t.should eq 0 + end + it '既存のt4には変化がない' do + @sheet_panel2.higher_shift @ot + @sheet_panel5.reload + @sheet_panel5.t.should eq 4 + end + it '既存のt2を1にシフトしている' do + @sheet_panel2.higher_shift @ot + @sheet_panel3.reload + @sheet_panel3.t.should eq 1 + end + it '既存のt3を2にシフトしている' do + @sheet_panel2.higher_shift @ot + @sheet_panel4.reload + @sheet_panel4.t.should eq 2 + end + it '他の用紙に影響がない' do + @sheet_panel2.higher_shift @ot + @sheet_panelc2.reload + @sheet_panelc2.t.should eq 0 + end + end + #例外ケース。 + #max超えたときはmaxとして正常扱い + context 'テーブルに2件(t:0,1)で0を2に移動したとき' do + before do + @sheet_panel = FactoryGirl.create :sheet_panel, :t => 0, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel2 = FactoryGirl.create :sheet_panel, :t => 1, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @ot = @sheet_panel.t + @sheet_panel.t = 2 + end + it '既存のt1を0にシフトしてこれから挿入するt(1)が欠番になっている' do + #移動させたい行はそのまま残る + @sheet_panel.higher_shift @ot + l = SheetPanel.find(:all).map {|s| s.t } + l.sort.should eq [0, 0] + end + it '既存のt1を0にシフトしている' do + @sheet_panel.higher_shift @ot + @sheet_panel2.reload + @sheet_panel2.t.should eq 0 + end + it '既存のt0は1に補正されている' do + @sheet_panel.higher_shift @ot + @sheet_panel.t.should eq 1 + end + end + end + describe '入れ替えに於いて' do + before do + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @panel = FactoryGirl.create :panel, :author_id => @author.id + @sheet_panel = FactoryGirl.create :sheet_panel, :t => 0, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel2 = FactoryGirl.create :sheet_panel, :t => 1, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + end + context '新tが旧tより小さいとき' do + it '少ない方に移動を依頼している' do + SheetPanel.any_instance.stub(:lesser_shift).with(any_args) + SheetPanel.any_instance.should_receive(:lesser_shift).with(any_args).exactly(1) + ot = @sheet_panel2.t + @sheet_panel2.t = 0 + @sheet_panel2.update_shift ot + end + end + context '新tが旧tより大きいとき' do + it '大きい方に移動を依頼している' do + SheetPanel.any_instance.stub(:higher_shift).with(any_args) + SheetPanel.any_instance.should_receive(:higher_shift).with(any_args).exactly(1) + ot = @sheet_panel.t + @sheet_panel.t = 1 + @sheet_panel.update_shift ot + end + end + end + describe '順序入れ替えに於いて' do + before do + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @panel = FactoryGirl.create :panel, :author_id => @author.id + end + context 'オブジェクトが新規でtが空のとき' do + it '末尾追加としてtを補充依頼している' do + @sheet_panel = FactoryGirl.build :sheet_panel, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + SheetPanel.stub(:new_t).with(any_args).and_return(0) + SheetPanel.should_receive(:new_t).with(any_args).exactly(1) + @sheet_panel.t = nil + r = @sheet_panel.rotate + end + end + context 'オブジェクトが新規でtが設定されているとき' do + it '挿入追加として挿入シフトを依頼している' do + @sheet_panel = FactoryGirl.build :sheet_panel, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + SheetPanel.any_instance.stub(:insert_shift).with(any_args) + SheetPanel.any_instance.should_receive(:insert_shift).with(any_args).exactly(1) + @sheet_panel.t = 0 + r = @sheet_panel.rotate + end + end + context 'オブジェクトが新規でなくtが設定されているとき' do + it 'コマ移動として入れ替えを依頼している' do + @sheet_panel = FactoryGirl.create :sheet_panel, :t => 0, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel2 = FactoryGirl.create :sheet_panel, :t => 1, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + SheetPanel.any_instance.stub(:update_shift).with(any_args) + SheetPanel.any_instance.should_receive(:update_shift).with(1).exactly(1) + @sheet_panel2.t = 0 + r = @sheet_panel.rotate 1 + end + end + context 'オブジェクトが新規でなくtが空のとき' do + it '入れ替えもシフトもせず、tを空のままにしている' do + #結果、tに欠番が生じてシリアライズチェックでひっかかる + end + end + end + describe '編集許可に於いて' do + before do + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @panel = FactoryGirl.create :panel, :author_id => @author.id + @sheet_panel = FactoryGirl.build :sheet_panel, :t => nil, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + end + context 'つつがなく終わるとき' do + it 'trueを返す' do + r = @sheet_panel.allow? + r.should be_true + end + end + context '用紙で引っかかるとき' do + it 'falseを返す' do + Panel.any_instance.stub(:usable?).with(any_args).and_return(true) + Sheet.any_instance.stub(:own?).with(any_args).and_return(false) + r = @sheet_panel.allow? + r.should be_false + end + end + context 'コマで引っかかるとき' do + it 'falseを返す' do + Sheet.any_instance.stub(:own?).with(any_args).and_return(true) + Panel.any_instance.stub(:usable?).with(any_args).and_return(false) + r = @sheet_panel.allow? + r.should be_false + end + end + context '用紙またはコマが指定されていなかったとき' do + it 'nilを返す' do + Sheet.any_instance.stub(:own?).with(any_args).and_return(true) + @sheet_panel.panel_id = nil + r = @sheet_panel.allow? + r.should eq nil + end + it 'nilを返す' do + Panel.any_instance.stub(:usable?).with(any_args).and_return(true) + @sheet_panel.sheet_id = nil + r = @sheet_panel.allow? + r.should eq nil + end + end + end + describe '保存に於いて' do + before do + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @panel = FactoryGirl.create :panel, :author_id => @author.id + @sheet_panel = FactoryGirl.build :sheet_panel, :t => nil, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + end + context 'つつがなく終わるとき' do + it '編集許可チェックを依頼している' do + SheetPanel.any_instance.stub(:allow?).with(any_args).and_return(true) + SheetPanel.any_instance.should_receive(:allow?).with(any_args).exactly(1) + r = @sheet_panel.store + end + it '順序入れ替えを依頼している' do + SheetPanel.any_instance.stub(:rotate).with(any_args).and_return(0) + SheetPanel.any_instance.should_receive(:rotate).with(any_args).exactly(1) + SheetPanel.any_instance.stub(:save).with(any_args).and_return(true) + SheetPanel.stub(:validate_t).with(any_args).and_return(true) + r = @sheet_panel.store + end + it '保存を依頼している' do + SheetPanel.stub(:new_t).with(any_args).and_return(0) + SheetPanel.any_instance.stub(:save).with(any_args).and_return(true) + SheetPanel.any_instance.should_receive(:save).with(any_args).exactly(1) + SheetPanel.stub(:validate_t).with(any_args).and_return(true) + r = @sheet_panel.store + end + it 'tのシリアライズチェックを依頼している' do + SheetPanel.stub(:new_t).with(any_args).and_return(0) + SheetPanel.any_instance.stub(:save).with(any_args).and_return(true) + SheetPanel.stub(:validate_t).with(any_args).and_return(true) + SheetPanel.should_receive(:validate_t).with(any_args).exactly(1) + r = @sheet_panel.store + end + end + #入れ替えテストと同じテストを実施。こちらはシフトだけでなく本尊も更新されている + context 'テーブルに5件(t:0,1,2,3,4)+他の用紙1件で2に挿入したとき' do + before do + @sheet2 = FactoryGirl.create :sheet, :author_id => @author.id + @sheet_panelc2 = FactoryGirl.create :sheet_panel, :t => 0, :sheet_id => @sheet2.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel = FactoryGirl.create :sheet_panel, :t => 0, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel2 = FactoryGirl.create :sheet_panel, :t => 1, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel3 = FactoryGirl.create :sheet_panel, :t => 2, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel4 = FactoryGirl.create :sheet_panel, :t => 3, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel5 = FactoryGirl.create :sheet_panel, :t => 4, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel6 = FactoryGirl.build :sheet_panel, :t => 2, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + end + it '既存のt0には変化がない' do + @sheet_panel6.store + @sheet_panel.reload + @sheet_panel.t.should eq 0 + end + it '既存のt1には変化がない' do + @sheet_panel6.store + @sheet_panel2.reload + @sheet_panel2.t.should eq 1 + end + it '既存のt2を3にシフトしている' do + @sheet_panel6.store + @sheet_panel3.reload + @sheet_panel3.t.should eq 3 + end + it '既存のt3を4にシフトしている' do + @sheet_panel6.store + @sheet_panel4.reload + @sheet_panel4.t.should eq 4 + end + it '既存のt5を5にシフトしている' do + @sheet_panel6.store + @sheet_panel5.reload + @sheet_panel5.t.should eq 5 + end + it '新規のt2が作成されている' do + @sheet_panel6.store + @sheet_panel6.reload + @sheet_panel6.t.should eq 2 + end + it '他の用紙に影響がない' do + @ot = @sheet_panelc2.t + @sheet_panel6.store + @sheet_panelc2.reload + @sheet_panelc2.t.should eq @ot + end + end + context 'テーブルに5件(t:0,1,2,3,4)+他の用紙1件で3を1に移動したとき' do + before do + @sheet2 = FactoryGirl.create :sheet, :author_id => @author.id + @sheet_panelc2 = FactoryGirl.create :sheet_panel, :t => 0, :sheet_id => @sheet2.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel = FactoryGirl.create :sheet_panel, :t => 0, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel2 = FactoryGirl.create :sheet_panel, :t => 1, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel3 = FactoryGirl.create :sheet_panel, :t => 2, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel4 = FactoryGirl.create :sheet_panel, :t => 3, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel5 = FactoryGirl.create :sheet_panel, :t => 4, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @ot = @sheet_panel4.t + @sheet_panel4.t = 1 + end + it '既存のt0には変化がない' do + @sheet_panel4.store @ot + @sheet_panel.reload + @sheet_panel.t.should eq 0 + end + it '既存のt4には変化がない' do + @sheet_panel4.store @ot + @sheet_panel5.reload + @sheet_panel5.t.should eq 4 + end + it '既存のt1を2にシフトしている' do + @sheet_panel4.store @ot + @sheet_panel2.reload + @sheet_panel2.t.should eq 2 + end + it '既存のt2を3にシフトしている' do + @sheet_panel4.store @ot + @sheet_panel3.reload + @sheet_panel3.t.should eq 3 + end + it '既存のt3を1にシフトしている' do + @sheet_panel4.store @ot + @sheet_panel4.reload + @sheet_panel4.t.should eq 1 + end + it '他の用紙に影響がない' do + @sheet_panel4.store @ot + @sheet_panelc2.reload + @sheet_panelc2.t.should eq 0 + end + end + context 'テーブルに5件(t:0,1,2,3,4)+他の用紙1件で1を3に移動したとき' do + before do + @sheet2 = FactoryGirl.create :sheet, :author_id => @author.id + @sheet_panelc2 = FactoryGirl.create :sheet_panel, :t => 0, :sheet_id => @sheet2.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel = FactoryGirl.create :sheet_panel, :t => 0, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel2 = FactoryGirl.create :sheet_panel, :t => 1, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel3 = FactoryGirl.create :sheet_panel, :t => 2, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel4 = FactoryGirl.create :sheet_panel, :t => 3, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel5 = FactoryGirl.create :sheet_panel, :t => 4, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @ot = @sheet_panel2.t + @sheet_panel2.t = 3 + end + it '既存のt0には変化がない' do + @sheet_panel2.store @ot + @sheet_panel.reload + @sheet_panel.t.should eq 0 + end + it '既存のt4には変化がない' do + @sheet_panel2.store @ot + @sheet_panel5.reload + @sheet_panel5.t.should eq 4 + end + it '既存のt1を3にシフトしている' do + @sheet_panel2.store @ot + @sheet_panel2.reload + @sheet_panel2.t.should eq 3 + end + it '既存のt2を1にシフトしている' do + @sheet_panel2.store @ot + @sheet_panel3.reload + @sheet_panel3.t.should eq 1 + end + it '既存のt3を2にシフトしている' do + @sheet_panel2.store @ot + @sheet_panel4.reload + @sheet_panel4.t.should eq 2 + end + it '他の用紙に影響がない' do + @sheet_panel2.store @ot + @sheet_panelc2.reload + @sheet_panelc2.t.should eq 0 + end + end + #ロールバックテスト。入れ替えが直接DBをいじるので、すべてのケースで確実にロールバックを確認する + context 'テーブルに5件(t:0,1,2,3,4)+他の用紙1件で2に挿入したが保存に失敗したとき' do + before do + SheetPanel.any_instance.stub(:save).with(any_args).and_return(false) + @sheet2 = FactoryGirl.create :sheet, :author_id => @author.id + @sheet_panelc2 = FactoryGirl.create :sheet_panel, :t => 0, :sheet_id => @sheet2.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel = FactoryGirl.create :sheet_panel, :t => 0, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel2 = FactoryGirl.create :sheet_panel, :t => 1, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel3 = FactoryGirl.create :sheet_panel, :t => 2, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel4 = FactoryGirl.create :sheet_panel, :t => 3, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel5 = FactoryGirl.create :sheet_panel, :t => 4, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel6 = FactoryGirl.build :sheet_panel, :t => 2, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + end + it '既存のtに変化がない' do + @sheet_panel6.store + @sheet_panel.reload + @sheet_panel.t.should eq 0 + @sheet_panel2.reload + @sheet_panel2.t.should eq 1 + @sheet_panel3.reload + @sheet_panel3.t.should eq 2 + @sheet_panel4.reload + @sheet_panel4.t.should eq 3 + @sheet_panel5.reload + @sheet_panel5.t.should eq 4 + @sheet_panelc2.reload + @sheet_panelc2.t.should eq 0 + end + it 'falseを返す' do + r = @sheet_panel6.store + r.should be_false + end + end + context 'テーブルに5件(t:0,1,2,3,4)+他の用紙1件で3を1に移動したがシリアルチェックに失敗したとき' do + before do + SheetPanel.stub(:validate_t).with(any_args).and_return(false) + @sheet2 = FactoryGirl.create :sheet, :author_id => @author.id + @sheet_panelc2 = FactoryGirl.create :sheet_panel, :t => 0, :sheet_id => @sheet2.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel = FactoryGirl.create :sheet_panel, :t => 0, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel2 = FactoryGirl.create :sheet_panel, :t => 1, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel3 = FactoryGirl.create :sheet_panel, :t => 2, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel4 = FactoryGirl.create :sheet_panel, :t => 3, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel5 = FactoryGirl.create :sheet_panel, :t => 4, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @ot = @sheet_panel4.t + @sheet_panel4.t = 1 + end + it '既存のtに変化がない' do + @sheet_panel4.store @ot + @sheet_panel.reload + @sheet_panel.t.should eq 0 + @sheet_panel2.reload + @sheet_panel2.t.should eq 1 + @sheet_panel3.reload + @sheet_panel3.t.should eq 2 + @sheet_panel4.reload + @sheet_panel4.t.should eq 3 + @sheet_panel5.reload + @sheet_panel5.t.should eq 4 + @sheet_panelc2.reload + @sheet_panelc2.t.should eq 0 + end + it 'falseを返す' do + r = @sheet_panel4.store @ot + r.should be_false + end + it 'tにエラーメッセージが入っている' do + @sheet_panel4.store @ot + @sheet_panel4.errors[:t].should_not be_empty + @sheet_panel4.valid?.should be_true + end + end + context '編集不可だったとき' do + before do + @sheet_panel = FactoryGirl.build :sheet_panel, :t => 0, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + SheetPanel.any_instance.stub(:allow?).and_return(false) + end + it '403Forbidden例外を返す' do + lambda{ + @sheet_panel.store + }.should raise_error(ActiveRecord::Forbidden) + end + end + end + describe '切り詰め処理つき削除に於いて' do + before do + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @panel = FactoryGirl.create :panel, :author_id => @author.id + @sheet_panel = FactoryGirl.create :sheet_panel, :t => 0, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + end + context 'つつがなく終わるとき' do + it '削除される' do + lambda{ + @sheet_panel.destroy_and_shorten + }.should change(SheetPanel, :count ).by(-1) + end + it 'Trueを返す' do + r = @sheet_panel.destroy_and_shorten + r.should be_true + end + end + context '削除に失敗したとき' do + before do + SheetPanel.any_instance.stub(:destroy).and_return(false) + end + it 'ロールバックされる' do + lambda{ + @sheet_panel.destroy_and_shorten + }.should_not change(SheetPanel, :count ) + end + it 'Falseを返す' do + r = @sheet_panel.destroy_and_shorten + r.should be_false + end + end + #連携テスト。切り詰めが直接DBをいじる + context '2件で先頭を削除したとき' do + before do + @sheet_panel2 = FactoryGirl.create :sheet_panel, :t => 1, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + end + it '行が削除される' do + lambda{ + @sheet_panel.destroy_and_shorten + }.should change(SheetPanel, :count ).by(-1) + end + it '先頭は削除される' do + @sheet_panel.destroy_and_shorten + lambda{ + SheetPanel.find @sheet_panel.id + }.should raise_error(ActiveRecord::RecordNotFound) + end + it '2件目は前に詰められる' do + @sheet_panel.destroy_and_shorten + @sheet_panel2.reload + @sheet_panel2.t.should eq 0 + end + end + context '3件で先頭を削除したとき' do + before do + @sheet_panel2 = FactoryGirl.create :sheet_panel, :t => 1, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel3 = FactoryGirl.create :sheet_panel, :t => 2, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + end + it '行が削除される' do + lambda{ + @sheet_panel.destroy_and_shorten + }.should change(SheetPanel, :count ).by(-1) + end + it '先頭は削除される' do + @sheet_panel.destroy_and_shorten + lambda{ + SheetPanel.find @sheet_panel.id + }.should raise_error(ActiveRecord::RecordNotFound) + end + it '2件目は前に詰められる' do + @sheet_panel.destroy_and_shorten + @sheet_panel2.reload + @sheet_panel2.t.should eq 0 + end + it '3件目は前に詰められる' do + @sheet_panel.destroy_and_shorten + @sheet_panel3.reload + @sheet_panel3.t.should eq 1 + end + end + context '5件で3件目を削除したとき' do + before do + @sheet_panel2 = FactoryGirl.create :sheet_panel, :t => 1, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel3 = FactoryGirl.create :sheet_panel, :t => 2, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel4 = FactoryGirl.create :sheet_panel, :t => 3, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + @sheet_panel5 = FactoryGirl.create :sheet_panel, :t => 4, :sheet_id => @sheet.id, :panel_id => @panel.id, :author_id => @author.id + end + it '行が削除される' do + lambda{ + @sheet_panel3.destroy_and_shorten + }.should change(SheetPanel, :count ).by(-1) + end + it '1件目は変化がない' do + @sheet_panel3.destroy_and_shorten + @sheet_panel.reload + @sheet_panel.t.should eq 0 + end + it '2件目は変化がない' do + @sheet_panel3.destroy_and_shorten + @sheet_panel2.reload + @sheet_panel2.t.should eq 1 + end + it '3件目は削除される' do + @sheet_panel3.destroy_and_shorten + lambda{ + SheetPanel.find @sheet_panel3.id + }.should raise_error(ActiveRecord::RecordNotFound) + end + it '4件目は前に詰められる' do + @sheet_panel3.destroy_and_shorten + @sheet_panel4.reload + @sheet_panel4.t.should eq 2 + end + it '5件目は前に詰められる' do + @sheet_panel3.destroy_and_shorten + @sheet_panel5.reload + @sheet_panel5.t.should eq 3 + end + end + #ロールバックテスト。切り詰めが直接DBをいじるので、すべてのケースで確実にロールバックを確認する + end +end diff --git a/spec/models/sheet_spec.rb b/spec/models/sheet_spec.rb new file mode 100644 index 00000000..20768233 --- /dev/null +++ b/spec/models/sheet_spec.rb @@ -0,0 +1,675 @@ +# -*- encoding: utf-8 -*- +require 'spec_helper' +#用紙 + +describe Sheet do + before do + SpeechBalloonTemplate.delete_all + @admin = FactoryGirl.create :admin + @demand_user = FactoryGirl.create :demand_user + @sp = FactoryGirl.create :system_picture + @lg = FactoryGirl.create :license_group + @license = FactoryGirl.create :license, :license_group_id => @lg.id, :system_picture_id => @sp.id + @user = FactoryGirl.create( :user_yas) + @author = FactoryGirl.create :author, :user_id => @user.id + @artist = FactoryGirl.create :artist_yas, :author_id => @author.id + @other_user = FactoryGirl.create( :user_yas) + @other_author = FactoryGirl.create :author, :user_id => @other_user.id + @other_artist = FactoryGirl.create :artist_yas, :author_id => @other_author.id + end + + describe '検証に於いて' do + before do + @sheet = FactoryGirl.build :sheet, :author_id => @author.id + end + + context 'オーソドックスなデータのとき' do + it '下限データが通る' do + @sheet.caption = 'a' + @sheet.visible = 0 + @sheet.should be_valid + end + it '上限データが通る' do + @sheet.caption = 'a'*100 + @sheet.visible = 1 + @sheet.should be_valid + end + end + + context 'captionを検証するとき' do + it 'nullなら失敗する' do + @sheet.caption = nil + @sheet.should_not be_valid + end + it '100文字以上なら失敗する' do + @sheet.caption = 'a'*101 + @sheet.should_not be_valid + end + end + context 'visibleを検証するとき' do + it 'nullなら失敗する' do + @sheet.visible = nil + @sheet.should_not be_valid + end + it '負なら失敗する' do + @sheet.visible = -1 + @sheet.should_not be_valid + end + it '2以上なら失敗する' do + @sheet.visible = 2 + @sheet.should_not be_valid + end + end + end + + describe '文字コード検証に於いて' do + before do + @sheet = FactoryGirl.build :sheet, :author_id => @author.id + end + + context 'captionを検証するとき' do + it 'Shift JISなら失敗する' do + @sheet.caption = "\x83G\x83r\x83]\x83D" + lambda{ + @sheet.valid_encode + }.should raise_error(Pettanr::BadRequest) + end + end + + end + + describe 'デフォルト値補充に於いて' do + it 'visibleが0になっている' do + @sheet = FactoryGirl.build :sheet, :visible => nil + @sheet.supply_default + @sheet.visible.should eq 0 + end + end + + describe '上書き補充に於いて' do + it '作家idが設定されている' do + @sheet = FactoryGirl.build :sheet, :author_id => nil + @sheet.overwrite @author + @sheet.author_id.should eq @author.id + end + end + + describe '所持判定に於いて' do + before do + @sheet = FactoryGirl.build :sheet, :author_id => @author.id + end + context '事前チェックする' do + it '自身にロールリストからの作家取得を依頼している' do + Sheet.should_receive(:get_author_from_roles).with(any_args).exactly(1) + r = @sheet.own?([@author]) + end + end + context 'ロール内作家が取得できるとき' do + before do + end + it 'ロール内作家のidが自身の作家idと一致するなら許可する' do + Sheet.stub(:get_author_from_roles).with(any_args).and_return(@author) + r = @sheet.own?([@author]) + r.should be_true + end + it 'ロール内作家のidが自身の作家idと一致しないならno' do + Sheet.stub(:get_author_from_roles).with(any_args).and_return(@other_author) + @sheet.own?(@other_author).should be_false + end + end + context 'ロール内作家が取得できないとき' do + before do + Sheet.stub(:get_author_from_roles).with(any_args).and_return(nil) + end + it 'Falseを返す' do + r = @sheet.own?([@author]) + r.should be_false + end + end + end + + describe '閲覧許可に於いて' do + before do + @sheet = FactoryGirl.build :sheet, :author_id => @author.id + end + context 'オープンモードのとき' do + before do + MagicNumber['run_mode'] = 0 + end + it '自身にゲスト用ロールチェックを問い合わせしている' do + Sheet.any_instance.stub(:guest_role_check).and_return(true) + Sheet.any_instance.should_receive(:guest_role_check).with(any_args).exactly(1) + r = @sheet.visible?([@author]) + end + it 'ゲスト用ロールチェックが失敗したとき、falseを返す' do + Sheet.any_instance.stub(:guest_role_check).and_return(false) + r = @sheet.visible?([@author]) + r.should be_false + end + end + context 'クローズドモードのとき' do + before do + MagicNumber['run_mode'] = 1 + end + it '自身に読者用ロールチェックを問い合わせしている' do + Sheet.any_instance.stub(:reader_role_check).and_return(true) + Sheet.any_instance.should_receive(:reader_role_check).with(any_args).exactly(1) + r = @sheet.visible?([@author]) + end + it '読者用ロールチェックが失敗したとき、falseを返す' do + Sheet.any_instance.stub(:reader_role_check).and_return(false) + r = @sheet.visible?([@author]) + r.should be_false + end + end + context '事前チェックする' do + before do + MagicNumber['run_mode'] = 1 + Sheet.any_instance.stub(:reader_role_check).and_return(true) + Sheet.any_instance.stub(:own?).and_return(true) + end + it '自身に所持判定を問い合わせしている' do + Sheet.any_instance.should_receive(:own?).with(any_args).exactly(1) + r = @sheet.visible?([@author]) + end + end + context 'つつがなく終わるとき' do + before do + MagicNumber['run_mode'] = 1 + Sheet.any_instance.stub(:reader_role_check).and_return(true) + end + it '自分の用紙なら許可する' do + Sheet.any_instance.stub(:own?).and_return(true) + Sheet.any_instance.stub(:visible).and_return(0) + r = @sheet.visible?([@author]) + r.should be_true + end + it '他人の非公開用紙なら許可しない' do + Sheet.any_instance.stub(:own?).and_return(false) + Sheet.any_instance.stub(:visible).and_return(0) + r = @sheet.visible?([@author]) + r.should be_false + end + it '他人の用紙でも公開なら許可する' do + Sheet.any_instance.stub(:own?).and_return(false) + Sheet.any_instance.stub(:visible).and_return(1) + r = @sheet.visible?([@author]) + r.should be_true + end + end + end + + describe '一覧取得に於いて' do + before do + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + end + context 'page補正について' do + it '文字列から数値に変換される' do + Sheet.page('8').should eq 8 + end + it 'nilの場合は1になる' do + Sheet.page().should eq 1 + end + it '0以下の場合は1になる' do + Sheet.page('0').should eq 1 + end + end + context 'page_size補正について' do + it '文字列から数値に変換される' do + Sheet.page_size('7').should eq 7 + end + it 'nilの場合はSheet.default_page_sizeになる' do + Sheet.page_size().should eq Sheet.default_page_size + end + it '0以下の場合はSheet.default_page_sizeになる' do + Sheet.page_size('0').should eq Sheet.default_page_size + end + it 'Sheet.max_page_sizeを超えた場合はSheet.max_page_sizeになる' do + Sheet.page_size('1000').should eq Sheet.max_page_size + end + end + context 'つつがなく終わるとき' do + it '一覧取得オプションを利用している' do + Sheet.stub(:list_opt).with(any_args).and_return({}) + Sheet.should_receive(:list_opt).with(any_args).exactly(1) + r = Sheet.list + end + end + it 'リストを返す' do + c = Sheet.list + c.should eq [@sheet] + end + it '非公開用紙は(自分の用紙であっても)含んでいない' do + FactoryGirl.create :sheet, :author_id => @author.id, :visible => 0 + c = Sheet.list + c.should eq [@sheet] + end + it '時系列で並んでいる' do + #公開用紙は(他人の用紙であっても)含んでいる + v = FactoryGirl.create :sheet, :author_id => @other_author.id, :updated_at => Time.now + 100 + c = Sheet.list + c.should eq [v, @sheet] + end + context 'DBに5件あって1ページの件数を2件に変えたとして' do + before do + @sheet2 = FactoryGirl.create :sheet, :author_id => @author.id, :updated_at => Time.now + 100 + @sheet3 = FactoryGirl.create :sheet, :author_id => @author.id, :updated_at => Time.now + 200 + @sheet4 = FactoryGirl.create :sheet, :author_id => @author.id, :updated_at => Time.now + 300 + @sheet5 = FactoryGirl.create :sheet, :author_id => @author.id, :updated_at => Time.now + 400 + Sheet.stub(:default_page_size).and_return(2) + end + it '通常は2件を返す' do + c = Sheet.list + c.should have(2).items + end + it 'page=1なら末尾2件を返す' do + #時系列で並んでいる + c = Sheet.list(1) + c.should eq [@sheet5, @sheet4] + end + it 'page=2なら中間2件を返す' do + c = Sheet.list(2) + c.should eq [@sheet3, @sheet2] + end + it 'page=3なら先頭1件を返す' do + c = Sheet.list(3) + c.should eq [@sheet] + end + end + end + + describe '自分の用紙一覧取得に於いて' do + before do + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + end + context 'つつがなく終わるとき' do + it '一覧取得オプションを利用している' do + Sheet.stub(:list_opt).with(any_args).and_return({}) + Sheet.should_receive(:list_opt).with(any_args).exactly(1) + r = Sheet.mylist @author + end + end + it 'リストを返す' do + c = Sheet.mylist @author + c.should eq [@sheet] + end + it '時系列で並んでいる' do + nc = FactoryGirl.create :sheet, :author_id => @author.id, :updated_at => Time.now + 100 + cl = Sheet.mylist @author + cl.should eq [nc, @sheet] + end + it '他人の用紙は公開でも含まない' do + nc = FactoryGirl.create :sheet, :author_id => @other_author.id, :visible => 1 + cl = Sheet.mylist @author + cl.should eq [@sheet] + end + it '自分の用紙は非公開でも含んでいる' do + nc = FactoryGirl.create :sheet, :author_id => @author.id, :visible => 0, :updated_at => Time.now + 100 + cl = Sheet.mylist @author + cl.should eq [nc, @sheet] + end + context 'DBに5件あって1ページの件数を2件に変えたとして' do + before do + @sheet2 = FactoryGirl.create :sheet, :author_id => @author.id, :updated_at => Time.now + 100 + @sheet3 = FactoryGirl.create :sheet, :author_id => @author.id, :updated_at => Time.now + 200 + @sheet4 = FactoryGirl.create :sheet, :author_id => @author.id, :updated_at => Time.now + 300 + @sheet5 = FactoryGirl.create :sheet, :author_id => @author.id, :updated_at => Time.now + 400 + end + it '通常は2件を返す' do + c = Sheet.mylist @author, 1, 2 + c.should have(2).items + end + it 'page=1なら末尾2件を返す' do + #時系列で並んでいる + c = Sheet.mylist(@author, 1, 2) + c.should eq [@sheet5, @sheet4] + end + it 'page=2なら中間2件を返す' do + c = Sheet.mylist(@author, 2, 2) + c.should eq [@sheet3, @sheet2] + end + it 'page=3なら先頭1件を返す' do + c = Sheet.mylist(@author, 3, 2) + c.should eq [@sheet] + end + end + end + + describe '他作家の用紙一覧取得に於いて' do + before do + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @other_sheet = FactoryGirl.create :sheet, :author_id => @other_author.id, :visible => 1 + end + context 'つつがなく終わるとき' do + it '一覧取得オプションを利用している' do + Sheet.stub(:list_opt).with(any_args).and_return({}) + Sheet.should_receive(:list_opt).with(any_args).exactly(1) + r = Sheet.himlist @other_author + end + end + it '指定した作家のリストを返す' do + r = Sheet.himlist @other_author + r.should eq [@other_sheet] + end + it '時系列で並んでいる' do + nc = FactoryGirl.create :sheet, :author_id => @other_author.id, :updated_at => Time.now + 100 + r = Sheet.himlist @other_author + r.should eq [nc, @other_sheet] + end + it '公開用紙に限る ' do + hidden = FactoryGirl.create :sheet, :author_id => @other_author.id, :visible => 0 + r = Sheet.himlist @other_author + r.should eq [@other_sheet] + end + context 'DBに5件あって1ページの件数を2件に変えたとして' do + before do + @other_sheet2 = FactoryGirl.create :sheet, :author_id => @other_author.id, :updated_at => Time.now + 100 + @other_sheet3 = FactoryGirl.create :sheet, :author_id => @other_author.id, :updated_at => Time.now + 200 + @other_sheet4 = FactoryGirl.create :sheet, :author_id => @other_author.id, :updated_at => Time.now + 300 + @other_sheet5 = FactoryGirl.create :sheet, :author_id => @other_author.id, :updated_at => Time.now + 400 + end + it '通常は2件を返す' do + c = Sheet.himlist @other_author, 1, 2 + c.should have(2).items + end + it 'page=1なら末尾2件を返す' do + #時系列で並んでいる + c = Sheet.himlist(@other_author, 1, 2) + c.should eq [@other_sheet5, @other_sheet4] + end + it 'page=2なら中間2件を返す' do + c = Sheet.himlist(@other_author, 2, 2) + c.should eq [@other_sheet3, @other_sheet2] + end + it 'page=3なら先頭1件を返す' do + c = Sheet.himlist(@other_author, 3, 2) + c.should eq [@other_sheet] + end + end + end + + describe '用紙一覧ページ制御に於いて' do + before do + Sheet.stub(:count).with(any_args).and_return(100) + end + it 'ページ制御を返す' do + r = Sheet.list_paginate + r.is_a?(Kaminari::PaginatableArray).should be_true + end + it '用紙一覧の取得条件を利用している' do + Sheet.stub(:list_where).with(any_args).and_return('') + Sheet.should_receive(:list_where).with(any_args).exactly(1) + r = Sheet.list_paginate + end + it 'ページ件数10のとき、3ページ目のオフセットは20から始まる' do + r = Sheet.list_paginate 3, 10 + r.limit_value.should eq 10 + r.offset_value.should eq 20 + end + end + + describe '自分の用紙一覧ページ制御に於いて' do + before do + Sheet.stub(:count).with(any_args).and_return(100) + end + it 'ページ制御を返す' do + r = Sheet.mylist_paginate @author + r.is_a?(Kaminari::PaginatableArray).should be_true + end + it '自分の用紙一覧の取得条件を利用している' do + Sheet.stub(:mylist_where).with(any_args).and_return('') + Sheet.should_receive(:mylist_where).with(any_args).exactly(1) + r = Sheet.mylist_paginate @author + end + it 'ページ件数10のとき、3ページ目のオフセットは20から始まる' do + r = Sheet.mylist_paginate @author, 3, 10 + r.limit_value.should eq 10 + r.offset_value.should eq 20 + end + end + + describe '他作家の用紙一覧ページ制御に於いて' do + before do + Sheet.stub(:count).with(any_args).and_return(100) + end + it 'ページ制御を返す' do + r = Sheet.himlist_paginate @other_author + r.is_a?(Kaminari::PaginatableArray).should be_true + end + it '他作家の用紙一覧の取得条件を利用している' do + Sheet.stub(:himlist_where).with(any_args).and_return('') + Sheet.should_receive(:himlist_where).with(any_args).exactly(1) + r = Sheet.himlist_paginate @other_author + end + it 'ページ件数10のとき、3ページ目のオフセットは20から始まる' do + r = Sheet.himlist_paginate @other_author, 3, 10 + r.limit_value.should eq 10 + r.offset_value.should eq 20 + end + end + + describe '一覧取得オプションに於いて' do + it '2つの項目を含んでいる' do + r = Sheet.list_opt + r.should have(2).items + end + it 'スクコマを含んでいる' do + r = Sheet.list_opt + r.has_key?(:sheet_panels).should be_true + end + it 'スクコマはコマを含んでいる' do + r = Sheet.list_opt + r[:sheet_panels].has_key?(:panel).should be_true + end + it '作家を含んでいる' do + r = Sheet.list_opt + r.has_key?(:author).should be_true + end + end + describe 'json一覧出力オプションに於いて' do + before do + @op = FactoryGirl.create :original_picture, :artist_id => @artist.id + @p = FactoryGirl.create :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id + @rp = FactoryGirl.create :resource_picture, :artist_id => @artist.id, :license_id => @license.id, :original_picture_id => @op.id, :picture_id => @p.id + @sbt = FactoryGirl.create :speech_balloon_template + @sheet = FactoryGirl.create :sheet, :author_id => @author.id, :visible => 1 + @panel = FactoryGirl.create :panel, :author_id => @author.id, :publish => 1 + @sheet_panel = FactoryGirl.create :sheet_panel, :author_id => @author.id, :sheet_id => @sheet.id, :panel_id => @panel.id + end + it 'スクコマを含んでいる' do + r = Sheet.list.to_json Sheet.list_json_opt + j = JSON.parse r + i = j.first + i.has_key?('sheet_panels').should be_true + end + it 'スクコマはコマを含んでいる' do + r = Sheet.list.to_json Sheet.list_json_opt + j = JSON.parse r + i = j.first + s = i['sheet_panels'].first + s.has_key?('panel').should be_true + end + it '作家を含んでいる' do + r = Sheet.list.to_json Sheet.list_json_opt + j = JSON.parse r + i = j.first + i.has_key?('author').should be_true + end + end + + describe '単体取得に於いて' do + before do + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + end + context 'つつがなく終わるとき' do + it '単体取得オプションを利用している' do + Sheet.stub(:show_opt).with(any_args).and_return({}) + Sheet.should_receive(:show_opt).with(any_args).exactly(1) + r = Sheet.show @sheet.id, @author + end + it '閲覧許可を問い合わせている' do + Sheet.any_instance.stub(:visible?).with(any_args).and_return(true) + Sheet.any_instance.should_receive(:visible?).with(any_args).exactly(1) + r = Sheet.show @sheet.id, @author + end + end + it '指定の用紙を返す' do + c = Sheet.show @sheet.id, @author + c.should eq @sheet + end + context '閲覧許可が出なかったとき' do + it '403Forbidden例外を返す' do + Sheet.any_instance.stub(:visible?).and_return(false) + lambda{ + Sheet.show @sheet.id, @author + }.should raise_error(ActiveRecord::Forbidden) + end + end + context '存在しない用紙を開こうとしたとき' do + it '404RecordNotFound例外を返す' do + lambda{ + Sheet.show 110, @author + }.should raise_error(ActiveRecord::RecordNotFound) + end + end + end + + describe '編集取得に於いて' do + before do + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + end + context 'つつがなく終わるとき' do + it '単体取得オプションを利用している' do + Sheet.stub(:show_opt).with(any_args).and_return({}) + Sheet.should_receive(:show_opt).with(any_args).exactly(1) + r = Sheet.edit @sheet.id, @author + end + it '所持判定を問い合わせている' do + Sheet.any_instance.stub(:own?).with(any_args).and_return(true) + Sheet.any_instance.should_receive(:own?).with(any_args).exactly(1) + r = Sheet.edit @sheet.id, @author + end + end + it '指定の用紙を返す' do + Sheet.any_instance.stub(:own?).and_return(true) + c = Sheet.edit @sheet.id, @author.id + c.should eq @sheet + end + context '他人の用紙を開こうとしたとき' do + it '403Forbidden例外を返す' do + Sheet.any_instance.stub(:own?).and_return(false) + lambda{ + Sheet.edit @sheet.id, @author + }.should raise_error(ActiveRecord::Forbidden) + end + end + context '存在しない用紙を開こうとしたとき' do + it '404RecordNotFound例外を返す' do + lambda{ + Sheet.edit 110, @author + }.should raise_error(ActiveRecord::RecordNotFound) + end + end + end + describe '単体取得オプションに於いて' do + it 'includeキーを含んでいる' do + r = Sheet.show_opt + r.has_key?(:include).should be_true + end + it '2つの項目を含んでいる' do + r = Sheet.show_opt[:include] + r.should have(2).items + end + it '作家を含んでいる' do + r = Sheet.show_opt[:include] + r.has_key?(:author).should be_true + end + it 'スクコマを含んでいる' do + r = Sheet.show_opt[:include] + r.has_key?(:sheet_panels).should be_true + end + it 'スクコマはコマを含んでいる' do + r = Sheet.show_opt[:include] + r[:sheet_panels].has_key?(:panel).should be_true + end + end + describe 'json単体出力オプションに於いて' do + before do + @op = FactoryGirl.create :original_picture, :artist_id => @artist.id + @p = FactoryGirl.create :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id + @rp = FactoryGirl.create :resource_picture, :artist_id => @artist.id, :license_id => @license.id, :original_picture_id => @op.id, :picture_id => @p.id + @sbt = FactoryGirl.create :speech_balloon_template + @sheet = FactoryGirl.create :sheet, :author_id => @author.id, :visible => 1 + @panel = FactoryGirl.create :panel, :author_id => @author.id, :publish => 1 + @sheet_panel = FactoryGirl.create :sheet_panel, :author_id => @author.id, :sheet_id => @sheet.id, :panel_id => @panel.id + end + it 'スクコマを含んでいる' do + r = Sheet.show(@sheet.id, @author).to_json Sheet.show_json_opt + j = JSON.parse r + i = j + i.has_key?('sheet_panels').should be_true + end + it 'スクコマはコマを含んでいる' do + r = Sheet.show(@sheet.id, @author).to_json Sheet.show_json_opt + j = JSON.parse r + i = j + s = i['sheet_panels'].first + s.has_key?('panel').should be_true + end + it '作家を含んでいる' do + r = Sheet.show(@sheet.id, @author).to_json Sheet.show_json_opt + j = JSON.parse r + i = j + i.has_key?('author').should be_true + end + end + + describe '削除に於いて' do + before do + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @panel = FactoryGirl.create :panel, :author_id => @author.id, :publish => 1 + @sheet_panel = FactoryGirl.create :sheet_panel, :author_id => @author.id, :sheet_id => @sheet.id, :panel_id => @panel.id + @other_sheet = FactoryGirl.create :sheet, :author_id => @author.id + @other_sheet_panel = FactoryGirl.create :sheet_panel, :author_id => @author.id, :sheet_id => @other_sheet.id, :panel_id => @panel.id + end + context 'つつがなく終わるとき' do + it '自身を削除する' do + lambda { + r = @sheet.destroy_with_sheet_panel + }.should change(Sheet, :count).by(-1) + lambda { + r = Sheet.find @sheet.id + }.should raise_error + end + it '自身にリンクしているスクコマをすべて削除する' do + lambda { + r = @sheet.destroy_with_sheet_panel + }.should change(SheetPanel, :count).by(-1) + lambda { + r = SheetPanel.find @sheet_panel.id + }.should raise_error + end + it 'Trueを返す' do + r = @sheet.destroy_with_sheet_panel + r.should be_true + end + end + context '削除に失敗したとき' do + before do + SheetPanel.any_instance.stub(:destroy).with(any_args).and_return(false) + end + it 'Falseを返す' do + r = @sheet.destroy_with_sheet_panel + r.should be_false + end + it 'ロールバックしている' do + lambda { + r = @sheet.destroy_with_sheet_panel + }.should_not change(Sheet, :count) + lambda { + r = @sheet.destroy_with_sheet_panel + }.should_not change(SheetPanel, :count) + end + end + end +end diff --git a/spec/models/speech_balloon_spec.rb b/spec/models/speech_balloon_spec.rb index 4d63acae..da4ea568 100644 --- a/spec/models/speech_balloon_spec.rb +++ b/spec/models/speech_balloon_spec.rb @@ -4,6 +4,7 @@ require 'spec_helper' describe SpeechBalloon do before do + SpeechBalloonTemplate.delete_all @admin = FactoryGirl.create :admin @user = FactoryGirl.create( :user_yas) @author = FactoryGirl.create :author, :user_id => @user.id diff --git a/spec/models/speech_balloon_template_spec.rb b/spec/models/speech_balloon_template_spec.rb index 544879a5..6797ae57 100644 --- a/spec/models/speech_balloon_template_spec.rb +++ b/spec/models/speech_balloon_template_spec.rb @@ -3,6 +3,7 @@ require 'spec_helper' #フキダシテンプレート describe SpeechBalloonTemplate do before do + SpeechBalloonTemplate.delete_all #テストデータを用意してね @f = Rails.root + 'spec/json/speech_balloon_template.json' @t = File.open(@f, 'r').read diff --git a/spec/models/speech_spec.rb b/spec/models/speech_spec.rb index 3e18d1eb..51af8e19 100644 --- a/spec/models/speech_spec.rb +++ b/spec/models/speech_spec.rb @@ -4,6 +4,7 @@ require 'spec_helper' describe Speech do before do + SpeechBalloonTemplate.delete_all @admin = FactoryGirl.create :admin @user = FactoryGirl.create( :user_yas) @author = FactoryGirl.create :author, :user_id => @user.id @@ -15,6 +16,7 @@ describe Speech do @license = FactoryGirl.create :license, :license_group_id => @lg.id, :system_picture_id => @sp.id @writing_format = FactoryGirl.create :writing_format + SpeechBalloonTemplate.delete_all @speech_balloon_template = FactoryGirl.create :speech_balloon_template, "name" => "circle@pettan.com", "classname" => "CircleSpeechBalloon", "caption" => "cc", "system_picture_id" => @sp.id, "settings" => '{}' @panel = FactoryGirl.create :panel, :author_id => @author.id end @@ -429,37 +431,37 @@ describe Speech do before do @sb2 = FactoryGirl.build :speech_balloon, :panel_id => @panel.id, :speech_balloon_template_id => @speech_balloon_template.id @speech2 = @sb2.build_speech( - FactoryGirl.attributes_for(:speech, :writing_format_id => @writing_format.id) + FactoryGirl.attributes_for(:speech, :writing_format_id => @writing_format.id, :updated_at => Time.now + 100) ) @balloon2 = @sb2.build_balloon( - FactoryGirl.attributes_for(:balloon, :system_picture_id => @sp.id, :updated_at => Time.now + 100) + FactoryGirl.attributes_for(:balloon, :system_picture_id => @sp.id) ) @sb2.boost @sb2.save! @sb3 = FactoryGirl.build :speech_balloon, :panel_id => @panel.id, :speech_balloon_template_id => @speech_balloon_template.id @speech3 = @sb3.build_speech( - FactoryGirl.attributes_for(:speech, :writing_format_id => @writing_format.id) + FactoryGirl.attributes_for(:speech, :writing_format_id => @writing_format.id, :updated_at => Time.now + 200) ) @balloon3 = @sb3.build_balloon( - FactoryGirl.attributes_for(:balloon, :system_picture_id => @sp.id, :updated_at => Time.now + 200) + FactoryGirl.attributes_for(:balloon, :system_picture_id => @sp.id) ) @sb3.boost @sb3.save! @sb4 = FactoryGirl.build :speech_balloon, :panel_id => @panel.id, :speech_balloon_template_id => @speech_balloon_template.id @speech4 = @sb4.build_speech( - FactoryGirl.attributes_for(:speech, :writing_format_id => @writing_format.id) + FactoryGirl.attributes_for(:speech, :writing_format_id => @writing_format.id, :updated_at => Time.now + 300) ) @balloon4 = @sb4.build_balloon( - FactoryGirl.attributes_for(:balloon, :system_picture_id => @sp.id, :updated_at => Time.now + 300) + FactoryGirl.attributes_for(:balloon, :system_picture_id => @sp.id) ) @sb4.boost @sb4.save! @sb5 = FactoryGirl.build :speech_balloon, :panel_id => @panel.id, :speech_balloon_template_id => @speech_balloon_template.id @speech5 = @sb5.build_speech( - FactoryGirl.attributes_for(:speech, :writing_format_id => @writing_format.id) + FactoryGirl.attributes_for(:speech, :writing_format_id => @writing_format.id, :updated_at => Time.now + 400) ) @balloon5 = @sb5.build_balloon( - FactoryGirl.attributes_for(:balloon, :system_picture_id => @sp.id, :updated_at => Time.now + 400) + FactoryGirl.attributes_for(:balloon, :system_picture_id => @sp.id) ) @sb5.boost @sb5.save! @@ -487,37 +489,37 @@ describe Speech do before do @sb2 = FactoryGirl.build :speech_balloon, :panel_id => @panel.id, :speech_balloon_template_id => @speech_balloon_template.id @speech2 = @sb2.build_speech( - FactoryGirl.attributes_for(:speech, :writing_format_id => @writing_format.id) + FactoryGirl.attributes_for(:speech, :writing_format_id => @writing_format.id, :updated_at => Time.now + 100) ) @balloon2 = @sb2.build_balloon( - FactoryGirl.attributes_for(:balloon, :system_picture_id => @sp.id, :updated_at => Time.now + 100) + FactoryGirl.attributes_for(:balloon, :system_picture_id => @sp.id) ) @sb2.boost @sb2.save! @sb3 = FactoryGirl.build :speech_balloon, :panel_id => @panel.id, :speech_balloon_template_id => @speech_balloon_template.id @speech3 = @sb3.build_speech( - FactoryGirl.attributes_for(:speech, :writing_format_id => @writing_format.id) + FactoryGirl.attributes_for(:speech, :writing_format_id => @writing_format.id, :updated_at => Time.now + 200) ) @balloon3 = @sb3.build_balloon( - FactoryGirl.attributes_for(:balloon, :system_picture_id => @sp.id, :updated_at => Time.now + 200) + FactoryGirl.attributes_for(:balloon, :system_picture_id => @sp.id) ) @sb3.boost @sb3.save! @sb4 = FactoryGirl.build :speech_balloon, :panel_id => @panel.id, :speech_balloon_template_id => @speech_balloon_template.id @speech4 = @sb4.build_speech( - FactoryGirl.attributes_for(:speech, :writing_format_id => @writing_format.id) + FactoryGirl.attributes_for(:speech, :writing_format_id => @writing_format.id, :updated_at => Time.now + 300) ) @balloon4 = @sb4.build_balloon( - FactoryGirl.attributes_for(:balloon, :system_picture_id => @sp.id, :updated_at => Time.now + 300) + FactoryGirl.attributes_for(:balloon, :system_picture_id => @sp.id) ) @sb4.boost @sb4.save! @sb5 = FactoryGirl.build :speech_balloon, :panel_id => @panel.id, :speech_balloon_template_id => @speech_balloon_template.id @speech5 = @sb5.build_speech( - FactoryGirl.attributes_for(:speech, :writing_format_id => @writing_format.id) + FactoryGirl.attributes_for(:speech, :writing_format_id => @writing_format.id, :updated_at => Time.now + 400) ) @balloon5 = @sb5.build_balloon( - FactoryGirl.attributes_for(:balloon, :system_picture_id => @sp.id, :updated_at => Time.now + 400) + FactoryGirl.attributes_for(:balloon, :system_picture_id => @sp.id) ) @sb5.boost @sb5.save! diff --git a/spec/models/story_sheet_spec.rb b/spec/models/story_sheet_spec.rb new file mode 100644 index 00000000..b00d8a91 --- /dev/null +++ b/spec/models/story_sheet_spec.rb @@ -0,0 +1,1856 @@ +# -*- encoding: utf-8 -*- +require 'spec_helper' +#スト紙 +describe StorySheet do + before do + @admin = FactoryGirl.create :admin + @sp = FactoryGirl.create :system_picture + @lg = FactoryGirl.create :license_group + @license = FactoryGirl.create :license, :license_group_id => @lg.id, :system_picture_id => @sp.id + SpeechBalloonTemplate.delete_all + @speech_balloon_template = FactoryGirl.create :speech_balloon_template, "name" => "circle@pettan.com", "classname" => "CircleSpeechBalloon", "caption" => "cc", "system_picture_id" => @sp.id, "settings" => '{}' + @writing_format = FactoryGirl.create :writing_format + @user = FactoryGirl.create( :user_yas) + @author = FactoryGirl.create :author, :user_id => @user.id + @artist = FactoryGirl.create :artist_yas, :author_id => @author.id + @other_user = FactoryGirl.create( :user_yas) + @other_author = FactoryGirl.create :author, :user_id => @other_user.id + @op = FactoryGirl.create :original_picture, :artist_id => @artist.id + @p = FactoryGirl.create :picture, :original_picture_id => @op.id, :license_id => @license.id, :artist_id => @artist.id + @rp = FactoryGirl.create :resource_picture, :artist_id => @artist.id, :license_id => @license.id, :original_picture_id => @op.id, :picture_id => @p.id + end + + describe '検証に於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @story = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id, :visible => 1 + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @story_sheet = FactoryGirl.build :story_sheet, :author_id => @author.id, :story_id => @story.id, :sheet_id => @sheet.id + end + + context 'オーソドックスなデータのとき' do + it '下限データが通る' do + @story_sheet.t = 0 + @story_sheet.should be_valid + end + it '上限データが通る' do + @story_sheet.t = 99999 + @story_sheet.should be_valid + end + end + + context 'story_idを検証するとき' do + it 'nullなら失敗する' do + @story_sheet.story_id = nil + @story_sheet.should_not be_valid + end + it '数値でなければ失敗する' do + @story_sheet.story_id = 'a' + @story_sheet.should_not be_valid + end + it '存在するストーリーでなければ失敗する' do + @story_sheet.story_id = 0 + @story_sheet.should_not be_valid + end + end + + context 'sheet_idを検証するとき' do + it 'nullなら失敗する' do + @story_sheet.sheet_id = nil + @story_sheet.should_not be_valid + end + it '数値でなければ失敗する' do + @story_sheet.sheet_id = 'a' + @story_sheet.should_not be_valid + end + it '存在する用紙でなければ失敗する' do + @story_sheet.sheet_id = 0 + @story_sheet.should_not be_valid + end + end + + context 'tを検証するとき' do + it 'nullなら失敗する' do + @story_sheet.t = nil + @story_sheet.should_not be_valid + end + it '数値でなければ失敗する' do + @story_sheet.t = 'a' + @story_sheet.should_not be_valid + end + it '負なら失敗する' do + @story_sheet.t = -1 + @story_sheet.should_not be_valid + end + end + + context 'author_idを検証するとき' do + it 'nullなら失敗する' do + @story_sheet.author_id = nil + @story_sheet.should_not be_valid + end + it '数値でなければ失敗する' do + @story_sheet.author_id = 'a' + @story_sheet.should_not be_valid + end + it '存在する作家でなければ失敗する' do + @story_sheet.author_id = 0 + @story_sheet.should_not be_valid + end + end + context '全体を検証するとき' do + end + end + + describe 'デフォルト値補充に於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @story = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id, :visible => 1 + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + end + + #dbのデフォルト値が0だから明示的にnilにしないと追加ができない + it 'tをnilにする' do + @story_sheet = FactoryGirl.build :story_sheet, :story_id => @story.id, :sheet_id => @sheet.id + @story_sheet.supply_default + @story_sheet.t.should be_nil + end + + end + + describe '上書き補充に於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @story = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id, :visible => 1 + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + end + + context 'author_idを補充' do + it '問答無用でauthor_idを補充する' do + @story_sheet = FactoryGirl.build :story_sheet, :story_id => @story.id, :sheet_id => @sheet.id + @story_sheet.author_id = nil + @story_sheet.overwrite @author + @story_sheet.author_id.should eq @author.id + end + end + + end + + describe '所持判定に於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @story = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id, :visible => 1 + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @story_sheet = FactoryGirl.create :story_sheet, :author_id => @author.id, :story_id => @story.id, :sheet_id => @sheet.id + @comico = FactoryGirl.create :comic, :author_id => @other_author.id + @storyo = FactoryGirl.create :story, :comic_id => @comico.id, :author_id => @other_author.id + @sheeto = FactoryGirl.create :sheet, :author_id => @other_author.id + @story_sheeto = FactoryGirl.create :story_sheet, :author_id => @other_author.id, :story_id => @storyo.id, :sheet_id => @sheeto.id + end + context '事前チェックする' do + it '自身にロールリストからの作家取得を依頼している' do + StorySheet.should_receive(:get_author_from_roles).with(any_args).exactly(1) + r = @story_sheet.own?([@author]) + end + end + context 'ロール内作家が取得できるとき' do + before do + end + it 'ロール内作家のidが自身の作家idと一致するなら許可する' do + StorySheet.stub(:get_author_from_roles).with(any_args).and_return(@author) + r = @story_sheet.own?([@author]) + r.should be_true + end + it 'ロール内作家のidが自身の作家idと一致しないならno' do + StorySheet.stub(:get_author_from_roles).with(any_args).and_return(@other_author) + @story_sheet.own?(@other_author).should be_false + end + end + context 'ロール内作家が取得できないとき' do + before do + StorySheet.stub(:get_author_from_roles).with(any_args).and_return(nil) + end + it 'Falseを返す' do + r = @story_sheet.own?([@author]) + r.should be_false + end + end + end + + describe '閲覧許可に於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @story = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id, :visible => 1 + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @story_sheet = FactoryGirl.create :story_sheet, :author_id => @author.id, :story_id => @story.id, :sheet_id => @sheet.id + end + context 'オープンモードのとき' do + before do + MagicNumber['run_mode'] = 0 + end + it '自身にゲスト用ロールチェックを問い合わせしている' do + StorySheet.any_instance.stub(:guest_role_check).and_return(true) + StorySheet.any_instance.should_receive(:guest_role_check).with(any_args).exactly(1) + r = @story_sheet.visible?([@author]) + end + it 'ゲスト用ロールチェックが失敗したとき、falseを返す' do + StorySheet.any_instance.stub(:guest_role_check).and_return(false) + r = @story_sheet.visible?([@author]) + r.should be_false + end + end + context 'クローズドモードのとき' do + before do + MagicNumber['run_mode'] = 1 + end + it '自身に読者用ロールチェックを問い合わせしている' do + StorySheet.any_instance.stub(:reader_role_check).and_return(true) + StorySheet.any_instance.should_receive(:reader_role_check).with(any_args).exactly(1) + r = @story_sheet.visible?([@author]) + end + it '読者用ロールチェックが失敗したとき、falseを返す' do + StorySheet.any_instance.stub(:reader_role_check).and_return(false) + r = @story_sheet.visible?([@author]) + r.should be_false + end + end + context '事前チェックする' do + before do + MagicNumber['run_mode'] = 1 + StorySheet.any_instance.stub(:reader_role_check).and_return(true) + end + it '自身のストーリーに所持判定を問い合わせしている' do + Story.any_instance.stub(:own?).and_return(true) + Story.any_instance.should_receive(:own?).with(any_args).exactly(1) + r = @story_sheet.visible?([@author]) + end + it '自身のストーリーに閲覧許可を問い合わせしている' do + Story.any_instance.stub(:own?).and_return(false) + Story.any_instance.stub(:visible?).and_return(true) + Story.any_instance.should_receive(:visible?).with(any_args).exactly(1) + r = @story_sheet.visible?([@author]) + end + end + context 'つつがなく終わるとき' do + before do + MagicNumber['run_mode'] = 1 + StorySheet.any_instance.stub(:reader_role_check).and_return(true) + end + it '自分のストーリーのスト紙なら許可する' do + Story.any_instance.stub(:own?).and_return(true) + Story.any_instance.stub(:visible).and_return(0) + r = @story_sheet.visible?([@author]) + r.should be_true + end + it '他人の非公開ストーリーのスト紙なら許可しない' do + Story.any_instance.stub(:own?).and_return(false) + Story.any_instance.stub(:visible).and_return(0) + r = @story_sheet.visible?([@author]) + r.should be_false + end + it '他人のストーリーのスト紙でも公開なら許可する' do + Story.any_instance.stub(:own?).and_return(false) + Story.any_instance.stub(:visible).and_return(1) + r = @story_sheet.visible?([@author]) + r.should be_true + end + end + end + + describe 'プレイリスト取得に於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @story = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id, :visible => 1 + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @sheet2 = FactoryGirl.create :sheet, :author_id => @author.id, :visible => 0 + @story_sheet = FactoryGirl.create :story_sheet, :author_id => @author.id, :story_id => @story.id, :sheet_id => @sheet.id + @other_comic = FactoryGirl.create :comic, :author_id => @other_author.id + @other_story = FactoryGirl.create :story, :comic_id => @other_comic.id, :author_id => @other_author.id, :visible => 1 + @other_sheet = FactoryGirl.create :sheet, :author_id => @other_author.id, :visible => 1 + end + context 'offset補正について' do + it '文字列から数値に変換される' do + StorySheet.offset(100, '8').should eq 8 + end + it 'nilの場合は0になる' do + StorySheet.offset(100).should eq 0 + end + #投稿された用紙数以上の値が指定されたときは、最後の用紙だけになる + #最後の用紙とは、用紙数‐1. + it '1件のときオフセット1なら0になる' do + StorySheet.offset(1, '1').should eq 0 + end + it '5件のときオフセット5なら4になる' do + StorySheet.offset(5, '5').should eq 4 + end + # 負の値が指定されたときは、最後の用紙から数えて用紙を飛ばして表示する。 + #-4のときは、最後から4つの用紙を表示する。 + it '2件のときオフセット-1なら1になる' do + StorySheet.offset(2, '-1').should eq 1 + end + it '5件のときオフセット-2なら3になる' do + StorySheet.offset(5, '-2').should eq 3 + end + # 最終的なが負になるなど、不正な値が入ったときは0となる。 + it '2件のときオフセット-5なら0になる' do + StorySheet.offset(2, '-5').should eq 0 + end + end + context 'sheet_count補正について' do + it '文字列から数値に変換される' do + StorySheet.sheet_count(100, '7').should eq 7 + end + it 'nilの場合はStorySheet.default_sheet_sizeになる' do + StorySheet.sheet_count(100).should eq StorySheet.default_sheet_size + end + it '0以下の場合はStorySheet.default_sheet_sizeになる' do + StorySheet.sheet_count(100, '0').should eq StorySheet.default_sheet_size + end + it 'StorySheet.max_sheet_sizeを超えた場合はStorySheet.max_sheet_sizeになる' do + StorySheet.sheet_count(100, '1000').should eq StorySheet.max_sheet_size + end + end + it 'リストを返す' do + c = StorySheet.play_list @story, @author + c.should eq [@story_sheet] + end + it 't順で並んでいる' do + #公開ストーリーの公開用紙は(他人のストーリーであっても)含んでいる + v = FactoryGirl.create :story_sheet, :author_id => @author.id, :story_id => @story.id, :sheet_id => @sheet.id, :t => 1 + c = StorySheet.play_list @story, @author + c.should eq [ @story_sheet, v] + end + it '非公開の用紙は含んでいる' do + h = FactoryGirl.create :story_sheet, :author_id => @author.id, :story_id => @story.id, :sheet_id => @sheet2.id, :t => 1 + c = StorySheet.play_list @story, @author + c.should eq [ @story_sheet, h] + end + context 'DBに5件あって1ページの件数を2件に変えたとして' do + before do + @story_sheet2 = FactoryGirl.create :story_sheet, :author_id => @author.id, :story_id => @story.id, :sheet_id => @sheet.id, :t => 1 + @story_sheet3 = FactoryGirl.create :story_sheet, :author_id => @author.id, :story_id => @story.id, :sheet_id => @sheet.id, :t => 2 + @story_sheet4 = FactoryGirl.create :story_sheet, :author_id => @author.id, :story_id => @story.id, :sheet_id => @sheet.id, :t => 3 + @story_sheet5 = FactoryGirl.create :story_sheet, :author_id => @author.id, :story_id => @story.id, :sheet_id => @sheet.id, :t => 4 + end + it 'offset=0なら末尾2件を返す' do + #時系列で並んでいる + c = StorySheet.play_list( @story, @author, 0, 2) + c.should eq [@story_sheet, @story_sheet2] + end + it 'offset=2なら中間2件を返す' do + c = StorySheet.play_list(@story, @author, 2, 2) + c.should eq [@story_sheet3, @story_sheet4] + end + it 'offset=4なら先頭1件を返す' do + c = StorySheet.play_list(@story, @author, 4, 2) + c.should eq [@story_sheet5] + end + end + end + + describe '一覧取得に於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @story = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id, :visible => 1 + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @story_sheet = FactoryGirl.create :story_sheet, :author_id => @author.id, :story_id => @story.id, :sheet_id => @sheet.id + @other_comic = FactoryGirl.create :comic, :author_id => @other_author.id + @other_story = FactoryGirl.create :story, :comic_id => @other_comic.id, :author_id => @other_author.id, :visible => 1 + @other_sheet = FactoryGirl.create :sheet, :author_id => @other_author.id + @hidden_comic = FactoryGirl.create :comic, :author_id => @author.id + @hidden_story = FactoryGirl.create :story, :author_id => @author.id, :visible => 0 + end + context 'page補正について' do + it '文字列から数値に変換される' do + StorySheet.page('8').should eq 8 + end + it 'nilの場合は1になる' do + StorySheet.page().should eq 1 + end + it '0以下の場合は1になる' do + StorySheet.page('0').should eq 1 + end + end + context 'page_size補正について' do + it '文字列から数値に変換される' do + StorySheet.page_size('7').should eq 7 + end + it 'nilの場合はStorySheet.default_page_sizeになる' do + StorySheet.page_size().should eq StorySheet.default_page_size + end + it '0以下の場合はStorySheet.default_page_sizeになる' do + StorySheet.page_size('0').should eq StorySheet.default_page_size + end + it 'StorySheet.max_page_sizeを超えた場合はStorySheet.max_page_sizeになる' do + StorySheet.page_size('1000').should eq StorySheet.max_page_size + end + end + it 'リストを返す' do + c = StorySheet.list + c.should eq [@story_sheet] + end + it '時系列で並んでいる' do + #公開ストーリーのStorySheetは(他人のStorySheetであっても)含んでいる + v = FactoryGirl.create :story_sheet, :author_id => @other_author.id, :story_id => @other_story.id, :sheet_id => @other_sheet.id, :t => 0, :updated_at => Time.now + 100 + c = StorySheet.list + c.should eq [ v, @story_sheet] + end + it '非公開のスト紙は(自分のスト紙であっても)含まない' do + h = FactoryGirl.create :story_sheet, :author_id => @author.id, :story_id => @hidden_story.id, :sheet_id => @sheet.id, :t => 0 + c = StorySheet.list + c.should eq [ @story_sheet] + end + context 'DBに5件あって1ページの件数を2件に変えたとして' do + before do + @story_sheet2 = FactoryGirl.create :story_sheet, :author_id => @author.id, :story_id => @story.id, :sheet_id => @sheet.id, :t => 1, :updated_at => Time.now + 100 + @story_sheet3 = FactoryGirl.create :story_sheet, :author_id => @author.id, :story_id => @story.id, :sheet_id => @sheet.id, :t => 2, :updated_at => Time.now + 200 + @story_sheet4 = FactoryGirl.create :story_sheet, :author_id => @author.id, :story_id => @story.id, :sheet_id => @sheet.id, :t => 3, :updated_at => Time.now + 300 + @story_sheet5 = FactoryGirl.create :story_sheet, :author_id => @author.id, :story_id => @story.id, :sheet_id => @sheet.id, :t => 4, :updated_at => Time.now + 400 + end + it '通常は2件を返す' do + l = StorySheet.list 1, 2 + l.should have(2).items + end + it 'page=1なら末尾2件を返す' do + #時系列で並んでいる + l = StorySheet.list 1, 2 + l.should eq [@story_sheet5, @story_sheet4] + end + it 'page=2なら中間2件を返す' do + l = StorySheet.list 2, 2 + l.should eq [@story_sheet3, @story_sheet2] + end + it 'page=3なら先頭1件を返す' do + l = StorySheet.list 3, 2 + l.should eq [@story_sheet] + end + end + end + + describe '自分のスト紙一覧取得に於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @story = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id, :visible => 1 + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @story_sheet = FactoryGirl.create :story_sheet, :author_id => @author.id, :story_id => @story.id, :sheet_id => @sheet.id + @other_comic = FactoryGirl.create :comic, :author_id => @other_author.id + @other_story = FactoryGirl.create :story, :comic_id => @other_comic.id, :author_id => @other_author.id, :visible => 1 + @other_sheet = FactoryGirl.create :sheet, :author_id => @other_author.id, :visible => 1 + @hcomic = FactoryGirl.create :comic, :author_id => @author.id + @hstory = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id, :visible => 0 + @hsheet = FactoryGirl.create :sheet, :author_id => @author.id, :visible => 0 + end + context 'つつがなく終わるとき' do + it '一覧取得オプションを利用している' do + StorySheet.stub(:list_opt).with(any_args).and_return({}) + StorySheet.should_receive(:list_opt).with(any_args).exactly(1) + r = StorySheet.mylist @author + end + end + it 'リストを返す' do + s = StorySheet.mylist @author + s.should eq [@story_sheet] + end + it '時系列で並んでいる' do + ns = FactoryGirl.create :story_sheet, :author_id => @author.id, :story_id => @story.id, :sheet_id => @sheet.id, :t => 1, :updated_at => Time.now + 100 + sl = StorySheet.mylist @author + sl.should eq [ns, @story_sheet] + end + it '他人のスト紙は用紙ストーリーともに公開でも含まない' do + so = FactoryGirl.create :story_sheet, :author_id => @other_author.id, :story_id => @other_story.id, :sheet_id => @other_sheet.id + sl = StorySheet.mylist @author + sl.should eq [@story_sheet] + end + it '自分のスト紙は用紙ストーリーともに非公開でも含んでいる' do + hs = FactoryGirl.create :story_sheet, :author_id => @author.id, :story_id => @hstory.id, :sheet_id => @hsheet.id, :updated_at => Time.now + 100 + sl = StorySheet.mylist @author + sl.should eq [hs, @story_sheet] + end + context 'DBに5件あって1ページの件数を2件に変えたとして' do + before do + @story_sheet2 = FactoryGirl.create :story_sheet, :author_id => @author.id, :story_id => @story.id, :sheet_id => @sheet.id, :t => 1, :updated_at => Time.now + 100 + @story_sheet3 = FactoryGirl.create :story_sheet, :author_id => @author.id, :story_id => @story.id, :sheet_id => @sheet.id, :t => 2, :updated_at => Time.now + 200 + @story_sheet4 = FactoryGirl.create :story_sheet, :author_id => @author.id, :story_id => @story.id, :sheet_id => @sheet.id, :t => 3, :updated_at => Time.now + 300 + @story_sheet5 = FactoryGirl.create :story_sheet, :author_id => @author.id, :story_id => @story.id, :sheet_id => @sheet.id, :t => 4, :updated_at => Time.now + 400 + StorySheet.stub(:default_page_size).and_return(2) + end + it '通常は2件を返す' do + l = StorySheet.mylist @author, 1, 2 + l.should have(2).items + end + it 'page=1なら末尾2件を返す' do + #時系列で並んでいる + l = StorySheet.mylist @author, 1, 2 + l.should eq [@story_sheet5, @story_sheet4] + end + it 'page=2なら中間2件を返す' do + l = StorySheet.mylist @author, 2, 2 + l.should eq [@story_sheet3, @story_sheet2] + end + it 'page=3なら先頭1件を返す' do + l = StorySheet.mylist @author, 3, 2 + l.should eq [@story_sheet] + end + end + end + + describe '他作家のスト紙一覧取得に於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @story = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id, :visible => 1 + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @story_sheet = FactoryGirl.create :story_sheet, :author_id => @author.id, :story_id => @story.id, :sheet_id => @sheet.id + @other_comic = FactoryGirl.create :comic, :author_id => @other_author.id + @other_story = FactoryGirl.create :story, :comic_id => @other_comic.id, :author_id => @other_author.id, :visible => 1 + @other_sheet = FactoryGirl.create :sheet, :author_id => @other_author.id, :visible => 1 + @other_story_sheet = FactoryGirl.create :story_sheet, :author_id => @other_author.id, :story_id => @other_story.id, :sheet_id => @other_sheet.id + end + it 'リストを返す' do + r = StorySheet.himlist @other_author + r.should eq [@other_story_sheet] + end + it '時系列で並んでいる' do + ns = FactoryGirl.create :story_sheet, :author_id => @other_author.id, :story_id => @other_story.id, :sheet_id => @other_sheet.id, :t => 1, :updated_at => Time.now + 100 + r = StorySheet.himlist @other_author + r.should eq [ns, @other_story_sheet] + end + it '公開ストーリーのスト紙' do + @hstory = FactoryGirl.create :story, :author_id => @other_author.id, :visible => 0 + ns = FactoryGirl.create :story_sheet, :author_id => @other_author.id, :story_id => @hstory.id, :sheet_id => @other_sheet.id, :t => 1, :updated_at => Time.now + 100 + r = StorySheet.himlist @other_author + r.should eq [@other_story_sheet] + end + context 'DBに5件あって1ページの件数を2件に変えたとして' do + before do + @other_story_sheet2 = FactoryGirl.create :story_sheet, :author_id => @other_author.id, :story_id => @other_story.id, :sheet_id => @other_sheet.id, :t => 1, :updated_at => Time.now + 100 + @other_story_sheet3 = FactoryGirl.create :story_sheet, :author_id => @other_author.id, :story_id => @other_story.id, :sheet_id => @other_sheet.id, :t => 2, :updated_at => Time.now + 200 + @other_story_sheet4 = FactoryGirl.create :story_sheet, :author_id => @other_author.id, :story_id => @other_story.id, :sheet_id => @other_sheet.id, :t => 3, :updated_at => Time.now + 300 + @other_story_sheet5 = FactoryGirl.create :story_sheet, :author_id => @other_author.id, :story_id => @other_story.id, :sheet_id => @other_sheet.id, :t => 4, :updated_at => Time.now + 400 + StorySheet.stub(:default_page_size).and_return(2) + end + it '通常は2件を返す' do + l = StorySheet.himlist @other_author, 1, 2 + l.should have(2).items + end + it 'page=1なら末尾2件を返す' do + #時系列で並んでいる + l = StorySheet.himlist @other_author, 1, 2 + l.should eq [@other_story_sheet5, @other_story_sheet4] + end + it 'page=2なら中間2件を返す' do + l = StorySheet.himlist @other_author, 2, 2 + l.should eq [@other_story_sheet3, @other_story_sheet2] + end + it 'page=3なら先頭1件を返す' do + l = StorySheet.himlist @other_author, 3, 2 + l.should eq [@other_story_sheet] + end + end + end + + describe 'スト紙一覧ページ制御に於いて' do + before do + StorySheet.stub(:count).with(any_args).and_return(100) + end + it 'ページ制御を返す' do + r = StorySheet.list_paginate + r.is_a?(Kaminari::PaginatableArray).should be_true + end + it 'スト紙一覧の取得条件を利用している' do + StorySheet.stub(:list_where).with(any_args).and_return('') + StorySheet.should_receive(:list_where).with(any_args).exactly(1) + r = StorySheet.list_paginate + end + it 'ページ件数10のとき、3ページ目のオフセットは20から始まる' do + r = StorySheet.list_paginate 3, 10 + r.limit_value.should eq 10 + r.offset_value.should eq 20 + end + end + + describe '自分のスト紙一覧ページ制御に於いて' do + before do + StorySheet.stub(:count).with(any_args).and_return(100) + end + it 'ページ制御を返す' do + r = StorySheet.mylist_paginate @author + r.is_a?(Kaminari::PaginatableArray).should be_true + end + it '自分のスト紙一覧の取得条件を利用している' do + StorySheet.stub(:mylist_where).with(any_args).and_return('') + StorySheet.should_receive(:mylist_where).with(any_args).exactly(1) + r = StorySheet.mylist_paginate @author + end + it 'ページ件数10のとき、3ページ目のオフセットは20から始まる' do + r = StorySheet.mylist_paginate @author, 3, 10 + r.limit_value.should eq 10 + r.offset_value.should eq 20 + end + end + + describe '他作家のスト紙一覧ページ制御に於いて' do + before do + StorySheet.stub(:count).with(any_args).and_return(100) + end + it 'ページ制御を返す' do + r = StorySheet.himlist_paginate @other_author + r.is_a?(Kaminari::PaginatableArray).should be_true + end + it '他作家のスト紙一覧の取得条件を利用している' do + StorySheet.stub(:himlist_where).with(any_args).and_return('') + StorySheet.should_receive(:himlist_where).with(any_args).exactly(1) + r = StorySheet.himlist_paginate @other_author + end + it 'ページ件数10のとき、3ページ目のオフセットは20から始まる' do + r = StorySheet.himlist_paginate @other_author, 3, 10 + r.limit_value.should eq 10 + r.offset_value.should eq 20 + end + end + + describe 'list関連テーブルプションに於いて' do + it '3つの項目を含んでいる' do + r = StorySheet.list_opt + r.should have(3).items + end + it 'ストーリーを含んでいる' do + r = StorySheet.list_opt + r.has_key?(:story).should be_true + end + it 'ストーリーは作家を含んでいる' do + r = StorySheet.list_opt + r[:story].has_key?(:author).should be_true + end + it '作家を含んでいる' do + r = StorySheet.list_opt + r.has_key?(:author).should be_true + end + it '用紙を含んでいる' do + r = StorySheet.list_opt + r.has_key?(:sheet).should be_true + end + it '用紙は作家を含んでいる' do + r = StorySheet.list_opt + r[:sheet].has_key?(:author).should be_true + end + end + describe 'json一覧出力オプションに於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @story = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id, :visible => 1 + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @story_sheet = FactoryGirl.create :story_sheet, :author_id => @author.id, :story_id => @story.id, :sheet_id => @sheet.id + end + it 'ストーリーを含んでいる' do + r = StorySheet.list.to_json StorySheet.list_json_opt + j = JSON.parse r + i = j.first + i.has_key?('story').should be_true + end + it 'ストーリーは作家を含んでいる' do + r = StorySheet.list.to_json StorySheet.list_json_opt + j = JSON.parse r + i = j.first + s = i['story'] + s.has_key?('author').should be_true + end + it '用紙を含んでいる' do + r = StorySheet.list.to_json StorySheet.list_json_opt + j = JSON.parse r + i = j.first + i.has_key?('sheet').should be_true + end + it '用紙は作家を含んでいる' do + r = StorySheet.list.to_json StorySheet.list_json_opt + j = JSON.parse r + i = j.first + s = i['sheet'] + s.has_key?('author').should be_true + end + it '作家を含んでいる' do + r = StorySheet.list.to_json StorySheet.list_json_opt + j = JSON.parse r + i = j.first + i.has_key?('author').should be_true + end + end + + describe '単体取得に於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @story = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id, :visible => 1 + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @story_sheet = FactoryGirl.create :story_sheet, :author_id => @author.id, :story_id => @story.id, :sheet_id => @sheet.id + end + context 'つつがなく終わるとき' do + it '単体取得オプションを利用している' do + StorySheet.stub(:show_opt).with(any_args).and_return({}) + StorySheet.should_receive(:show_opt).with(any_args).exactly(1) + r = StorySheet.show @story_sheet.id, @author + end + it '閲覧許可を問い合わせている' do + StorySheet.any_instance.stub(:visible?).with(@author).and_return(true) + StorySheet.any_instance.should_receive(:visible?).with(@author).exactly(1) + r = StorySheet.show @story_sheet.id, @author + end + end + it '指定のスト紙を返す' do + l = StorySheet.show @story_sheet.id, @author + l.should eq @story_sheet + end + context '他人のスト紙を開こうとしたとき' do + it '403Forbidden例外を返す' do + StorySheet.any_instance.stub(:visible?).with(@other_author).and_return(false) + lambda{ + StorySheet.show @story_sheet.id, @other_author + }.should raise_error(ActiveRecord::Forbidden) + end + end + context '存在しないスト紙を開こうとしたとき' do + it '404RecordNotFound例外を返す' do + lambda{ + StorySheet.show 110, @author + }.should raise_error(ActiveRecord::RecordNotFound) + end + end + end + + describe '編集取得に於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @story = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id, :visible => 1 + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @story_sheet = FactoryGirl.create :story_sheet, :author_id => @author.id, :story_id => @story.id, :sheet_id => @sheet.id + end + context 'つつがなく終わるとき' do + it '単体取得オプションを利用している' do + StorySheet.stub(:show_opt).with(any_args).and_return({}) + StorySheet.should_receive(:show_opt).with(any_args).exactly(1) + r = StorySheet.edit @story_sheet.id, @author + end + it '所持判定を問い合わせている' do + StorySheet.any_instance.stub(:own?).with(any_args).and_return(true) + StorySheet.any_instance.should_receive(:own?).with(any_args).exactly(1) + r = StorySheet.edit @story_sheet.id, @author + end + end + it '指定のスト紙を返す' do + l = StorySheet.edit @story_sheet.id, @author + l.should eq @story_sheet + end + context '他人のスト紙を開こうとしたとき' do + it '403Forbidden例外を返す' do + StorySheet.any_instance.stub(:own?).and_return(false) + lambda{ + StorySheet.edit @story_sheet.id, @author + }.should raise_error(ActiveRecord::Forbidden) + end + end + context '存在しないスト紙を開こうとしたとき' do + it '404RecordNotFound例外を返す' do + lambda{ + StorySheet.edit 110, @author + }.should raise_error(ActiveRecord::RecordNotFound) + end + end + end + + describe '単体取得オプションに於いて' do + it 'includeキーを含んでいる' do + r = StorySheet.show_opt + r.has_key?(:include).should be_true + end + it '3つの項目を含んでいる' do + r = StorySheet.show_opt[:include] + r.should have(3).items + end + it 'ストーリーを含んでいる' do + r = StorySheet.show_opt[:include] + r.has_key?(:story).should be_true + end + it 'ストーリーは作家を含んでいる' do + r = StorySheet.show_opt[:include] + r[:story].has_key?(:author).should be_true + end + it '作家を含んでいる' do + r = StorySheet.show_opt[:include] + r.has_key?(:author).should be_true + end + it '用紙を含んでいる' do + r = StorySheet.show_opt[:include] + r.has_key?(:sheet).should be_true + end + it '用紙は作家を含んでいる' do + r = StorySheet.show_opt[:include] + r[:sheet].has_key?(:author).should be_true + end + end + describe 'json単体取得オプションに於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @story = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id, :visible => 1 + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @story_sheet = FactoryGirl.create :story_sheet, :author_id => @author.id, :story_id => @story.id, :sheet_id => @sheet.id + end + it 'ストーリーを含んでいる' do + r = StorySheet.show(@story_sheet.id, @author).to_json StorySheet.show_json_opt + j = JSON.parse r + i = j + i.has_key?('story').should be_true + end + it 'ストーリーは作家を含んでいる' do + r = StorySheet.show(@story_sheet.id, @author).to_json StorySheet.show_json_opt + j = JSON.parse r + i = j + s = i['story'] + s.has_key?('author').should be_true + end + it '用紙を含んでいる' do + r = StorySheet.show(@story_sheet.id, @author).to_json StorySheet.show_json_opt + j = JSON.parse r + i = j + i.has_key?('sheet').should be_true + end + it '用紙は作家を含んでいる' do + r = StorySheet.show(@story_sheet.id, @author).to_json StorySheet.show_json_opt + j = JSON.parse r + i = j + s = i['sheet'] + s.has_key?('author').should be_true + end + it '作家を含んでいる' do + r = StorySheet.show(@story_sheet.id, @author).to_json StorySheet.show_json_opt + j = JSON.parse r + i = j + i.has_key?('author').should be_true + end + end + + describe 't補充値に於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @story = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id, :visible => 1 + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + end + + context 'ストーリー初の用紙なら' do + it '0を補充値とする' do + @story_sheet = FactoryGirl.build :story_sheet, :author_id => @author.id, :story_id => @story.id, :sheet_id => @sheet.id + @story_sheet.t = nil + r = StorySheet.new_t @story_sheet.story_id + r.should eq 0 + end + end + context 'ストーリーに一個用紙があるとき' do + it '1を補充値とする' do + FactoryGirl.create :story_sheet, :author_id => @author.id, :story_id => @story.id, :sheet_id => @sheet.id, :t => 0 + @story_sheet = FactoryGirl.build :story_sheet, :author_id => @author.id, :story_id => @story.id, :sheet_id => @sheet.id + @story_sheet.t = nil + r = StorySheet.new_t @story_sheet.story_id + r.should eq 1 + end + end + context 'ストーリーに2個用紙があるとき' do + it '2を補充値とする' do + FactoryGirl.create :story_sheet, :author_id => @author.id, :story_id => @story.id, :sheet_id => @sheet.id, :t => 0 + FactoryGirl.create :story_sheet, :author_id => @author.id, :story_id => @story.id, :sheet_id => @sheet.id, :t => 1 + @story_sheet = FactoryGirl.build :story_sheet, :author_id => @author.id, :story_id => @story.id, :sheet_id => @sheet.id + @story_sheet.t = nil + r = StorySheet.new_t @story_sheet.story_id + r.should eq 2 + end + end + end + describe 'シリアライズチェックに於いて' do + context 'つつがなく終わるとき' do + it '0からシリアライズされているならTrueを返す' do + r = StorySheet.serial? [0, 1, 2] + r.should be_true + end + it '見た目はシリアライズされてなくてもソート結果が無事ならtrueを返す' do + r = StorySheet.serial? [0, 2, 1] + r.should be_true + end + it '見た目はシリアライズされてなくてもソート結果が無事ならtrueを返す' do + r = StorySheet.serial? [ 2, 1, 4, 3, 0] + r.should be_true + end + end + context '異常なとき' do + it '0から始まらないならFalseを返す' do + r = StorySheet.serial? [1, 2, 3] + r.should be_false + end + it '連続していないならFalseを返す' do + r = StorySheet.serial? [0, 1, 2, 4] + r.should be_false + end + it '連続していないならFalseを返す' do + r = StorySheet.serial? [0, 1, 2, 4, 5] + r.should be_false + end + end + end + describe 't収集に於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @story = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id, :visible => 1 + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @story_sheet = FactoryGirl.create :story_sheet, :author_id => @author.id, :story_id => @story.id, :sheet_id => @sheet.id + @story2 = FactoryGirl.create :story, :author_id => @author.id + @c2story_sheet = FactoryGirl.create :story_sheet, :t => 0, :story_id => @story2.id, :sheet_id => @sheet.id, :author_id => @author.id + end + context 'つつがなく終わるとき' do + it 'スト紙から同一ストーリーのtだけを収集している' do + r = StorySheet.collect_t @story_sheet + r.should eq [0] + end + end + context '複数用紙のとき' do + it 'スト紙から同一ストーリーのtだけを収集している' do + @story_sheet2 = FactoryGirl.create :story_sheet, :t => 1, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + r = StorySheet.collect_t @story_sheet + r.sort.should eq [0, 1] + end + end + context '複数用紙でヨソのストーリーも混じっているとき' do + it 'スト紙から同一ストーリーのtだけを収集している' do + @story_sheet2 = FactoryGirl.create :story_sheet, :t => 1, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + r = StorySheet.collect_t @story_sheet + r.sort.should eq [0, 1] + end + end + end + describe 'tチェックに於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @story = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id, :visible => 1 + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @story_sheet = FactoryGirl.build :story_sheet, :t => 1, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + end + context 'つつがなく終わるとき' do + it 't収集を依頼している' do + StorySheet.should_receive(:collect_t).with(any_args).exactly(1) + StorySheet.stub(:collect_t).with(any_args).and_return([]) + StorySheet.stub(:serial?).with(any_args).and_return(true) + r = StorySheet.validate_t @story_sheet + end + it '収集したtをシリアライズチェック依頼している' do + StorySheet.stub(:collect_t).with(any_args).and_return([]) + StorySheet.should_receive(:serial?).with(any_args).exactly(1) + StorySheet.stub(:serial?).with(any_args).and_return(true) + r = StorySheet.validate_t @story_sheet + end + end + #実データでチェック + #依頼チェックだけでは不安なので最低限のチェックを + context '新規のとき' do + it '一件だけで正常通過している' do + @story_sheet = FactoryGirl.build :story_sheet, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id, :t => 0 + r = StorySheet.validate_t @story_sheet + r.should be_true + end + end + context '既存のとき' do + it '2件目を作っても正常通過している' do + @story_sheet = FactoryGirl.create :story_sheet, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id, :t => 0 + @story_sheet2 = FactoryGirl.build :story_sheet, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id, :t => 1 + r = StorySheet.validate_t @story_sheet2 + r.should be_true + end + end + end + describe '挿入シフトに於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @story = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id, :visible => 1 + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + end + context '依頼チェック' do + #テーブルが空で0に挿入 + it 'Updateを依頼している' do + StorySheet.stub(:update_all).with(any_args) + StorySheet.should_receive(:update_all).with(any_args).exactly(1) + @story_sheet = FactoryGirl.build :story_sheet, :t => 0, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet.insert_shift + end + end + context 'テーブルに1件(t:0)で0に挿入したとき' do + before do + @story_sheet = FactoryGirl.create :story_sheet, :t => 0, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet2 = FactoryGirl.build :story_sheet, :t => 0, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + end + it '既存の行を1にシフトしている' do + @story_sheet2.insert_shift + l = StorySheet.find :all + l.first.t.should eq 1 + end + it 'これから挿入するt(0)が欠番になっている' do + @story_sheet2.insert_shift + l = StorySheet.find(:all).map {|s| s.t } + l.include?(0).should_not be_true + end + end + context 'テーブルに2件(t:0,1)で1に挿入したとき' do + before do + @story_sheet = FactoryGirl.create :story_sheet, :t => 0, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet2 = FactoryGirl.create :story_sheet, :t => 1, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet3 = FactoryGirl.build :story_sheet, :t => 1, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + end + it '既存のt1を2にシフトしてこれから挿入するt(1)が欠番になっている' do + @story_sheet3.insert_shift + l = StorySheet.find(:all).map {|s| s.t } + l.sort.should eq [0, 2] + end + end + context 'テーブルに5件(t:0,1,2,3,4)で2に挿入したとき' do + before do + @story_sheet = FactoryGirl.create :story_sheet, :t => 0, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet2 = FactoryGirl.create :story_sheet, :t => 1, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet3 = FactoryGirl.create :story_sheet, :t => 2, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet4 = FactoryGirl.create :story_sheet, :t => 3, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet5 = FactoryGirl.create :story_sheet, :t => 4, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet6 = FactoryGirl.build :story_sheet, :t => 2, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + end + it '既存のt1を2にシフトしてこれから挿入するt(1)が欠番になっている' do + @story_sheet6.insert_shift + l = StorySheet.find(:all).map {|s| s.t } + l.sort.should eq [0, 1, 3, 4, 5] + end + end + context '先ほどのケース+他のストーリー1件で挿入したとき' do + before do + @story2 = FactoryGirl.create :story, :author_id => @author.id + @story_sheetc2 = FactoryGirl.create :story_sheet, :t => 0, :story_id => @story2.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet = FactoryGirl.create :story_sheet, :t => 0, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet2 = FactoryGirl.create :story_sheet, :t => 1, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet3 = FactoryGirl.create :story_sheet, :t => 2, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet4 = FactoryGirl.create :story_sheet, :t => 3, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet5 = FactoryGirl.create :story_sheet, :t => 4, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet6 = FactoryGirl.build :story_sheet, :t => 2, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + end + it '既存のt1を2にシフトしてこれから挿入するt(1)が欠番になっている' do + @story_sheet6.insert_shift + l = StorySheet.find(:all, :conditions => ['story_id = ?', @story.id]).map {|s| s.t } + l.sort.should eq [0, 1, 3, 4, 5] + end + it '他のストーリーに影響がない' do + ot = @story_sheetc2.t + @story_sheet6.insert_shift + @story_sheetc2.reload + @story_sheetc2.t.should eq ot + end + end + end + describe '少ない方に移動に於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @story = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id, :visible => 1 + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + end + context '依頼チェック' do + it 'Updateを依頼している' do + @story_sheet = FactoryGirl.create :story_sheet, :t => 0, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet2 = FactoryGirl.create :story_sheet, :t => 1, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + StorySheet.stub(:update_all).with(any_args) + StorySheet.should_receive(:update_all).with(any_args).exactly(1) + ot = @story_sheet2.t + @story_sheet2.t = 0 + @story_sheet2.lesser_shift ot + end + end + context 'テーブルに2件(t:0,1)で1を0に移動したとき' do + before do + @story_sheet = FactoryGirl.create :story_sheet, :t => 0, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet2 = FactoryGirl.create :story_sheet, :t => 1, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @ot = @story_sheet2.t + @story_sheet2.t = 0 + end + it '既存のt0を1にシフトしてこれから挿入するt(0)が欠番になっている' do + #移動させたい行はそのまま残る + @story_sheet2.lesser_shift @ot + l = StorySheet.find(:all).map {|s| s.t } + l.sort.should eq [1, 1] + end + it '既存のt0を1にシフトしている' do + @story_sheet2.lesser_shift @ot + @story_sheet.reload + @story_sheet.t.should eq 1 + end + end + context 'テーブルに3件(t:0,1,2)で2を1に移動したとき' do + before do + @story_sheet = FactoryGirl.create :story_sheet, :t => 0, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet2 = FactoryGirl.create :story_sheet, :t => 1, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet3 = FactoryGirl.create :story_sheet, :t => 2, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @ot = @story_sheet3.t + @story_sheet3.t = 1 + end + it '既存のt1を2にシフトしてこれから挿入するt(1)が欠番になっている' do + #移動させたい行はそのまま残る + @story_sheet3.lesser_shift @ot + l = StorySheet.find(:all).map {|s| s.t } + l.sort.should eq [0, 2, 2] + end + it '既存のt1を2にシフトしている' do + @story_sheet3.lesser_shift @ot + @story_sheet2.reload + @story_sheet2.t.should eq 2 + end + end + context 'テーブルに5件(t:0,1,2,3,4)で3を1に移動したとき' do + before do + @story_sheet = FactoryGirl.create :story_sheet, :t => 0, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet2 = FactoryGirl.create :story_sheet, :t => 1, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet3 = FactoryGirl.create :story_sheet, :t => 2, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet4 = FactoryGirl.create :story_sheet, :t => 3, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet5 = FactoryGirl.create :story_sheet, :t => 4, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @ot = @story_sheet4.t + @story_sheet4.t = 1 + end + it 'これから挿入するt(1)が欠番になっている' do + #移動させたい行はそのまま残る + @story_sheet4.lesser_shift @ot + l = StorySheet.find(:all).map {|s| s.t } + l.sort.should eq [0, 2, 3, 3, 4] + end + it '既存のt0には変化がない' do + @story_sheet4.lesser_shift @ot + @story_sheet.reload + @story_sheet.t.should eq 0 + end + it '既存のt4には変化がない' do + @story_sheet4.lesser_shift @ot + @story_sheet5.reload + @story_sheet5.t.should eq 4 + end + it '既存のt1を2にシフトしている' do + @story_sheet4.lesser_shift @ot + @story_sheet2.reload + @story_sheet2.t.should eq 2 + end + it '既存のt2を3にシフトしている' do + @story_sheet4.lesser_shift @ot + @story_sheet3.reload + @story_sheet3.t.should eq 3 + end + end + context '先ほどのケース+他のストーリー1件で挿入したとき' do + before do + @story2 = FactoryGirl.create :story, :author_id => @author.id + @story_sheetc2 = FactoryGirl.create :story_sheet, :t => 0, :story_id => @story2.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet = FactoryGirl.create :story_sheet, :t => 0, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet2 = FactoryGirl.create :story_sheet, :t => 1, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet3 = FactoryGirl.create :story_sheet, :t => 2, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet4 = FactoryGirl.create :story_sheet, :t => 3, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet5 = FactoryGirl.create :story_sheet, :t => 4, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @ot = @story_sheet4.t + @story_sheet4.t = 1 + end + it 'これから挿入するt(1)が欠番になっている' do + @story_sheet4.lesser_shift @ot + l = StorySheet.find(:all).map {|s| s.t } + l.sort.should eq [0, 0, 2, 3, 3, 4] + end + it '既存のt0には変化がない' do + @story_sheet4.lesser_shift @ot + @story_sheet.reload + @story_sheet.t.should eq 0 + end + it '既存のt4には変化がない' do + @story_sheet4.lesser_shift @ot + @story_sheet5.reload + @story_sheet5.t.should eq 4 + end + it '既存のt1を2にシフトしている' do + @story_sheet4.lesser_shift @ot + @story_sheet2.reload + @story_sheet2.t.should eq 2 + end + it '既存のt2を3にシフトしている' do + @story_sheet4.lesser_shift @ot + @story_sheet3.reload + @story_sheet3.t.should eq 3 + end + it '他のストーリーに影響がない' do + @story_sheet4.lesser_shift @ot + @story_sheetc2.reload + @story_sheetc2.t.should eq 0 + end + end + #例外ケース。 + #負のときは0として正常扱い + context 'テーブルに2件(t:0,1)で1を-1に移動したとき' do + before do + @story_sheet = FactoryGirl.create :story_sheet, :t => 0, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet2 = FactoryGirl.create :story_sheet, :t => 1, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @ot = @story_sheet2.t + @story_sheet2.t = -1 + end + it '既存のt0を1にシフトしてこれから挿入するt(0)が欠番になっている' do + #移動させたい行はそのまま残る + @story_sheet2.lesser_shift @ot + l = StorySheet.find(:all).map {|s| s.t } + l.sort.should eq [1, 1] + end + it '既存のt0を1にシフトしている' do + @story_sheet2.lesser_shift @ot + @story_sheet.reload + @story_sheet.t.should eq 1 + end + it '既存のt1は0に補正されている' do + @story_sheet2.lesser_shift @ot + @story_sheet2.t.should eq 0 + end + end + end + describe '大きい方に移動に於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @story = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id, :visible => 1 + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + end + context '依頼チェック' do + it 'Updateを依頼している' do + @story_sheet = FactoryGirl.create :story_sheet, :t => 0, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet2 = FactoryGirl.create :story_sheet, :t => 1, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + StorySheet.stub(:update_all).with(any_args) + StorySheet.should_receive(:update_all).with(any_args).exactly(1) + ot = @story_sheet.t + @story_sheet.t = 1 + @story_sheet.higher_shift ot + end + end + context 'テーブルに2件(t:0,1)で0を1に移動したとき' do + before do + @story_sheet = FactoryGirl.create :story_sheet, :t => 0, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet2 = FactoryGirl.create :story_sheet, :t => 1, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @ot = @story_sheet.t + @story_sheet.t = 1 + end + it '既存のt1を0にシフトしてこれから挿入するt(1)が欠番になっている' do + #移動させたい行はそのまま残る + @story_sheet.higher_shift @ot + l = StorySheet.find(:all).map {|s| s.t } + l.sort.should eq [0, 0] + end + it '既存のt1を0にシフトしている' do + @story_sheet.higher_shift @ot + @story_sheet2.reload + @story_sheet2.t.should eq 0 + end + end + context 'テーブルに3件(t:0,1,2)で0を1に移動したとき' do + before do + @story_sheet = FactoryGirl.create :story_sheet, :t => 0, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet2 = FactoryGirl.create :story_sheet, :t => 1, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet3 = FactoryGirl.create :story_sheet, :t => 2, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @ot = @story_sheet.t + @story_sheet.t = 1 + end + it '既存のt1を0にシフトしてこれから挿入するt(1)が欠番になっている' do + #移動させたい行はそのまま残る + @story_sheet.higher_shift @ot + l = StorySheet.find(:all).map {|s| s.t } + l.sort.should eq [0, 0, 2] + end + it '既存のt1を0にシフトしている' do + @story_sheet.higher_shift @ot + @story_sheet2.reload + @story_sheet2.t.should eq 0 + end + end + context 'テーブルに5件(t:0,1,2,3,4)で1を3に移動したとき' do + before do + @story_sheet = FactoryGirl.create :story_sheet, :t => 0, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet2 = FactoryGirl.create :story_sheet, :t => 1, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet3 = FactoryGirl.create :story_sheet, :t => 2, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet4 = FactoryGirl.create :story_sheet, :t => 3, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet5 = FactoryGirl.create :story_sheet, :t => 4, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @ot = @story_sheet2.t + @story_sheet2.t = 3 + end + it 'これから挿入するt(3)が欠番になっている' do + #移動させたい行はそのまま残る + @story_sheet2.higher_shift @ot + l = StorySheet.find(:all).map {|s| s.t } + l.sort.should eq [0, 1, 1, 2, 4] + end + it '既存のt0には変化がない' do + @story_sheet2.higher_shift @ot + @story_sheet.reload + @story_sheet.t.should eq 0 + end + it '既存のt4には変化がない' do + @story_sheet2.higher_shift @ot + @story_sheet5.reload + @story_sheet5.t.should eq 4 + end + it '既存のt2を1にシフトしている' do + @story_sheet2.higher_shift @ot + @story_sheet3.reload + @story_sheet3.t.should eq 1 + end + it '既存のt3を2にシフトしている' do + @story_sheet2.higher_shift @ot + @story_sheet4.reload + @story_sheet4.t.should eq 2 + end + end + context '先ほどのケース+他のストーリー1件で挿入したとき' do + before do + @story2 = FactoryGirl.create :story, :author_id => @author.id + @story_sheetc2 = FactoryGirl.create :story_sheet, :t => 0, :story_id => @story2.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet = FactoryGirl.create :story_sheet, :t => 0, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet2 = FactoryGirl.create :story_sheet, :t => 1, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet3 = FactoryGirl.create :story_sheet, :t => 2, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet4 = FactoryGirl.create :story_sheet, :t => 3, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet5 = FactoryGirl.create :story_sheet, :t => 4, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @ot = @story_sheet2.t + @story_sheet2.t = 3 + end + it 'これから挿入するt(3)が欠番になっている' do + #移動させたい行はそのまま残る + @story_sheet2.higher_shift @ot + l = StorySheet.find(:all).map {|s| s.t } + l.sort.should eq [0, 0, 1, 1, 2, 4] + end + it '既存のt0には変化がない' do + @story_sheet2.higher_shift @ot + @story_sheet.reload + @story_sheet.t.should eq 0 + end + it '既存のt4には変化がない' do + @story_sheet2.higher_shift @ot + @story_sheet5.reload + @story_sheet5.t.should eq 4 + end + it '既存のt2を1にシフトしている' do + @story_sheet2.higher_shift @ot + @story_sheet3.reload + @story_sheet3.t.should eq 1 + end + it '既存のt3を2にシフトしている' do + @story_sheet2.higher_shift @ot + @story_sheet4.reload + @story_sheet4.t.should eq 2 + end + it '他のストーリーに影響がない' do + @story_sheet2.higher_shift @ot + @story_sheetc2.reload + @story_sheetc2.t.should eq 0 + end + end + #例外ケース。 + #max超えたときはmaxとして正常扱い + context 'テーブルに2件(t:0,1)で0を2に移動したとき' do + before do + @story_sheet = FactoryGirl.create :story_sheet, :t => 0, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet2 = FactoryGirl.create :story_sheet, :t => 1, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @ot = @story_sheet.t + @story_sheet.t = 2 + end + it '既存のt1を0にシフトしてこれから挿入するt(1)が欠番になっている' do + #移動させたい行はそのまま残る + @story_sheet.higher_shift @ot + l = StorySheet.find(:all).map {|s| s.t } + l.sort.should eq [0, 0] + end + it '既存のt1を0にシフトしている' do + @story_sheet.higher_shift @ot + @story_sheet2.reload + @story_sheet2.t.should eq 0 + end + it '既存のt0は1に補正されている' do + @story_sheet.higher_shift @ot + @story_sheet.t.should eq 1 + end + end + end + describe '入れ替えに於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @story = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id, :visible => 1 + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @story_sheet = FactoryGirl.create :story_sheet, :t => 0, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet2 = FactoryGirl.create :story_sheet, :t => 1, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + end + context '新tが旧tより小さいとき' do + it '少ない方に移動を依頼している' do + StorySheet.any_instance.stub(:lesser_shift).with(any_args) + StorySheet.any_instance.should_receive(:lesser_shift).with(any_args).exactly(1) + ot = @story_sheet2.t + @story_sheet2.t = 0 + @story_sheet2.update_shift ot + end + end + context '新tが旧tより大きいとき' do + it '大きい方に移動を依頼している' do + StorySheet.any_instance.stub(:higher_shift).with(any_args) + StorySheet.any_instance.should_receive(:higher_shift).with(any_args).exactly(1) + ot = @story_sheet.t + @story_sheet.t = 1 + @story_sheet.update_shift ot + end + end + end + describe '順序入れ替えに於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @story = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id, :visible => 1 + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + end + context 'オブジェクトが新規でtが空のとき' do + it '末尾追加としてtを補充依頼している' do + @story_sheet = FactoryGirl.build :story_sheet, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + StorySheet.stub(:new_t).with(any_args).and_return(0) + StorySheet.should_receive(:new_t).with(any_args).exactly(1) + @story_sheet.t = nil + r = @story_sheet.rotate + end + end + context 'オブジェクトが新規でtが設定されているとき' do + it '挿入追加として挿入シフトを依頼している' do + @story_sheet = FactoryGirl.build :story_sheet, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + StorySheet.any_instance.stub(:insert_shift).with(any_args) + StorySheet.any_instance.should_receive(:insert_shift).with(any_args).exactly(1) + @story_sheet.t = 0 + r = @story_sheet.rotate + end + end + context 'オブジェクトが新規でなくtが設定されているとき' do + it '用紙移動として入れ替えを依頼している' do + @story_sheet = FactoryGirl.create :story_sheet, :t => 0, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet2 = FactoryGirl.create :story_sheet, :t => 1, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + StorySheet.any_instance.stub(:update_shift).with(any_args) + StorySheet.any_instance.should_receive(:update_shift).with(1).exactly(1) + @story_sheet2.t = 0 + r = @story_sheet.rotate 1 + end + end + context 'オブジェクトが新規でなくtが空のとき' do + it '入れ替えもシフトもせず、tを空のままにしている' do + #結果、tに欠番が生じてシリアライズチェックでひっかかる + end + end + end + describe '編集許可に於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @story = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id, :visible => 1 + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @story_sheet = FactoryGirl.build :story_sheet, :t => nil, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + end + context 'つつがなく終わるとき' do + it 'trueを返す' do + r = @story_sheet.allow? + r.should be_true + end + end + context 'ストーリーで引っかかるとき' do + it 'falseを返す' do + Sheet.any_instance.stub(:usable?).with(any_args).and_return(true) + Story.any_instance.stub(:own?).with(any_args).and_return(false) + r = @story_sheet.allow? + r.should be_false + end + end + context '用紙で引っかかるとき' do + it 'falseを返す' do + Story.any_instance.stub(:own?).with(any_args).and_return(true) + Sheet.any_instance.stub(:usable?).with(any_args).and_return(false) + r = @story_sheet.allow? + r.should be_false + end + end + context 'ストーリーまたは用紙が指定されていなかったとき' do + it 'nilを返す' do + Story.any_instance.stub(:own?).with(any_args).and_return(true) + @story_sheet.sheet_id = nil + r = @story_sheet.allow? + r.should eq nil + end + it 'nilを返す' do + Sheet.any_instance.stub(:usable?).with(any_args).and_return(true) + @story_sheet.story_id = nil + r = @story_sheet.allow? + r.should eq nil + end + end + end + describe '保存に於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @story = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id, :visible => 1 + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @story_sheet = FactoryGirl.build :story_sheet, :t => nil, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + end + context 'つつがなく終わるとき' do + it '編集許可チェックを依頼している' do + StorySheet.any_instance.stub(:allow?).with(any_args).and_return(true) + StorySheet.any_instance.should_receive(:allow?).with(any_args).exactly(1) + r = @story_sheet.store + end + it '順序入れ替えを依頼している' do + StorySheet.any_instance.stub(:rotate).with(any_args).and_return(0) + StorySheet.any_instance.should_receive(:rotate).with(any_args).exactly(1) + StorySheet.any_instance.stub(:save).with(any_args).and_return(true) + StorySheet.stub(:validate_t).with(any_args).and_return(true) + r = @story_sheet.store + end + it '保存を依頼している' do + StorySheet.stub(:new_t).with(any_args).and_return(0) + StorySheet.any_instance.stub(:save).with(any_args).and_return(true) + StorySheet.any_instance.should_receive(:save).with(any_args).exactly(1) + StorySheet.stub(:validate_t).with(any_args).and_return(true) + r = @story_sheet.store + end + it 'tのシリアライズチェックを依頼している' do + StorySheet.stub(:new_t).with(any_args).and_return(0) + StorySheet.any_instance.stub(:save).with(any_args).and_return(true) + StorySheet.stub(:validate_t).with(any_args).and_return(true) + StorySheet.should_receive(:validate_t).with(any_args).exactly(1) + r = @story_sheet.store + end + end + #入れ替えテストと同じテストを実施。こちらはシフトだけでなく本尊も更新されている + context 'テーブルに5件(t:0,1,2,3,4)+他のストーリー1件で2に挿入したとき' do + before do + @story2 = FactoryGirl.create :story, :author_id => @author.id + @story_sheetc2 = FactoryGirl.create :story_sheet, :t => 0, :story_id => @story2.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet = FactoryGirl.create :story_sheet, :t => 0, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet2 = FactoryGirl.create :story_sheet, :t => 1, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet3 = FactoryGirl.create :story_sheet, :t => 2, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet4 = FactoryGirl.create :story_sheet, :t => 3, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet5 = FactoryGirl.create :story_sheet, :t => 4, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet6 = FactoryGirl.build :story_sheet, :t => 2, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + end + it '既存のt0には変化がない' do + @story_sheet6.store + @story_sheet.reload + @story_sheet.t.should eq 0 + end + it '既存のt1には変化がない' do + @story_sheet6.store + @story_sheet2.reload + @story_sheet2.t.should eq 1 + end + it '既存のt2を3にシフトしている' do + @story_sheet6.store + @story_sheet3.reload + @story_sheet3.t.should eq 3 + end + it '既存のt3を4にシフトしている' do + @story_sheet6.store + @story_sheet4.reload + @story_sheet4.t.should eq 4 + end + it '既存のt5を5にシフトしている' do + @story_sheet6.store + @story_sheet5.reload + @story_sheet5.t.should eq 5 + end + it '新規のt2が作成されている' do + @story_sheet6.store + @story_sheet6.reload + @story_sheet6.t.should eq 2 + end + it '他のストーリーに影響がない' do + @ot = @story_sheetc2.t + @story_sheet6.store + @story_sheetc2.reload + @story_sheetc2.t.should eq @ot + end + end + context 'テーブルに5件(t:0,1,2,3,4)+他のストーリー1件で3を1に移動したとき' do + before do + @story2 = FactoryGirl.create :story, :author_id => @author.id + @story_sheetc2 = FactoryGirl.create :story_sheet, :t => 0, :story_id => @story2.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet = FactoryGirl.create :story_sheet, :t => 0, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet2 = FactoryGirl.create :story_sheet, :t => 1, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet3 = FactoryGirl.create :story_sheet, :t => 2, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet4 = FactoryGirl.create :story_sheet, :t => 3, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet5 = FactoryGirl.create :story_sheet, :t => 4, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @ot = @story_sheet4.t + @story_sheet4.t = 1 + end + it '既存のt0には変化がない' do + @story_sheet4.store @ot + @story_sheet.reload + @story_sheet.t.should eq 0 + end + it '既存のt4には変化がない' do + @story_sheet4.store @ot + @story_sheet5.reload + @story_sheet5.t.should eq 4 + end + it '既存のt1を2にシフトしている' do + @story_sheet4.store @ot + @story_sheet2.reload + @story_sheet2.t.should eq 2 + end + it '既存のt2を3にシフトしている' do + @story_sheet4.store @ot + @story_sheet3.reload + @story_sheet3.t.should eq 3 + end + it '既存のt3を1にシフトしている' do + @story_sheet4.store @ot + @story_sheet4.reload + @story_sheet4.t.should eq 1 + end + it '他のストーリーに影響がない' do + @story_sheet4.store @ot + @story_sheetc2.reload + @story_sheetc2.t.should eq 0 + end + end + context 'テーブルに5件(t:0,1,2,3,4)+他のストーリー1件で1を3に移動したとき' do + before do + @story2 = FactoryGirl.create :story, :author_id => @author.id + @story_sheetc2 = FactoryGirl.create :story_sheet, :t => 0, :story_id => @story2.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet = FactoryGirl.create :story_sheet, :t => 0, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet2 = FactoryGirl.create :story_sheet, :t => 1, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet3 = FactoryGirl.create :story_sheet, :t => 2, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet4 = FactoryGirl.create :story_sheet, :t => 3, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet5 = FactoryGirl.create :story_sheet, :t => 4, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @ot = @story_sheet2.t + @story_sheet2.t = 3 + end + it '既存のt0には変化がない' do + @story_sheet2.store @ot + @story_sheet.reload + @story_sheet.t.should eq 0 + end + it '既存のt4には変化がない' do + @story_sheet2.store @ot + @story_sheet5.reload + @story_sheet5.t.should eq 4 + end + it '既存のt1を3にシフトしている' do + @story_sheet2.store @ot + @story_sheet2.reload + @story_sheet2.t.should eq 3 + end + it '既存のt2を1にシフトしている' do + @story_sheet2.store @ot + @story_sheet3.reload + @story_sheet3.t.should eq 1 + end + it '既存のt3を2にシフトしている' do + @story_sheet2.store @ot + @story_sheet4.reload + @story_sheet4.t.should eq 2 + end + it '他のストーリーに影響がない' do + @story_sheet2.store @ot + @story_sheetc2.reload + @story_sheetc2.t.should eq 0 + end + end + #ロールバックテスト。入れ替えが直接DBをいじるので、すべてのケースで確実にロールバックを確認する + context 'テーブルに5件(t:0,1,2,3,4)+他のストーリー1件で2に挿入したが保存に失敗したとき' do + before do + StorySheet.any_instance.stub(:save).with(any_args).and_return(false) + @story2 = FactoryGirl.create :story, :author_id => @author.id + @story_sheetc2 = FactoryGirl.create :story_sheet, :t => 0, :story_id => @story2.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet = FactoryGirl.create :story_sheet, :t => 0, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet2 = FactoryGirl.create :story_sheet, :t => 1, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet3 = FactoryGirl.create :story_sheet, :t => 2, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet4 = FactoryGirl.create :story_sheet, :t => 3, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet5 = FactoryGirl.create :story_sheet, :t => 4, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet6 = FactoryGirl.build :story_sheet, :t => 2, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + end + it '既存のtに変化がない' do + @story_sheet6.store + @story_sheet.reload + @story_sheet.t.should eq 0 + @story_sheet2.reload + @story_sheet2.t.should eq 1 + @story_sheet3.reload + @story_sheet3.t.should eq 2 + @story_sheet4.reload + @story_sheet4.t.should eq 3 + @story_sheet5.reload + @story_sheet5.t.should eq 4 + @story_sheetc2.reload + @story_sheetc2.t.should eq 0 + end + it 'falseを返す' do + r = @story_sheet6.store + r.should be_false + end + end + context 'テーブルに5件(t:0,1,2,3,4)+他のストーリー1件で3を1に移動したがシリアルチェックに失敗したとき' do + before do + StorySheet.stub(:validate_t).with(any_args).and_return(false) + @story2 = FactoryGirl.create :story, :author_id => @author.id + @story_sheetc2 = FactoryGirl.create :story_sheet, :t => 0, :story_id => @story2.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet = FactoryGirl.create :story_sheet, :t => 0, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet2 = FactoryGirl.create :story_sheet, :t => 1, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet3 = FactoryGirl.create :story_sheet, :t => 2, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet4 = FactoryGirl.create :story_sheet, :t => 3, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet5 = FactoryGirl.create :story_sheet, :t => 4, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @ot = @story_sheet4.t + @story_sheet4.t = 1 + end + it '既存のtに変化がない' do + @story_sheet4.store @ot + @story_sheet.reload + @story_sheet.t.should eq 0 + @story_sheet2.reload + @story_sheet2.t.should eq 1 + @story_sheet3.reload + @story_sheet3.t.should eq 2 + @story_sheet4.reload + @story_sheet4.t.should eq 3 + @story_sheet5.reload + @story_sheet5.t.should eq 4 + @story_sheetc2.reload + @story_sheetc2.t.should eq 0 + end + it 'falseを返す' do + r = @story_sheet4.store @ot + r.should be_false + end + it 'tにエラーメッセージが入っている' do + @story_sheet4.store @ot + @story_sheet4.errors[:t].should_not be_empty + @story_sheet4.valid?.should be_true + end + end + context '編集不可だったとき' do + before do + @story_sheet = FactoryGirl.build :story_sheet, :t => 0, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + StorySheet.any_instance.stub(:allow?).and_return(false) + end + it '403Forbidden例外を返す' do + lambda{ + @story_sheet.store + }.should raise_error(ActiveRecord::Forbidden) + end + end + end + describe '切り詰め処理つき削除に於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @story = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id, :visible => 1 + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @story_sheet = FactoryGirl.create :story_sheet, :t => 0, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + end + context 'つつがなく終わるとき' do + it '削除される' do + lambda{ + @story_sheet.destroy_and_shorten + }.should change(StorySheet, :count ).by(-1) + end + it 'Trueを返す' do + r = @story_sheet.destroy_and_shorten + r.should be_true + end + end + context '削除に失敗したとき' do + before do + StorySheet.any_instance.stub(:destroy).and_return(false) + end + it 'ロールバックされる' do + lambda{ + @story_sheet.destroy_and_shorten + }.should_not change(StorySheet, :count ) + end + it 'Falseを返す' do + r = @story_sheet.destroy_and_shorten + r.should be_false + end + end + #連携テスト。切り詰めが直接DBをいじる + context '2件で先頭を削除したとき' do + before do + @story_sheet2 = FactoryGirl.create :story_sheet, :t => 1, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + end + it '行が削除される' do + lambda{ + @story_sheet.destroy_and_shorten + }.should change(StorySheet, :count ).by(-1) + end + it '先頭は削除される' do + @story_sheet.destroy_and_shorten + lambda{ + StorySheet.find @story_sheet.id + }.should raise_error(ActiveRecord::RecordNotFound) + end + it '2件目は前に詰められる' do + @story_sheet.destroy_and_shorten + @story_sheet2.reload + @story_sheet2.t.should eq 0 + end + end + context '3件で先頭を削除したとき' do + before do + @story_sheet2 = FactoryGirl.create :story_sheet, :t => 1, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet3 = FactoryGirl.create :story_sheet, :t => 2, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + end + it '行が削除される' do + lambda{ + @story_sheet.destroy_and_shorten + }.should change(StorySheet, :count ).by(-1) + end + it '先頭は削除される' do + @story_sheet.destroy_and_shorten + lambda{ + StorySheet.find @story_sheet.id + }.should raise_error(ActiveRecord::RecordNotFound) + end + it '2件目は前に詰められる' do + @story_sheet.destroy_and_shorten + @story_sheet2.reload + @story_sheet2.t.should eq 0 + end + it '3件目は前に詰められる' do + @story_sheet.destroy_and_shorten + @story_sheet3.reload + @story_sheet3.t.should eq 1 + end + end + context '5件で3件目を削除したとき' do + before do + @story_sheet2 = FactoryGirl.create :story_sheet, :t => 1, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet3 = FactoryGirl.create :story_sheet, :t => 2, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet4 = FactoryGirl.create :story_sheet, :t => 3, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + @story_sheet5 = FactoryGirl.create :story_sheet, :t => 4, :story_id => @story.id, :sheet_id => @sheet.id, :author_id => @author.id + end + it '行が削除される' do + lambda{ + @story_sheet3.destroy_and_shorten + }.should change(StorySheet, :count ).by(-1) + end + it '1件目は変化がない' do + @story_sheet3.destroy_and_shorten + @story_sheet.reload + @story_sheet.t.should eq 0 + end + it '2件目は変化がない' do + @story_sheet3.destroy_and_shorten + @story_sheet2.reload + @story_sheet2.t.should eq 1 + end + it '3件目は削除される' do + @story_sheet3.destroy_and_shorten + lambda{ + StorySheet.find @story_sheet3.id + }.should raise_error(ActiveRecord::RecordNotFound) + end + it '4件目は前に詰められる' do + @story_sheet3.destroy_and_shorten + @story_sheet4.reload + @story_sheet4.t.should eq 2 + end + it '5件目は前に詰められる' do + @story_sheet3.destroy_and_shorten + @story_sheet5.reload + @story_sheet5.t.should eq 3 + end + end + #ロールバックテスト。切り詰めが直接DBをいじるので、すべてのケースで確実にロールバックを確認する + end +end diff --git a/spec/models/story_spec.rb b/spec/models/story_spec.rb new file mode 100644 index 00000000..de0452b8 --- /dev/null +++ b/spec/models/story_spec.rb @@ -0,0 +1,1719 @@ +# -*- encoding: utf-8 -*- +require 'spec_helper' +#ストーリー + +describe Story do + before do + @admin = FactoryGirl.create :admin + @demand_user = FactoryGirl.create :demand_user + @sp = FactoryGirl.create :system_picture + @lg = FactoryGirl.create :license_group + @license = FactoryGirl.create :license, :license_group_id => @lg.id, :system_picture_id => @sp.id + @user = FactoryGirl.create( :user_yas) + @author = FactoryGirl.create :author, :user_id => @user.id + @artist = FactoryGirl.create :artist_yas, :author_id => @author.id + @other_user = FactoryGirl.create( :user_yas) + @other_author = FactoryGirl.create :author, :user_id => @other_user.id + @other_artist = FactoryGirl.create :artist_yas, :author_id => @other_author.id + end + + describe '検証に於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @story = FactoryGirl.build :story, :comic_id => @comic.id, :author_id => @author.id + end + + context 'オーソドックスなデータのとき' do + it '下限データが通る' do + @story.title = 'a' + @story.visible = 0 + @story.t = 0 + @story.should be_valid + end + it '上限データが通る' do + @story.title = 'a'*100 + @story.visible = 1 + @story.t = 99999 + @story.should be_valid + end + end + + context 'titleを検証するとき' do + it 'nullなら失敗する' do + @story.title = nil + @story.should_not be_valid + end + it '100文字以上なら失敗する' do + @story.title = 'a'*101 + @story.should_not be_valid + end + end + context 'visibleを検証するとき' do + it 'nullなら失敗する' do + @story.visible = nil + @story.should_not be_valid + end + it '負なら失敗する' do + @story.visible = -1 + @story.should_not be_valid + end + it '2以上なら失敗する' do + @story.visible = 2 + @story.should_not be_valid + end + end + context 'tを検証するとき' do + it 'nullなら失敗する' do + @story.t = nil + @story.should_not be_valid + end + it '数値でなければ失敗する' do + @story.t = 'a' + @story.should_not be_valid + end + it '負なら失敗する' do + @story.t = -1 + @story.should_not be_valid + end + end + end + + describe '文字コード検証に於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @story = FactoryGirl.build :story, :comic_id => @comic.id, :author_id => @author.id + end + + context 'titleを検証するとき' do + it 'Shift JISなら失敗する' do + @story.title = "\x83G\x83r\x83]\x83D" + lambda{ + @story.valid_encode + }.should raise_error(Pettanr::BadRequest) + end + end + + context 'descriptionを検証するとき' do + it 'Shift JISなら失敗する' do + @story.description = "\x83G\x83r\x83]\x83D" + lambda{ + @story.valid_encode + }.should raise_error(Pettanr::BadRequest) + end + end + end + + describe 'デフォルト値補充に於いて' do + it 'visibleが0になっている' do + @story = FactoryGirl.build :story, :visible => nil + @story.supply_default + @story.visible.should eq 0 + end + end + + describe '上書き補充に於いて' do + it '作家idが設定されている' do + @story = FactoryGirl.build :story, :author_id => nil + @story.overwrite @author + @story.author_id.should eq @author.id + end + end + + describe '所持判定に於いて' do + before do + @story = FactoryGirl.build :story, :author_id => @author.id + end + context '事前チェックする' do + it '自身にロールリストからの作家取得を依頼している' do + Story.should_receive(:get_author_from_roles).with(any_args).exactly(1) + r = @story.own?([@author]) + end + end + context 'ロール内作家が取得できるとき' do + before do + end + it 'ロール内作家のidが自身の作家idと一致するなら許可する' do + Story.stub(:get_author_from_roles).with(any_args).and_return(@author) + r = @story.own?([@author]) + r.should be_true + end + it 'ロール内作家のidが自身の作家idと一致しないならno' do + Story.stub(:get_author_from_roles).with(any_args).and_return(@other_author) + @story.own?(@other_author).should be_false + end + end + context 'ロール内作家が取得できないとき' do + before do + Story.stub(:get_author_from_roles).with(any_args).and_return(nil) + end + it 'Falseを返す' do + r = @story.own?([@author]) + r.should be_false + end + end + end + + describe '閲覧許可に於いて' do + before do + @story = FactoryGirl.build :story, :author_id => @author.id + end + context 'オープンモードのとき' do + before do + MagicNumber['run_mode'] = 0 + end + it '自身にゲスト用ロールチェックを問い合わせしている' do + Story.any_instance.stub(:guest_role_check).and_return(true) + Story.any_instance.should_receive(:guest_role_check).with(any_args).exactly(1) + r = @story.visible?([@author]) + end + it 'ゲスト用ロールチェックが失敗したとき、falseを返す' do + Story.any_instance.stub(:guest_role_check).and_return(false) + r = @story.visible?([@author]) + r.should be_false + end + end + context 'クローズドモードのとき' do + before do + MagicNumber['run_mode'] = 1 + end + it '自身に読者用ロールチェックを問い合わせしている' do + Story.any_instance.stub(:reader_role_check).and_return(true) + Story.any_instance.should_receive(:reader_role_check).with(any_args).exactly(1) + r = @story.visible?([@author]) + end + it '読者用ロールチェックが失敗したとき、falseを返す' do + Story.any_instance.stub(:reader_role_check).and_return(false) + r = @story.visible?([@author]) + r.should be_false + end + end + context '事前チェックする' do + before do + MagicNumber['run_mode'] = 1 + Story.any_instance.stub(:reader_role_check).and_return(true) + Story.any_instance.stub(:own?).and_return(true) + end + it '自身に所持判定を問い合わせしている' do + Story.any_instance.should_receive(:own?).with(any_args).exactly(1) + r = @story.visible?([@author]) + end + end + context 'つつがなく終わるとき' do + before do + MagicNumber['run_mode'] = 1 + Story.any_instance.stub(:reader_role_check).and_return(true) + end + it '自分のストーリーなら許可する' do + Story.any_instance.stub(:own?).and_return(true) + Story.any_instance.stub(:visible).and_return(0) + r = @story.visible?([@author]) + r.should be_true + end + it '他人の非公開ストーリーなら許可しない' do + Story.any_instance.stub(:own?).and_return(false) + Story.any_instance.stub(:visible).and_return(0) + r = @story.visible?([@author]) + r.should be_false + end + it '他人のストーリーでも公開なら許可する' do + Story.any_instance.stub(:own?).and_return(false) + Story.any_instance.stub(:visible).and_return(1) + r = @story.visible?([@author]) + r.should be_true + end + end + end + + describe '一覧取得に於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @story = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id + end + context 'page補正について' do + it '文字列から数値に変換される' do + Story.page('8').should eq 8 + end + it 'nilの場合は1になる' do + Story.page().should eq 1 + end + it '0以下の場合は1になる' do + Story.page('0').should eq 1 + end + end + context 'page_size補正について' do + it '文字列から数値に変換される' do + Story.page_size('7').should eq 7 + end + it 'nilの場合はStory.default_page_sizeになる' do + Story.page_size().should eq Story.default_page_size + end + it '0以下の場合はStory.default_page_sizeになる' do + Story.page_size('0').should eq Story.default_page_size + end + it 'Story.max_page_sizeを超えた場合はStory.max_page_sizeになる' do + Story.page_size('1000').should eq Story.max_page_size + end + end + context 'つつがなく終わるとき' do + it '一覧取得オプションを利用している' do + Story.stub(:list_opt).with(any_args).and_return({}) + Story.should_receive(:list_opt).with(any_args).exactly(1) + r = Story.list + end + end + it 'リストを返す' do + c = Story.list + c.should eq [@story] + end + it '非公開ストーリーは(自分のストーリーであっても)含んでいない' do + FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id, :visible => 0 + c = Story.list + c.should eq [@story] + end + it '時系列で並んでいる' do + #公開ストーリーは(他人のストーリーであっても)含んでいる + other_comic = FactoryGirl.create :comic, :author_id => @other_author.id + v = FactoryGirl.create :story, :comic_id => other_comic.id, :author_id => @other_author.id, :updated_at => Time.now + 100 + c = Story.list + c.should eq [v, @story] + end + context 'DBに5件あって1ページの件数を2件に変えたとして' do + before do + @story2 = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id, :updated_at => Time.now + 100 + @story3 = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id, :updated_at => Time.now + 200 + @story4 = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id, :updated_at => Time.now + 300 + @story5 = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id, :updated_at => Time.now + 400 + Story.stub(:default_page_size).and_return(2) + end + it '通常は2件を返す' do + c = Story.list + c.should have(2).items + end + it 'page=1なら末尾2件を返す' do + #時系列で並んでいる + c = Story.list(1) + c.should eq [@story5, @story4] + end + it 'page=2なら中間2件を返す' do + c = Story.list(2) + c.should eq [@story3, @story2] + end + it 'page=3なら先頭1件を返す' do + c = Story.list(3) + c.should eq [@story] + end + end + end + + describe '自分のストーリー一覧取得に於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @story = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id + end + context 'つつがなく終わるとき' do + it '一覧取得オプションを利用している' do + Story.stub(:list_opt).with(any_args).and_return({}) + Story.should_receive(:list_opt).with(any_args).exactly(1) + r = Story.mylist @author + end + end + it 'リストを返す' do + c = Story.mylist @author + c.should eq [@story] + end + it '時系列で並んでいる' do + nc = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id, :updated_at => Time.now + 100 + cl = Story.mylist @author + cl.should eq [nc, @story] + end + it '他人のストーリーは公開でも含まない' do + other_comic = FactoryGirl.create :comic, :author_id => @other_author.id + nc = FactoryGirl.create :story, :comic_id => other_comic.id, :author_id => @other_author.id, :visible => 1 + cl = Story.mylist @author + cl.should eq [@story] + end + it '自分のストーリーは非公開でも含んでいる' do + nc = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id, :visible => 0, :updated_at => Time.now + 100 + cl = Story.mylist @author + cl.should eq [nc, @story] + end + context 'DBに5件あって1ページの件数を2件に変えたとして' do + before do + @story2 = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id, :updated_at => Time.now + 100 + @story3 = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id, :updated_at => Time.now + 200 + @story4 = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id, :updated_at => Time.now + 300 + @story5 = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id, :updated_at => Time.now + 400 + end + it '通常は2件を返す' do + c = Story.mylist @author, 1, 2 + c.should have(2).items + end + it 'page=1なら末尾2件を返す' do + #時系列で並んでいる + c = Story.mylist(@author, 1, 2) + c.should eq [@story5, @story4] + end + it 'page=2なら中間2件を返す' do + c = Story.mylist(@author, 2, 2) + c.should eq [@story3, @story2] + end + it 'page=3なら先頭1件を返す' do + c = Story.mylist(@author, 3, 2) + c.should eq [@story] + end + end + end + + describe '他作家のストーリー一覧取得に於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @story = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id + @other_comic = FactoryGirl.create :comic, :author_id => @other_author.id + @other_story = FactoryGirl.create :story, :author_id => @other_author.id, :visible => 1 + end + context 'つつがなく終わるとき' do + it '一覧取得オプションを利用している' do + Story.stub(:list_opt).with(any_args).and_return({}) + Story.should_receive(:list_opt).with(any_args).exactly(1) + r = Story.himlist @other_author + end + end + it '指定した作家のリストを返す' do + r = Story.himlist @other_author + r.should eq [@other_story] + end + it '時系列で並んでいる' do + nc = FactoryGirl.create :story, :comic_id => @other_comic.id, :author_id => @other_author.id, :updated_at => Time.now + 100 + r = Story.himlist @other_author + r.should eq [nc, @other_story] + end + it '公開ストーリーに限る ' do + hidden = FactoryGirl.create :story, :comic_id => @other_comic.id, :author_id => @other_author.id, :visible => 0 + r = Story.himlist @other_author + r.should eq [@other_story] + end + context 'DBに5件あって1ページの件数を2件に変えたとして' do + before do + @other_story2 = FactoryGirl.create :story, :comic_id => @other_comic.id, :author_id => @other_author.id, :updated_at => Time.now + 100 + @other_story3 = FactoryGirl.create :story, :comic_id => @other_comic.id, :author_id => @other_author.id, :updated_at => Time.now + 200 + @other_story4 = FactoryGirl.create :story, :comic_id => @other_comic.id, :author_id => @other_author.id, :updated_at => Time.now + 300 + @other_story5 = FactoryGirl.create :story, :comic_id => @other_comic.id, :author_id => @other_author.id, :updated_at => Time.now + 400 + end + it '通常は2件を返す' do + c = Story.himlist @other_author, 1, 2 + c.should have(2).items + end + it 'page=1なら末尾2件を返す' do + #時系列で並んでいる + c = Story.himlist(@other_author, 1, 2) + c.should eq [@other_story5, @other_story4] + end + it 'page=2なら中間2件を返す' do + c = Story.himlist(@other_author, 2, 2) + c.should eq [@other_story3, @other_story2] + end + it 'page=3なら先頭1件を返す' do + c = Story.himlist(@other_author, 3, 2) + c.should eq [@other_story] + end + end + end + + describe 'ストーリー一覧ページ制御に於いて' do + before do + Story.stub(:count).with(any_args).and_return(100) + end + it 'ページ制御を返す' do + r = Story.list_paginate + r.is_a?(Kaminari::PaginatableArray).should be_true + end + it 'ストーリー一覧の取得条件を利用している' do + Story.stub(:list_where).with(any_args).and_return('') + Story.should_receive(:list_where).with(any_args).exactly(1) + r = Story.list_paginate + end + it 'ページ件数10のとき、3ページ目のオフセットは20から始まる' do + r = Story.list_paginate 3, 10 + r.limit_value.should eq 10 + r.offset_value.should eq 20 + end + end + + describe '自分のストーリー一覧ページ制御に於いて' do + before do + Story.stub(:count).with(any_args).and_return(100) + end + it 'ページ制御を返す' do + r = Story.mylist_paginate @author + r.is_a?(Kaminari::PaginatableArray).should be_true + end + it '自分のストーリー一覧の取得条件を利用している' do + Story.stub(:mylist_where).with(any_args).and_return('') + Story.should_receive(:mylist_where).with(any_args).exactly(1) + r = Story.mylist_paginate @author + end + it 'ページ件数10のとき、3ページ目のオフセットは20から始まる' do + r = Story.mylist_paginate @author, 3, 10 + r.limit_value.should eq 10 + r.offset_value.should eq 20 + end + end + + describe '他作家のストーリー一覧ページ制御に於いて' do + before do + Story.stub(:count).with(any_args).and_return(100) + end + it 'ページ制御を返す' do + r = Story.himlist_paginate @other_author + r.is_a?(Kaminari::PaginatableArray).should be_true + end + it '他作家のストーリー一覧の取得条件を利用している' do + Story.stub(:himlist_where).with(any_args).and_return('') + Story.should_receive(:himlist_where).with(any_args).exactly(1) + r = Story.himlist_paginate @other_author + end + it 'ページ件数10のとき、3ページ目のオフセットは20から始まる' do + r = Story.himlist_paginate @other_author, 3, 10 + r.limit_value.should eq 10 + r.offset_value.should eq 20 + end + end + + describe '一覧取得オプションに於いて' do + it '2つの項目を含んでいる' do + r = Story.list_opt + r.should have(2).items + end + it 'スト紙を含んでいる' do + r = Story.list_opt + r.has_key?(:story_sheets).should be_true + end + it 'スト紙は用紙を含んでいる' do + r = Story.list_opt + r[:story_sheets].has_key?(:sheet).should be_true + end + it 'スト紙は作家を含んでいる' do + r = Story.list_opt + r[:story_sheets].has_key?(:author).should be_true + end + it '作家を含んでいる' do + r = Story.list_opt + r.has_key?(:author).should be_true + end + end + describe 'json一覧出力オプションに於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @story = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id, :visible => 1 + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @story_sheet = FactoryGirl.create :story_sheet, :author_id => @author.id, :story_id => @story.id, :sheet_id => @sheet.id + end + it 'スト紙を含んでいる' do + r = Story.list.to_json Story.list_json_opt + j = JSON.parse r + i = j.first + i.has_key?('story_sheets').should be_true + end + it 'スト紙は用紙を含んでいる' do + r = Story.list.to_json Story.list_json_opt + j = JSON.parse r + i = j.first + s = i['story_sheets'].first + s.has_key?('sheet').should be_true + end + it 'スト紙は作家を含んでいる' do + r = Story.list.to_json Story.list_json_opt + j = JSON.parse r + i = j.first + s = i['story_sheets'].first + s.has_key?('author').should be_true + end + it '作家を含んでいる' do + r = Story.list.to_json Story.list_json_opt + j = JSON.parse r + i = j.first + i.has_key?('author').should be_true + end + end + + describe '単体取得に於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @story = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id + end + context 'つつがなく終わるとき' do + it '単体取得オプションを利用している' do + Story.stub(:show_opt).with(any_args).and_return({}) + Story.should_receive(:show_opt).with(any_args).exactly(1) + r = Story.show @story.id, @author + end + it '閲覧許可を問い合わせている' do + Story.any_instance.stub(:visible?).with(any_args).and_return(true) + Story.any_instance.should_receive(:visible?).with(any_args).exactly(1) + r = Story.show @story.id, @author + end + end + it '指定のストーリーを返す' do + c = Story.show @story.id, @author + c.should eq @story + end + context '閲覧許可が出なかったとき' do + it '403Forbidden例外を返す' do + Story.any_instance.stub(:visible?).and_return(false) + lambda{ + Story.show @story.id, @author + }.should raise_error(ActiveRecord::Forbidden) + end + end + context '存在しないストーリーを開こうとしたとき' do + it '404RecordNotFound例外を返す' do + lambda{ + Story.show 110, @author + }.should raise_error(ActiveRecord::RecordNotFound) + end + end + end + + describe '編集取得に於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @story = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id + end + context 'つつがなく終わるとき' do + it '単体取得オプションを利用している' do + Story.stub(:show_opt).with(any_args).and_return({}) + Story.should_receive(:show_opt).with(any_args).exactly(1) + r = Story.edit @story.id, @author + end + it '所持判定を問い合わせている' do + Story.any_instance.stub(:own?).with(any_args).and_return(true) + Story.any_instance.should_receive(:own?).with(any_args).exactly(1) + r = Story.edit @story.id, @author + end + end + it '指定のストーリーを返す' do + Story.any_instance.stub(:own?).and_return(true) + c = Story.edit @story.id, @author.id + c.should eq @story + end + context '他人のストーリーを開こうとしたとき' do + it '403Forbidden例外を返す' do + Story.any_instance.stub(:own?).and_return(false) + lambda{ + Story.edit @story.id, @author + }.should raise_error(ActiveRecord::Forbidden) + end + end + context '存在しないストーリーを開こうとしたとき' do + it '404RecordNotFound例外を返す' do + lambda{ + Story.edit 110, @author + }.should raise_error(ActiveRecord::RecordNotFound) + end + end + end + describe '単体取得オプションに於いて' do + it 'includeキーを含んでいる' do + r = Story.show_opt + r.has_key?(:include).should be_true + end + it '2つの項目を含んでいる' do + r = Story.show_opt[:include] + r.should have(2).items + end + it '作家を含んでいる' do + r = Story.show_opt[:include] + r.has_key?(:author).should be_true + end + it 'スト紙を含んでいる' do + r = Story.show_opt[:include] + r.has_key?(:story_sheets).should be_true + end + it 'スト紙は用紙を含んでいる' do + r = Story.show_opt[:include] + r[:story_sheets].has_key?(:sheet).should be_true + end + it 'スト紙は作家を含んでいる' do + r = Story.show_opt[:include] + r[:story_sheets].has_key?(:author).should be_true + end + end + describe 'json単体出力オプションに於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @story = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id, :visible => 1 + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @story_sheet = FactoryGirl.create :story_sheet, :author_id => @author.id, :story_id => @story.id, :sheet_id => @sheet.id + end + it 'スト紙を含んでいる' do + r = Story.show(@story.id, @author).to_json Story.show_json_opt + j = JSON.parse r + i = j + i.has_key?('story_sheets').should be_true + end + it 'スト紙は用紙を含んでいる' do + r = Story.show(@story.id, @author).to_json Story.show_json_opt + j = JSON.parse r + i = j + s = i['story_sheets'].first + s.has_key?('sheet').should be_true + end + it 'スト紙は作家を含んでいる' do + r = Story.show(@story.id, @author).to_json Story.show_json_opt + j = JSON.parse r + i = j + s = i['story_sheets'].first + s.has_key?('author').should be_true + end + it '作家を含んでいる' do + r = Story.show(@story.id, @author).to_json Story.show_json_opt + j = JSON.parse r + i = j + i.has_key?('author').should be_true + end + end + + describe 't補充値に於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + end + + context 'コミック初のコマなら' do + it '0を補充値とする' do + @story = FactoryGirl.build :story, :author_id => @author.id, :comic_id => @comic.id + @story.t = nil + r = Story.new_t @story.comic_id + r.should eq 0 + end + end + context 'コミックに一個コマがあるとき' do + it '1を補充値とする' do + FactoryGirl.create :story, :author_id => @author.id, :comic_id => @comic.id, :t => 0 + @story = FactoryGirl.build :story, :author_id => @author.id, :comic_id => @comic.id + @story.t = nil + r = Story.new_t @story.comic_id + r.should eq 1 + end + end + context 'コミックに2個コマがあるとき' do + it '2を補充値とする' do + FactoryGirl.create :story, :author_id => @author.id, :comic_id => @comic.id, :t => 0 + FactoryGirl.create :story, :author_id => @author.id, :comic_id => @comic.id, :t => 1 + @story = FactoryGirl.build :story, :author_id => @author.id, :comic_id => @comic.id + @story.t = nil + r = Story.new_t @story.comic_id + r.should eq 2 + end + end + end + describe 'シリアライズチェックに於いて' do + context 'つつがなく終わるとき' do + it '0からシリアライズされているならTrueを返す' do + r = Story.serial? [0, 1, 2] + r.should be_true + end + it '見た目はシリアライズされてなくてもソート結果が無事ならtrueを返す' do + r = Story.serial? [0, 2, 1] + r.should be_true + end + it '見た目はシリアライズされてなくてもソート結果が無事ならtrueを返す' do + r = Story.serial? [ 2, 1, 4, 3, 0] + r.should be_true + end + end + context '異常なとき' do + it '0から始まらないならFalseを返す' do + r = Story.serial? [1, 2, 3] + r.should be_false + end + it '連続していないならFalseを返す' do + r = Story.serial? [0, 1, 2, 4] + r.should be_false + end + it '連続していないならFalseを返す' do + r = Story.serial? [0, 1, 2, 4, 5] + r.should be_false + end + end + end + describe 't収集に於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id, :author_id => @author.id + @comic2 = FactoryGirl.create :comic, :author_id => @author.id + @c2story = FactoryGirl.create :story, :t => 0, :comic_id => @comic2.id, :author_id => @author.id + end + context 'つつがなく終わるとき' do + it 'ストーリーから同一コミックのtだけを収集している' do + r = Story.collect_t @story + r.should eq [0] + end + end + context '複数コマのとき' do + it 'ストーリーから同一コミックのtだけを収集している' do + @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id, :author_id => @author.id + r = Story.collect_t @story + r.sort.should eq [0, 1] + end + end + context '複数ストーリーでヨソのコミックも混じっているとき' do + it 'ストーリーから同一コミックのtだけを収集している' do + @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id, :author_id => @author.id + r = Story.collect_t @story + r.sort.should eq [0, 1] + end + end + end + describe 'tチェックに於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @story = FactoryGirl.build :story, :t => 1, :comic_id => @comic.id, :author_id => @author.id + end + context 'つつがなく終わるとき' do + it 't収集を依頼している' do + Story.should_receive(:collect_t).with(any_args).exactly(1) + Story.stub(:collect_t).with(any_args).and_return([]) + Story.stub(:serial?).with(any_args).and_return(true) + r = Story.validate_t @story + end + it '収集したtをシリアライズチェック依頼している' do + Story.stub(:collect_t).with(any_args).and_return([]) + Story.should_receive(:serial?).with(any_args).exactly(1) + Story.stub(:serial?).with(any_args).and_return(true) + r = Story.validate_t @story + end + end + #実データでチェック + #依頼チェックだけでは不安なので最低限のチェックを + context '新規のとき' do + it '一件だけで正常通過している' do + @story = FactoryGirl.build :story, :comic_id => @comic.id, :author_id => @author.id, :t => 0 + r = Story.validate_t @story + r.should be_true + end + end + context '既存のとき' do + it '2件目を作っても正常通過している' do + @story = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id, :t => 0 + @story2 = FactoryGirl.build :story, :comic_id => @comic.id, :author_id => @author.id, :t => 1 + r = Story.validate_t @story2 + r.should be_true + end + end + end + describe '挿入シフトに於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + end + context '依頼チェック' do + #テーブルが空で0に挿入 + it 'Updateを依頼している' do + Story.stub(:update_all).with(any_args) + Story.should_receive(:update_all).with(any_args).exactly(1) + @story = FactoryGirl.build :story, :t => 0, :comic_id => @comic.id, :author_id => @author.id + @story.insert_shift + end + end + context 'テーブルに1件(t:0)で0に挿入したとき' do + before do + @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id, :author_id => @author.id + @story2 = FactoryGirl.build :story, :t => 0, :comic_id => @comic.id, :author_id => @author.id + end + it '既存の行を1にシフトしている' do + @story2.insert_shift + l = Story.find :all + l.first.t.should eq 1 + end + it 'これから挿入するt(0)が欠番になっている' do + @story2.insert_shift + l = Story.find(:all).map {|s| s.t } + l.include?(0).should_not be_true + end + end + context 'テーブルに2件(t:0,1)で1に挿入したとき' do + before do + @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id, :author_id => @author.id + @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id, :author_id => @author.id + @story3 = FactoryGirl.build :story, :t => 1, :comic_id => @comic.id, :author_id => @author.id + end + it '既存のt1を2にシフトしてこれから挿入するt(1)が欠番になっている' do + @story3.insert_shift + l = Story.find(:all).map {|s| s.t } + l.sort.should eq [0, 2] + end + end + context 'テーブルに5件(t:0,1,2,3,4)で2に挿入したとき' do + before do + @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id, :author_id => @author.id + @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id, :author_id => @author.id + @story3 = FactoryGirl.create :story, :t => 2, :comic_id => @comic.id, :author_id => @author.id + @story4 = FactoryGirl.create :story, :t => 3, :comic_id => @comic.id, :author_id => @author.id + @story5 = FactoryGirl.create :story, :t => 4, :comic_id => @comic.id, :author_id => @author.id + @story6 = FactoryGirl.build :story, :t => 2, :comic_id => @comic.id, :author_id => @author.id + end + it '既存のt1を2にシフトしてこれから挿入するt(1)が欠番になっている' do + @story6.insert_shift + l = Story.find(:all).map {|s| s.t } + l.sort.should eq [0, 1, 3, 4, 5] + end + end + context '先ほどのケース+他のコミック1件で挿入したとき' do + before do + @comic2 = FactoryGirl.create :comic, :author_id => @author.id + @storyc2 = FactoryGirl.create :story, :t => 0, :comic_id => @comic2.id, :author_id => @author.id + @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id, :author_id => @author.id + @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id, :author_id => @author.id + @story3 = FactoryGirl.create :story, :t => 2, :comic_id => @comic.id, :author_id => @author.id + @story4 = FactoryGirl.create :story, :t => 3, :comic_id => @comic.id, :author_id => @author.id + @story5 = FactoryGirl.create :story, :t => 4, :comic_id => @comic.id, :author_id => @author.id + @story6 = FactoryGirl.build :story, :t => 2, :comic_id => @comic.id, :author_id => @author.id + end + it '既存のt1を2にシフトしてこれから挿入するt(1)が欠番になっている' do + @story6.insert_shift + l = Story.find(:all, :conditions => ['comic_id = ?', @comic.id]).map {|s| s.t } + l.sort.should eq [0, 1, 3, 4, 5] + end + it '他のコミックに影響がない' do + ot = @storyc2.t + @story6.insert_shift + @storyc2.reload + @storyc2.t.should eq ot + end + end + end + describe '少ない方に移動に於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + end + context '依頼チェック' do + it 'Updateを依頼している' do + @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id, :author_id => @author.id + @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id, :author_id => @author.id + Story.stub(:update_all).with(any_args) + Story.should_receive(:update_all).with(any_args).exactly(1) + ot = @story2.t + @story2.t = 0 + @story2.lesser_shift ot + end + end + context 'テーブルに2件(t:0,1)で1を0に移動したとき' do + before do + @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id, :author_id => @author.id + @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id, :author_id => @author.id + @ot = @story2.t + @story2.t = 0 + end + it '既存のt0を1にシフトしてこれから挿入するt(0)が欠番になっている' do + #移動させたい行はそのまま残る + @story2.lesser_shift @ot + l = Story.find(:all).map {|s| s.t } + l.sort.should eq [1, 1] + end + it '既存のt0を1にシフトしている' do + @story2.lesser_shift @ot + @story.reload + @story.t.should eq 1 + end + end + context 'テーブルに3件(t:0,1,2)で2を1に移動したとき' do + before do + @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id, :author_id => @author.id + @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id, :author_id => @author.id + @story3 = FactoryGirl.create :story, :t => 2, :comic_id => @comic.id, :author_id => @author.id + @ot = @story3.t + @story3.t = 1 + end + it '既存のt1を2にシフトしてこれから挿入するt(1)が欠番になっている' do + #移動させたい行はそのまま残る + @story3.lesser_shift @ot + l = Story.find(:all).map {|s| s.t } + l.sort.should eq [0, 2, 2] + end + it '既存のt1を2にシフトしている' do + @story3.lesser_shift @ot + @story2.reload + @story2.t.should eq 2 + end + end + context 'テーブルに5件(t:0,1,2,3,4)で3を1に移動したとき' do + before do + @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id, :author_id => @author.id + @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id, :author_id => @author.id + @story3 = FactoryGirl.create :story, :t => 2, :comic_id => @comic.id, :author_id => @author.id + @story4 = FactoryGirl.create :story, :t => 3, :comic_id => @comic.id, :author_id => @author.id + @story5 = FactoryGirl.create :story, :t => 4, :comic_id => @comic.id, :author_id => @author.id + @ot = @story4.t + @story4.t = 1 + end + it 'これから挿入するt(1)が欠番になっている' do + #移動させたい行はそのまま残る + @story4.lesser_shift @ot + l = Story.find(:all).map {|s| s.t } + l.sort.should eq [0, 2, 3, 3, 4] + end + it '既存のt0には変化がない' do + @story4.lesser_shift @ot + @story.reload + @story.t.should eq 0 + end + it '既存のt4には変化がない' do + @story4.lesser_shift @ot + @story5.reload + @story5.t.should eq 4 + end + it '既存のt1を2にシフトしている' do + @story4.lesser_shift @ot + @story2.reload + @story2.t.should eq 2 + end + it '既存のt2を3にシフトしている' do + @story4.lesser_shift @ot + @story3.reload + @story3.t.should eq 3 + end + end + context '先ほどのケース+他のコミック1件で挿入したとき' do + before do + @comic2 = FactoryGirl.create :comic, :author_id => @author.id + @storyc2 = FactoryGirl.create :story, :t => 0, :comic_id => @comic2.id, :author_id => @author.id + @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id, :author_id => @author.id + @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id, :author_id => @author.id + @story3 = FactoryGirl.create :story, :t => 2, :comic_id => @comic.id, :author_id => @author.id + @story4 = FactoryGirl.create :story, :t => 3, :comic_id => @comic.id, :author_id => @author.id + @story5 = FactoryGirl.create :story, :t => 4, :comic_id => @comic.id, :author_id => @author.id + @ot = @story4.t + @story4.t = 1 + end + it 'これから挿入するt(1)が欠番になっている' do + @story4.lesser_shift @ot + l = Story.find(:all).map {|s| s.t } + l.sort.should eq [0, 0, 2, 3, 3, 4] + end + it '既存のt0には変化がない' do + @story4.lesser_shift @ot + @story.reload + @story.t.should eq 0 + end + it '既存のt4には変化がない' do + @story4.lesser_shift @ot + @story5.reload + @story5.t.should eq 4 + end + it '既存のt1を2にシフトしている' do + @story4.lesser_shift @ot + @story2.reload + @story2.t.should eq 2 + end + it '既存のt2を3にシフトしている' do + @story4.lesser_shift @ot + @story3.reload + @story3.t.should eq 3 + end + it '他のコミックに影響がない' do + @story4.lesser_shift @ot + @storyc2.reload + @storyc2.t.should eq 0 + end + end + #例外ケース。 + #負のときは0として正常扱い + context 'テーブルに2件(t:0,1)で1を-1に移動したとき' do + before do + @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id, :author_id => @author.id + @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id, :author_id => @author.id + @ot = @story2.t + @story2.t = -1 + end + it '既存のt0を1にシフトしてこれから挿入するt(0)が欠番になっている' do + #移動させたい行はそのまま残る + @story2.lesser_shift @ot + l = Story.find(:all).map {|s| s.t } + l.sort.should eq [1, 1] + end + it '既存のt0を1にシフトしている' do + @story2.lesser_shift @ot + @story.reload + @story.t.should eq 1 + end + it '既存のt1は0に補正されている' do + @story2.lesser_shift @ot + @story2.t.should eq 0 + end + end + end + describe '大きい方に移動に於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + end + context '依頼チェック' do + it 'Updateを依頼している' do + @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id, :author_id => @author.id + @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id, :author_id => @author.id + Story.stub(:update_all).with(any_args) + Story.should_receive(:update_all).with(any_args).exactly(1) + ot = @story.t + @story.t = 1 + @story.higher_shift ot + end + end + context 'テーブルに2件(t:0,1)で0を1に移動したとき' do + before do + @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id, :author_id => @author.id + @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id, :author_id => @author.id + @ot = @story.t + @story.t = 1 + end + it '既存のt1を0にシフトしてこれから挿入するt(1)が欠番になっている' do + #移動させたい行はそのまま残る + @story.higher_shift @ot + l = Story.find(:all).map {|s| s.t } + l.sort.should eq [0, 0] + end + it '既存のt1を0にシフトしている' do + @story.higher_shift @ot + @story2.reload + @story2.t.should eq 0 + end + end + context 'テーブルに3件(t:0,1,2)で0を1に移動したとき' do + before do + @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id, :author_id => @author.id + @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id, :author_id => @author.id + @story3 = FactoryGirl.create :story, :t => 2, :comic_id => @comic.id, :author_id => @author.id + @ot = @story.t + @story.t = 1 + end + it '既存のt1を0にシフトしてこれから挿入するt(1)が欠番になっている' do + #移動させたい行はそのまま残る + @story.higher_shift @ot + l = Story.find(:all).map {|s| s.t } + l.sort.should eq [0, 0, 2] + end + it '既存のt1を0にシフトしている' do + @story.higher_shift @ot + @story2.reload + @story2.t.should eq 0 + end + end + context 'テーブルに5件(t:0,1,2,3,4)で1を3に移動したとき' do + before do + @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id, :author_id => @author.id + @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id, :author_id => @author.id + @story3 = FactoryGirl.create :story, :t => 2, :comic_id => @comic.id, :author_id => @author.id + @story4 = FactoryGirl.create :story, :t => 3, :comic_id => @comic.id, :author_id => @author.id + @story5 = FactoryGirl.create :story, :t => 4, :comic_id => @comic.id, :author_id => @author.id + @ot = @story2.t + @story2.t = 3 + end + it 'これから挿入するt(3)が欠番になっている' do + #移動させたい行はそのまま残る + @story2.higher_shift @ot + l = Story.find(:all).map {|s| s.t } + l.sort.should eq [0, 1, 1, 2, 4] + end + it '既存のt0には変化がない' do + @story2.higher_shift @ot + @story.reload + @story.t.should eq 0 + end + it '既存のt4には変化がない' do + @story2.higher_shift @ot + @story5.reload + @story5.t.should eq 4 + end + it '既存のt2を1にシフトしている' do + @story2.higher_shift @ot + @story3.reload + @story3.t.should eq 1 + end + it '既存のt3を2にシフトしている' do + @story2.higher_shift @ot + @story4.reload + @story4.t.should eq 2 + end + end + context '先ほどのケース+他のコミック1件で挿入したとき' do + before do + @comic2 = FactoryGirl.create :comic, :author_id => @author.id + @storyc2 = FactoryGirl.create :story, :t => 0, :comic_id => @comic2.id, :author_id => @author.id + @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id, :author_id => @author.id + @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id, :author_id => @author.id + @story3 = FactoryGirl.create :story, :t => 2, :comic_id => @comic.id, :author_id => @author.id + @story4 = FactoryGirl.create :story, :t => 3, :comic_id => @comic.id, :author_id => @author.id + @story5 = FactoryGirl.create :story, :t => 4, :comic_id => @comic.id, :author_id => @author.id + @ot = @story2.t + @story2.t = 3 + end + it 'これから挿入するt(3)が欠番になっている' do + #移動させたい行はそのまま残る + @story2.higher_shift @ot + l = Story.find(:all).map {|s| s.t } + l.sort.should eq [0, 0, 1, 1, 2, 4] + end + it '既存のt0には変化がない' do + @story2.higher_shift @ot + @story.reload + @story.t.should eq 0 + end + it '既存のt4には変化がない' do + @story2.higher_shift @ot + @story5.reload + @story5.t.should eq 4 + end + it '既存のt2を1にシフトしている' do + @story2.higher_shift @ot + @story3.reload + @story3.t.should eq 1 + end + it '既存のt3を2にシフトしている' do + @story2.higher_shift @ot + @story4.reload + @story4.t.should eq 2 + end + it '他のコミックに影響がない' do + @story2.higher_shift @ot + @storyc2.reload + @storyc2.t.should eq 0 + end + end + #例外ケース。 + #max超えたときはmaxとして正常扱い + context 'テーブルに2件(t:0,1)で0を2に移動したとき' do + before do + @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id, :author_id => @author.id + @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id, :author_id => @author.id + @ot = @story.t + @story.t = 2 + end + it '既存のt1を0にシフトしてこれから挿入するt(1)が欠番になっている' do + #移動させたい行はそのまま残る + @story.higher_shift @ot + l = Story.find(:all).map {|s| s.t } + l.sort.should eq [0, 0] + end + it '既存のt1を0にシフトしている' do + @story.higher_shift @ot + @story2.reload + @story2.t.should eq 0 + end + it '既存のt0は1に補正されている' do + @story.higher_shift @ot + @story.t.should eq 1 + end + end + end + describe '入れ替えに於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id, :author_id => @author.id + @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id, :author_id => @author.id + end + context '新tが旧tより小さいとき' do + it '少ない方に移動を依頼している' do + Story.any_instance.stub(:lesser_shift).with(any_args) + Story.any_instance.should_receive(:lesser_shift).with(any_args).exactly(1) + ot = @story2.t + @story2.t = 0 + @story2.update_shift ot + end + end + context '新tが旧tより大きいとき' do + it '大きい方に移動を依頼している' do + Story.any_instance.stub(:higher_shift).with(any_args) + Story.any_instance.should_receive(:higher_shift).with(any_args).exactly(1) + ot = @story.t + @story.t = 1 + @story.update_shift ot + end + end + end + describe '順序入れ替えに於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + end + context 'オブジェクトが新規でtが空のとき' do + it '末尾追加としてtを補充依頼している' do + @story = FactoryGirl.build :story, :comic_id => @comic.id, :author_id => @author.id + Story.stub(:new_t).with(any_args).and_return(0) + Story.should_receive(:new_t).with(any_args).exactly(1) + @story.t = nil + r = @story.rotate + end + end + context 'オブジェクトが新規でtが設定されているとき' do + it '挿入追加として挿入シフトを依頼している' do + @story = FactoryGirl.build :story, :comic_id => @comic.id, :author_id => @author.id + Story.any_instance.stub(:insert_shift).with(any_args) + Story.any_instance.should_receive(:insert_shift).with(any_args).exactly(1) + @story.t = 0 + r = @story.rotate + end + end + context 'オブジェクトが新規でなくtが設定されているとき' do + it '移動として入れ替えを依頼している' do + @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id, :author_id => @author.id + @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id, :author_id => @author.id + Story.any_instance.stub(:update_shift).with(any_args) + Story.any_instance.should_receive(:update_shift).with(1).exactly(1) + @story2.t = 0 + r = @story.rotate 1 + end + end + context 'オブジェクトが新規でなくtが空のとき' do + it '入れ替えもシフトもせず、tを空のままにしている' do + #結果、tに欠番が生じてシリアライズチェックでひっかかる + end + end + end + describe '編集許可に於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @panel = FactoryGirl.create :panel, :author_id => @author.id + @story = FactoryGirl.build :story, :t => nil, :comic_id => @comic.id, :author_id => @author.id + end + context 'つつがなく終わるとき' do + it 'trueを返す' do + r = @story.allow? + r.should be_true + end + end + context 'コミックで引っかかるとき' do + it 'falseを返す' do + Panel.any_instance.stub(:usable?).with(any_args).and_return(true) + Comic.any_instance.stub(:own?).with(any_args).and_return(false) + r = @story.allow? + r.should be_false + end + end + context 'コミックが指定されていなかったとき' do + it 'nilを返す' do + Comic.any_instance.stub(:own?).with(any_args).and_return(true) + @story.comic_id = nil + r = @story.allow? + r.should eq nil + end + end + end + describe '保存に於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @story = FactoryGirl.build :story, :t => nil, :comic_id => @comic.id, :author_id => @author.id + end + context 'つつがなく終わるとき' do + it '編集許可チェックを依頼している' do + Story.any_instance.stub(:allow?).with(any_args).and_return(true) + Story.any_instance.should_receive(:allow?).with(any_args).exactly(1) + r = @story.store + end + it '順序入れ替えを依頼している' do + Story.any_instance.stub(:rotate).with(any_args).and_return(0) + Story.any_instance.should_receive(:rotate).with(any_args).exactly(1) + Story.any_instance.stub(:save).with(any_args).and_return(true) + Story.stub(:validate_t).with(any_args).and_return(true) + r = @story.store + end + it '保存を依頼している' do + Story.stub(:new_t).with(any_args).and_return(0) + Story.any_instance.stub(:save).with(any_args).and_return(true) + Story.any_instance.should_receive(:save).with(any_args).exactly(1) + Story.stub(:validate_t).with(any_args).and_return(true) + r = @story.store + end + it 'tのシリアライズチェックを依頼している' do + Story.stub(:new_t).with(any_args).and_return(0) + Story.any_instance.stub(:save).with(any_args).and_return(true) + Story.stub(:validate_t).with(any_args).and_return(true) + Story.should_receive(:validate_t).with(any_args).exactly(1) + r = @story.store + end + end + #入れ替えテストと同じテストを実施。こちらはシフトだけでなく本尊も更新されている + context 'テーブルに5件(t:0,1,2,3,4)+他のコミック1件で2に挿入したとき' do + before do + @comic2 = FactoryGirl.create :comic, :author_id => @author.id + @storyc2 = FactoryGirl.create :story, :t => 0, :comic_id => @comic2.id, :author_id => @author.id + @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id, :author_id => @author.id + @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id, :author_id => @author.id + @story3 = FactoryGirl.create :story, :t => 2, :comic_id => @comic.id, :author_id => @author.id + @story4 = FactoryGirl.create :story, :t => 3, :comic_id => @comic.id, :author_id => @author.id + @story5 = FactoryGirl.create :story, :t => 4, :comic_id => @comic.id, :author_id => @author.id + @story6 = FactoryGirl.build :story, :t => 2, :comic_id => @comic.id, :author_id => @author.id + end + it '既存のt0には変化がない' do + @story6.store + @story.reload + @story.t.should eq 0 + end + it '既存のt1には変化がない' do + @story6.store + @story2.reload + @story2.t.should eq 1 + end + it '既存のt2を3にシフトしている' do + @story6.store + @story3.reload + @story3.t.should eq 3 + end + it '既存のt3を4にシフトしている' do + @story6.store + @story4.reload + @story4.t.should eq 4 + end + it '既存のt5を5にシフトしている' do + @story6.store + @story5.reload + @story5.t.should eq 5 + end + it '新規のt2が作成されている' do + @story6.store + @story6.reload + @story6.t.should eq 2 + end + it '他のコミックに影響がない' do + @ot = @storyc2.t + @story6.store + @storyc2.reload + @storyc2.t.should eq @ot + end + end + context 'テーブルに5件(t:0,1,2,3,4)+他のコミック1件で3を1に移動したとき' do + before do + @comic2 = FactoryGirl.create :comic, :author_id => @author.id + @storyc2 = FactoryGirl.create :story, :t => 0, :comic_id => @comic2.id, :author_id => @author.id + @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id, :author_id => @author.id + @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id, :author_id => @author.id + @story3 = FactoryGirl.create :story, :t => 2, :comic_id => @comic.id, :author_id => @author.id + @story4 = FactoryGirl.create :story, :t => 3, :comic_id => @comic.id, :author_id => @author.id + @story5 = FactoryGirl.create :story, :t => 4, :comic_id => @comic.id, :author_id => @author.id + @ot = @story4.t + @story4.t = 1 + end + it '既存のt0には変化がない' do + @story4.store @ot + @story.reload + @story.t.should eq 0 + end + it '既存のt4には変化がない' do + @story4.store @ot + @story5.reload + @story5.t.should eq 4 + end + it '既存のt1を2にシフトしている' do + @story4.store @ot + @story2.reload + @story2.t.should eq 2 + end + it '既存のt2を3にシフトしている' do + @story4.store @ot + @story3.reload + @story3.t.should eq 3 + end + it '既存のt3を1にシフトしている' do + @story4.store @ot + @story4.reload + @story4.t.should eq 1 + end + it '他のコミックに影響がない' do + @story4.store @ot + @storyc2.reload + @storyc2.t.should eq 0 + end + end + context 'テーブルに5件(t:0,1,2,3,4)+他のコミック1件で1を3に移動したとき' do + before do + @comic2 = FactoryGirl.create :comic, :author_id => @author.id + @storyc2 = FactoryGirl.create :story, :t => 0, :comic_id => @comic2.id, :author_id => @author.id + @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id, :author_id => @author.id + @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id, :author_id => @author.id + @story3 = FactoryGirl.create :story, :t => 2, :comic_id => @comic.id, :author_id => @author.id + @story4 = FactoryGirl.create :story, :t => 3, :comic_id => @comic.id, :author_id => @author.id + @story5 = FactoryGirl.create :story, :t => 4, :comic_id => @comic.id, :author_id => @author.id + @ot = @story2.t + @story2.t = 3 + end + it '既存のt0には変化がない' do + @story2.store @ot + @story.reload + @story.t.should eq 0 + end + it '既存のt4には変化がない' do + @story2.store @ot + @story5.reload + @story5.t.should eq 4 + end + it '既存のt1を3にシフトしている' do + @story2.store @ot + @story2.reload + @story2.t.should eq 3 + end + it '既存のt2を1にシフトしている' do + @story2.store @ot + @story3.reload + @story3.t.should eq 1 + end + it '既存のt3を2にシフトしている' do + @story2.store @ot + @story4.reload + @story4.t.should eq 2 + end + it '他のコミックに影響がない' do + @story2.store @ot + @storyc2.reload + @storyc2.t.should eq 0 + end + end + #ロールバックテスト。入れ替えが直接DBをいじるので、すべてのケースで確実にロールバックを確認する + context 'テーブルに5件(t:0,1,2,3,4)+他のコミック1件で2に挿入したが保存に失敗したとき' do + before do + Story.any_instance.stub(:save).with(any_args).and_return(false) + @comic2 = FactoryGirl.create :comic, :author_id => @author.id + @storyc2 = FactoryGirl.create :story, :t => 0, :comic_id => @comic2.id, :author_id => @author.id + @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id, :author_id => @author.id + @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id, :author_id => @author.id + @story3 = FactoryGirl.create :story, :t => 2, :comic_id => @comic.id, :author_id => @author.id + @story4 = FactoryGirl.create :story, :t => 3, :comic_id => @comic.id, :author_id => @author.id + @story5 = FactoryGirl.create :story, :t => 4, :comic_id => @comic.id, :author_id => @author.id + @story6 = FactoryGirl.build :story, :t => 2, :comic_id => @comic.id, :author_id => @author.id + end + it '既存のtに変化がない' do + @story6.store + @story.reload + @story.t.should eq 0 + @story2.reload + @story2.t.should eq 1 + @story3.reload + @story3.t.should eq 2 + @story4.reload + @story4.t.should eq 3 + @story5.reload + @story5.t.should eq 4 + @storyc2.reload + @storyc2.t.should eq 0 + end + it 'falseを返す' do + r = @story6.store + r.should be_false + end + end + context 'テーブルに5件(t:0,1,2,3,4)+他のコミック1件で3を1に移動したがシリアルチェックに失敗したとき' do + before do + Story.stub(:validate_t).with(any_args).and_return(false) + @comic2 = FactoryGirl.create :comic, :author_id => @author.id + @storyc2 = FactoryGirl.create :story, :t => 0, :comic_id => @comic2.id, :author_id => @author.id + @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id, :author_id => @author.id + @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id, :author_id => @author.id + @story3 = FactoryGirl.create :story, :t => 2, :comic_id => @comic.id, :author_id => @author.id + @story4 = FactoryGirl.create :story, :t => 3, :comic_id => @comic.id, :author_id => @author.id + @story5 = FactoryGirl.create :story, :t => 4, :comic_id => @comic.id, :author_id => @author.id + @ot = @story4.t + @story4.t = 1 + end + it '既存のtに変化がない' do + @story4.store @ot + @story.reload + @story.t.should eq 0 + @story2.reload + @story2.t.should eq 1 + @story3.reload + @story3.t.should eq 2 + @story4.reload + @story4.t.should eq 3 + @story5.reload + @story5.t.should eq 4 + @storyc2.reload + @storyc2.t.should eq 0 + end + it 'falseを返す' do + r = @story4.store @ot + r.should be_false + end + it 'tにエラーメッセージが入っている' do + @story4.store @ot + @story4.errors[:t].should_not be_empty + @story4.valid?.should be_true + end + end + context '編集不可だったとき' do + before do + @story = FactoryGirl.build :story, :t => 0, :comic_id => @comic.id, :author_id => @author.id + Story.any_instance.stub(:allow?).and_return(false) + end + it '403Forbidden例外を返す' do + lambda{ + @story.store + }.should raise_error(ActiveRecord::Forbidden) + end + end + end + describe '切り詰め処理つき削除に於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @story = FactoryGirl.create :story, :t => 0, :comic_id => @comic.id, :author_id => @author.id + end + context 'つつがなく終わるとき' do + it '削除される' do + lambda{ + @story.destroy_and_shorten + }.should change(Story, :count ).by(-1) + end + it 'Trueを返す' do + r = @story.destroy_and_shorten + r.should be_true + end + end + context '削除に失敗したとき' do + before do + Story.any_instance.stub(:destroy).and_return(false) + end + it 'ロールバックされる' do + lambda{ + @story.destroy_and_shorten + }.should_not change(Story, :count ) + end + it 'Falseを返す' do + r = @story.destroy_and_shorten + r.should be_false + end + end + #連携テスト。切り詰めが直接DBをいじる + context '2件で先頭を削除したとき' do + before do + @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id, :author_id => @author.id + end + it '行が削除される' do + lambda{ + @story.destroy_and_shorten + }.should change(Story, :count ).by(-1) + end + it '先頭は削除される' do + @story.destroy_and_shorten + lambda{ + Story.find @story.id + }.should raise_error(ActiveRecord::RecordNotFound) + end + it '2件目は前に詰められる' do + @story.destroy_and_shorten + @story2.reload + @story2.t.should eq 0 + end + end + context '3件で先頭を削除したとき' do + before do + @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id, :author_id => @author.id + @story3 = FactoryGirl.create :story, :t => 2, :comic_id => @comic.id, :author_id => @author.id + end + it '行が削除される' do + lambda{ + @story.destroy_and_shorten + }.should change(Story, :count ).by(-1) + end + it '先頭は削除される' do + @story.destroy_and_shorten + lambda{ + Story.find @story.id + }.should raise_error(ActiveRecord::RecordNotFound) + end + it '2件目は前に詰められる' do + @story.destroy_and_shorten + @story2.reload + @story2.t.should eq 0 + end + it '3件目は前に詰められる' do + @story.destroy_and_shorten + @story3.reload + @story3.t.should eq 1 + end + end + context '5件で3件目を削除したとき' do + before do + @story2 = FactoryGirl.create :story, :t => 1, :comic_id => @comic.id, :author_id => @author.id + @story3 = FactoryGirl.create :story, :t => 2, :comic_id => @comic.id, :author_id => @author.id + @story4 = FactoryGirl.create :story, :t => 3, :comic_id => @comic.id, :author_id => @author.id + @story5 = FactoryGirl.create :story, :t => 4, :comic_id => @comic.id, :author_id => @author.id + end + it '行が削除される' do + lambda{ + @story3.destroy_and_shorten + }.should change(Story, :count ).by(-1) + end + it '1件目は変化がない' do + @story3.destroy_and_shorten + @story.reload + @story.t.should eq 0 + end + it '2件目は変化がない' do + @story3.destroy_and_shorten + @story2.reload + @story2.t.should eq 1 + end + it '3件目は削除される' do + @story3.destroy_and_shorten + lambda{ + Story.find @story3.id + }.should raise_error(ActiveRecord::RecordNotFound) + end + it '4件目は前に詰められる' do + @story3.destroy_and_shorten + @story4.reload + @story4.t.should eq 2 + end + it '5件目は前に詰められる' do + @story3.destroy_and_shorten + @story5.reload + @story5.t.should eq 3 + end + end + #ロールバックテスト。切り詰めが直接DBをいじるので、すべてのケースで確実にロールバックを確認する + end + describe '削除に於いて' do + before do + @comic = FactoryGirl.create :comic, :author_id => @author.id + @story = FactoryGirl.create :story, :comic_id => @comic.id, :author_id => @author.id + @sheet = FactoryGirl.create :sheet, :author_id => @author.id + @story_sheet = FactoryGirl.create :story_sheet, :author_id => @author.id, :story_id => @story.id, :sheet_id => @sheet.id + @other_comic = FactoryGirl.create :comic, :author_id => @author.id + @other_story = FactoryGirl.create :story, :comic_id => @other_comic.id, :author_id => @author.id + @other_sheet = FactoryGirl.create :sheet, :author_id => @author.id + @other_story_sheet = FactoryGirl.create :story_sheet, :author_id => @author.id, :story_id => @other_story.id, :sheet_id => @other_sheet.id + end + context 'つつがなく終わるとき' do + it '自身を削除する' do + lambda { + r = @story.destroy_with_story_sheet + }.should change(Story, :count).by(-1) + lambda { + r = Story.find @story.id + }.should raise_error + end + it '自身にリンクしているスト紙をすべて削除する' do + lambda { + r = @story.destroy_with_story_sheet + }.should change(StorySheet, :count).by(-1) + lambda { + r = StorySheet.find @story_sheet.id + }.should raise_error + end + it 'Trueを返す' do + r = @story.destroy_with_story_sheet + r.should be_true + end + end + context '削除に失敗したとき' do + before do + StorySheet.any_instance.stub(:destroy).with(any_args).and_return(false) + end + it 'Falseを返す' do + r = @story.destroy_with_story_sheet + r.should be_false + end + it 'ロールバックしている' do + lambda { + r = @story.destroy_with_story_sheet + }.should_not change(Story, :count) + lambda { + r = @story.destroy_with_story_sheet + }.should_not change(StorySheet, :count) + end + end + end +end diff --git a/spec/models/system_picture_spec.rb b/spec/models/system_picture_spec.rb index de784bd1..60d9e5fa 100644 --- a/spec/models/system_picture_spec.rb +++ b/spec/models/system_picture_spec.rb @@ -3,6 +3,8 @@ require 'spec_helper' #システム画像 describe SystemPicture do before do + SpeechBalloonTemplate.delete_all + SystemPicture.delete_all @admin = FactoryGirl.create :admin end -- 2.11.0