リビジョン | 6795717c3801cc4d3503eeca5eff8ee2f775f65b (tree) |
---|---|
日時 | 2017-08-14 03:00:50 |
作者 | HMML <hmml3939@gmai...> |
コミッター | HMML |
Add theme class (WIP).
@@ -24,6 +24,7 @@ | ||
24 | 24 | /yarn-error.log |
25 | 25 | /public/packs |
26 | 26 | /public/system |
27 | +/private | |
27 | 28 | |
28 | 29 | /.vagrant |
29 | 30 | /erd.* |
@@ -57,6 +57,8 @@ gem 'daemons' | ||
57 | 57 | gem 'exception_notification', group: :production |
58 | 58 | gem 'paperclip' |
59 | 59 | gem 'rqrcode', github: 'sugi/rqrcode', branch: 'inline-svg' |
60 | +gem 'rubyzip', '>= 1.0.0', require: 'zip' | |
61 | +#gem 'counter_culture', '~> 1.0' | |
60 | 62 | |
61 | 63 | group :development, :test do |
62 | 64 | # Call 'byebug' anywhere in the code to stop execution and get a debugger console |
@@ -472,6 +472,7 @@ DEPENDENCIES | ||
472 | 472 | responders |
473 | 473 | rqrcode! |
474 | 474 | rspec-rails |
475 | + rubyzip (>= 1.0.0) | |
475 | 476 | sass-rails (~> 5.0) |
476 | 477 | sdoc (~> 0.4.0) |
477 | 478 | selenium-webdriver |
@@ -0,0 +1,3 @@ | ||
1 | +# Place all the behaviors and hooks related to the matching controller here. | |
2 | +# All this logic will automatically be available in application.js. | |
3 | +# You can use CoffeeScript in this file: http://coffeescript.org/ |
@@ -0,0 +1,3 @@ | ||
1 | +// Place all the styles related to the Themes controller here. | |
2 | +// They will automatically be included in application.css. | |
3 | +// You can use Sass (SCSS) here: http://sass-lang.com/ |
@@ -0,0 +1,48 @@ | ||
1 | +class ThemesController < ApplicationController | |
2 | + before_action :set_theme, only: [:show, :edit, :update, :destroy] | |
3 | + respond_to :html | |
4 | + | |
5 | + load_and_authorize_resource | |
6 | + | |
7 | + def index | |
8 | + @themes = Theme.all | |
9 | + respond_with(@themes) | |
10 | + end | |
11 | + | |
12 | + def show | |
13 | + respond_with(@theme) | |
14 | + end | |
15 | + | |
16 | + def new | |
17 | + @theme = Theme.new | |
18 | + respond_with(@theme) | |
19 | + end | |
20 | + | |
21 | + def edit | |
22 | + end | |
23 | + | |
24 | + def create | |
25 | + @theme = Theme.new(theme_params) | |
26 | + @theme.save | |
27 | + respond_with(@theme) | |
28 | + end | |
29 | + | |
30 | + def update | |
31 | + @theme.update(theme_params) | |
32 | + respond_with(@theme) | |
33 | + end | |
34 | + | |
35 | + def destroy | |
36 | + @theme.destroy | |
37 | + respond_with(@theme) | |
38 | + end | |
39 | + | |
40 | + private | |
41 | + def set_theme | |
42 | + @theme = Theme.find(params[:id]) | |
43 | + end | |
44 | + | |
45 | + def theme_params | |
46 | + params.require(:theme).permit(:name, :short_desc, :disabled, :author, :url, :license, :user_id, :allow_orig_dl) | |
47 | + end | |
48 | +end |
@@ -0,0 +1,2 @@ | ||
1 | +module ThemesHelper | |
2 | +end |
@@ -1,3 +1,10 @@ | ||
1 | +require 'fileutils' | |
1 | 2 | class ApplicationRecord < ActiveRecord::Base |
2 | 3 | self.abstract_class = true |
4 | + | |
5 | + def _zip_tmp_path(category) | |
6 | + path = Rails.root.join('tmp', 'archives', category, "#{self.class.to_s.downcase}-#{id}-#{SecureRandom.hex(6)}.zip") | |
7 | + FileUtils.mkdir_p path.dirname | |
8 | + path | |
9 | + end | |
3 | 10 | end |
@@ -31,7 +31,7 @@ class Draft < ApplicationRecord | ||
31 | 31 | belongs_to :user, required: false |
32 | 32 | before_save :renew_expire |
33 | 33 | after_initialize :set_key |
34 | - validates :title, :url, length: { maximum: 255 } | |
34 | + validates :title, length: { maximum: 60 } | |
35 | 35 | validates :url, format: { with: %r{\Ahttps?://[a-z0-9-]+(\.[a-z0-9-]+){1,}/}i }, allow_blank: true |
36 | 36 | validates :key, uniqueness: true |
37 | 37 |
@@ -48,6 +48,10 @@ class Draft < ApplicationRecord | ||
48 | 48 | size: { less_than: 20.megabyte } |
49 | 49 | end |
50 | 50 | |
51 | + def name | |
52 | + title | |
53 | + end | |
54 | + | |
51 | 55 | def renew_expire |
52 | 56 | self.expires_at = Time.now + EXPIRES_IN |
53 | 57 | end |
@@ -66,6 +70,35 @@ class Draft < ApplicationRecord | ||
66 | 70 | key |
67 | 71 | end |
68 | 72 | |
73 | + def theme_definition | |
74 | + ThemeDefinition.new(draft: self) | |
75 | + end | |
76 | + | |
77 | + def theme_image_archive | |
78 | + ICONS.find { |ic| public_send("wi_#{ic}?") } or return nil | |
79 | + path = _zip_tmp_path('theme-archive') | |
80 | + Zip::File.open(path, Zip::File::CREATE) do |zf| | |
81 | + ICONS.each do |ic| | |
82 | + public_send("wi_#{ic}?") or next | |
83 | + zf.add "wi-#{ic.chars.map{|c| FILENAME_MAP[c]}.join('_')}.webp", public_send("wi_#{ic}").path(:webp500) | |
84 | + end | |
85 | + end | |
86 | + path | |
87 | + end | |
88 | + | |
89 | + def orig_archive | |
90 | + ICONS.find { |ic| public_send("wi_#{ic}?") } or return nil | |
91 | + path = _zip_tmp_path('orig-archive') | |
92 | + Zip::File.open(path, Zip::File::CREATE) do |zf| | |
93 | + ICONS.each do |ic| | |
94 | + public_send("wi_#{ic}?") or next | |
95 | + attach = public_send("wi_#{ic}") | |
96 | + zf.add "Weather_#{ic.chars.map{|c| FILENAME_MAP[c]}.join('-')}#{File.extname(attach.path)}", attach.path | |
97 | + end | |
98 | + end | |
99 | + path | |
100 | + end | |
101 | + | |
69 | 102 | def as_json(opts = {}) |
70 | 103 | ret = super(opts) |
71 | 104 | ret["path"] = Rails.application.routes.url_helpers.draft_path(self, format: :json) |
@@ -0,0 +1,116 @@ | ||
1 | +require 'fileutils' | |
2 | +class Theme < ApplicationRecord | |
3 | + belongs_to :user, required: false | |
4 | + | |
5 | + attr_accessor :archive_update_required | |
6 | + enum day_frame: {white: '@builtin/white', black: '@builtin/black'}, _prefix: 'day_frame' | |
7 | + | |
8 | + preview_opts = { | |
9 | + styles: { | |
10 | + thumb500: '500x500>', | |
11 | + thumb300: '300x300>', | |
12 | + thumb120: '120x120>', | |
13 | + }, | |
14 | + } | |
15 | + has_attached_file :preview1, preview_opts | |
16 | + has_attached_file :preview2, preview_opts | |
17 | + has_attached_file :preview3, preview_opts | |
18 | + | |
19 | + archive_opts = { | |
20 | + path: ':rails_root/private/system/:class/:attachment/:id_partition/:style/:filename', | |
21 | + processors: [], | |
22 | + } | |
23 | + has_attached_file :orig_archive, archive_opts | |
24 | + has_attached_file :theme_archive, archive_opts | |
25 | + | |
26 | + validates :name, :author, :license, presence: true | |
27 | + validates :name, length: {maximum: 60} | |
28 | + validates :url, format: { with: %r{\Ahttps?://[a-z0-9-]+(\.[a-z0-9-]+){1,}/}i }, allow_blank: true | |
29 | + | |
30 | + validates_attachment :preview1, :preview2, :preview3, content_type: {content_type: /\Aimage\//} | |
31 | + validates_attachment :orig_archive, :theme_archive, content_type: {content_type: %w(application/zip)} | |
32 | + | |
33 | + before_save :set_archive_update_required | |
34 | + after_save :auto_update_archive | |
35 | + | |
36 | + def draft=(draft) | |
37 | + draft.kind_of?(Draft) or draft = Draft.find(draft) | |
38 | + %i(name author url).each do |attr| | |
39 | + self.public_send "#{attr}=", draft.public_send(attr) | |
40 | + end | |
41 | + self.day_frame = draft.read_attribute_before_type_cast(:day_frame) | |
42 | + {theme: :theme_image, orig: :orig}.each do |t_name, d_name| | |
43 | + fh = nil | |
44 | + begin | |
45 | + path = draft.public_send("#{d_name}_archive") or next | |
46 | + fh = File.open(path) | |
47 | + public_send "#{t_name}_archive=", fh | |
48 | + ensure | |
49 | + begin | |
50 | + fh && fh.close | |
51 | + rescue | |
52 | + # ignore | |
53 | + end | |
54 | + end | |
55 | + end | |
56 | + draft | |
57 | + end | |
58 | + alias_method :draft_id=, :draft= | |
59 | + | |
60 | + def update_archives | |
61 | + update_orig_archive | |
62 | + update_theme_archive | |
63 | + end | |
64 | + | |
65 | + def update_orig_archive | |
66 | + orig_archive? or return | |
67 | + if new_record? | |
68 | + self.archive_update_required = true | |
69 | + logger.warn "update_orig_archive is called before seve. Setting update hook and ignore..." | |
70 | + return | |
71 | + end | |
72 | + tmp_path = _zip_tmp_path('orig-archive') | |
73 | + FileUtils.cp (orig_archive.dirty? ? orig_archive.staged_path : orig_archive.path), tmp_path | |
74 | + Zip::File.open(tmp_path) do |zf| | |
75 | + zf.get_output_stream("ThemeDetails.html") do |o| | |
76 | + o << %Q{<!DOCTYPE html>\n<script>window.location.href="#{Rails.application.routes.url_helpers.theme_url(self)}";</script>} | |
77 | + end | |
78 | + end | |
79 | + tmp_path.open do |f| | |
80 | + self.orig_archive = f | |
81 | + end | |
82 | + save | |
83 | + end | |
84 | + | |
85 | + def update_theme_archive | |
86 | + theme_archive? or return | |
87 | + if new_record? | |
88 | + self.archive_update_required = true | |
89 | + logger.warn "update_theme_archive is called before seve. Setting update hook and ignore..." | |
90 | + return | |
91 | + end | |
92 | + tmp_path = _zip_tmp_path('theme-archive') | |
93 | + FileUtils.cp theme_archive.path, tmp_path | |
94 | + Zip::File.open(tmp_path) do |zf| | |
95 | + zf.get_output_stream("theme.json") do |o| | |
96 | + o << ThemeDefinition.new(theme: self).to_json | |
97 | + end | |
98 | + end | |
99 | + tmp_path.open do |f| | |
100 | + self.theme_archive = f | |
101 | + end | |
102 | + save | |
103 | + end | |
104 | + | |
105 | + def set_archive_update_required | |
106 | + new_record? or return true | |
107 | + self.archive_update_required = true | |
108 | + end | |
109 | + | |
110 | + def auto_update_archive | |
111 | + self.archive_update_required or return true | |
112 | + self.archive_update_required = false | |
113 | + update_archives | |
114 | + true | |
115 | + end | |
116 | +end |
@@ -0,0 +1,41 @@ | ||
1 | +class ThemeDefinition | |
2 | + include ActiveModel | |
3 | + | |
4 | + attr_accessor :id, :name, :url, :author, :day_frame, :license, :short_desc | |
5 | + | |
6 | + def initialize(attrs = {}) | |
7 | + (attrs || {}).each do |k, v| | |
8 | + public_send "#{k}=", v | |
9 | + end | |
10 | + end | |
11 | + | |
12 | + def draft=(draft) | |
13 | + draft.kind_of?(Draft) or theme = Draft.find(draft) | |
14 | + %i(name author url).each do |attr| | |
15 | + self.public_send "#{attr}=", draft.public_send(attr) | |
16 | + end | |
17 | + self.day_frame = draft.read_attribute_before_type_cast(:day_frame) | |
18 | + draft | |
19 | + end | |
20 | + alias_method :draft_id=, :draft= | |
21 | + | |
22 | + def theme=(theme) | |
23 | + theme.kind_of?(Theme) or theme = Theme.find(theme) | |
24 | + %i(id name author url license short_desc).each do |attr| | |
25 | + self.public_send "#{attr}=", theme.public_send(attr) | |
26 | + end | |
27 | + self.day_frame = theme.read_attribute_before_type_cast(:day_frame) | |
28 | + theme | |
29 | + end | |
30 | + alias_method :theme_id=, :theme= | |
31 | + | |
32 | + def as_json(opts = {}) | |
33 | + ret = { | |
34 | + schema_version: 1, | |
35 | + } | |
36 | + %i(id name author url short_desc day_frame).each do |a| | |
37 | + ret[a] = public_send(a) | |
38 | + end | |
39 | + ret.stringify_keys | |
40 | + end | |
41 | +end |
@@ -5,11 +5,11 @@ | ||
5 | 5 | root_path, class: "navbar-brand" |
6 | 6 | .collapse.navbar-collapse#topnavbar-nav |
7 | 7 | %ul.navbar-nav.mr-auto |
8 | + %li.nav-item{class: controller_name == "themes" ? 'active' : ''} | |
9 | + = link_to t('activerecord.models.theme'), themes_path, class: 'nav-link' | |
8 | 10 | - if user_signed_in? |
9 | 11 | %li.nav-item.active |
10 | 12 | = link_to 'Signal', dist_signals_path, class: 'nav-link' |
11 | - - if false # signed_in? | |
12 | - = render "layouts/topnav" | |
13 | 13 | // %li.visible-sm= link_to t('logout'), logout_path |
14 | 14 | - else |
15 | 15 | // %li.visible-sm= link_to t('login'), login_path |
@@ -0,0 +1,15 @@ | ||
1 | += simple_form_for(@theme) do |f| | |
2 | + = f.error_notification | |
3 | + | |
4 | + .form-inputs | |
5 | + = f.input :name | |
6 | + = f.input :short_desc | |
7 | + = f.input :disabled | |
8 | + = f.input :author | |
9 | + = f.input :url | |
10 | + = f.input :license | |
11 | + = f.association :user | |
12 | + = f.input :allow_orig_dl | |
13 | + | |
14 | + .form-actions | |
15 | + = f.button :submit |
@@ -0,0 +1,2 @@ | ||
1 | +json.extract! theme, :id, :name, :short_desc, :disabled, :author, :url, :license, :user_id, :allow_orig_dl, :created_at, :updated_at | |
2 | +json.url theme_url(theme, format: :json) |
@@ -0,0 +1,7 @@ | ||
1 | +%h1 Editing theme | |
2 | + | |
3 | += render 'form' | |
4 | + | |
5 | += link_to 'Show', @theme | |
6 | +\| | |
7 | += link_to 'Back', themes_path |
@@ -0,0 +1,35 @@ | ||
1 | +%h1 Listing themes | |
2 | + | |
3 | +%table | |
4 | + %thead | |
5 | + %tr | |
6 | + %th Name | |
7 | + %th Short desc | |
8 | + %th Disabled | |
9 | + %th Author | |
10 | + %th url | |
11 | + %th License | |
12 | + %th User | |
13 | + %th Allow orig dl | |
14 | + %th | |
15 | + %th | |
16 | + %th | |
17 | + | |
18 | + %tbody | |
19 | + - @themes.each do |theme| | |
20 | + %tr | |
21 | + %td= theme.name | |
22 | + %td= theme.short_desc | |
23 | + %td= theme.disabled | |
24 | + %td= theme.author | |
25 | + %td= theme.url | |
26 | + %td= theme.license | |
27 | + %td= theme.user | |
28 | + %td= theme.allow_orig_dl | |
29 | + %td= link_to 'Show', theme | |
30 | + %td= link_to 'Edit', edit_theme_path(theme) | |
31 | + %td= link_to 'Destroy', theme, method: :delete, data: { confirm: 'Are you sure?' } | |
32 | + | |
33 | +%br | |
34 | + | |
35 | += link_to 'New Theme', new_theme_path |
@@ -0,0 +1 @@ | ||
1 | +json.array! @themes, partial: 'themes/theme', as: :theme |
@@ -0,0 +1,5 @@ | ||
1 | +%h1 New theme | |
2 | + | |
3 | += render 'form' | |
4 | + | |
5 | += link_to 'Back', themes_path |
@@ -0,0 +1,30 @@ | ||
1 | +%p#notice= notice | |
2 | + | |
3 | +%p | |
4 | + %b Name: | |
5 | + = @theme.name | |
6 | +%p | |
7 | + %b Short desc: | |
8 | + = @theme.short_desc | |
9 | +%p | |
10 | + %b Disabled: | |
11 | + = @theme.disabled | |
12 | +%p | |
13 | + %b Author: | |
14 | + = @theme.author | |
15 | +%p | |
16 | + %b url: | |
17 | + = @theme.url | |
18 | +%p | |
19 | + %b License: | |
20 | + = @theme.license | |
21 | +%p | |
22 | + %b User: | |
23 | + = @theme.user | |
24 | +%p | |
25 | + %b Allow orig dl: | |
26 | + = @theme.allow_orig_dl | |
27 | + | |
28 | += link_to 'Edit', edit_theme_path(@theme) | |
29 | +\| | |
30 | += link_to 'Back', themes_path |
@@ -0,0 +1 @@ | ||
1 | +json.partial! "themes/theme", theme: @theme |
@@ -31,6 +31,11 @@ module MmwPsh | ||
31 | 31 | g.fixture_replacement :factory_girl, dir: "spec/factories" |
32 | 32 | end |
33 | 33 | |
34 | + config.action_controller.default_url_options = | |
35 | + config.action_mailer.default_url_options = { | |
36 | + protocol: 'http', host: 'localhost', port: 3000, | |
37 | + } | |
38 | + | |
34 | 39 | config.i18n.default_locale = :en |
35 | 40 | config.i18n.available_locales = [:en, :ja] |
36 | 41 | config.i18n.enforce_available_locales = true |
@@ -40,3 +45,7 @@ module MmwPsh | ||
40 | 45 | config.hub_secrets = {} |
41 | 46 | end |
42 | 47 | end |
48 | + | |
49 | +Rails.application.routes.default_url_options = { | |
50 | + protocol: 'http', host: 'localhost', port: 3000, | |
51 | +} |
@@ -1,6 +1,7 @@ | ||
1 | 1 | en: |
2 | 2 | activerecord: |
3 | 3 | models: |
4 | + theme: Theme | |
4 | 5 | attributes: |
5 | 6 | |
6 | 7 | drafts: |
@@ -1,7 +1,9 @@ | ||
1 | 1 | ja: |
2 | 2 | activerecord: |
3 | 3 | models: |
4 | + theme: テーマ | |
4 | 5 | attributes: |
6 | + | |
5 | 7 | |
6 | 8 | drafts: |
7 | 9 | show: |
@@ -1,4 +1,5 @@ | ||
1 | 1 | Rails.application.routes.draw do |
2 | + resources :themes | |
2 | 3 | namespace :api, defaults: {format: :json} do |
3 | 4 | namespace :v1 do |
4 | 5 | get 'forecasts/:area_ns/:area_code', to: 'forecasts#show', as: :forecasts |
@@ -0,0 +1,28 @@ | ||
1 | +class CreateThemes < ActiveRecord::Migration[5.1] | |
2 | + def change | |
3 | + create_table :themes do |t| | |
4 | + t.string :name | |
5 | + t.text :short_desc | |
6 | + t.boolean :disabled, default: false, null: false | |
7 | + t.string :author | |
8 | + t.text :url | |
9 | + t.string :license, null: false | |
10 | + t.string :day_frame | |
11 | + t.references :user | |
12 | + t.boolean :allow_orig_dl, default: true, null: false | |
13 | + t.integer :revision, default: 1, null: false | |
14 | + | |
15 | + t.timestamps | |
16 | + | |
17 | + t.attachment :preview1 | |
18 | + t.attachment :preview2 | |
19 | + t.attachment :preview3 | |
20 | + t.attachment :theme_archive | |
21 | + t.string :theme_archive_fingerprint | |
22 | + t.attachment :orig_archive | |
23 | + t.string :orig_archive_fingerprint | |
24 | + | |
25 | + t.index :created_at | |
26 | + end | |
27 | + end | |
28 | +end |
@@ -0,0 +1,5 @@ | ||
1 | +class AddAuthorToDraft < ActiveRecord::Migration[5.1] | |
2 | + def change | |
3 | + add_column :drafts, :author, :string | |
4 | + end | |
5 | +end |
@@ -10,7 +10,7 @@ | ||
10 | 10 | # |
11 | 11 | # It's strongly recommended that you check this file into your version control system. |
12 | 12 | |
13 | -ActiveRecord::Schema.define(version: 20170807093054) do | |
13 | +ActiveRecord::Schema.define(version: 20170813041825) do | |
14 | 14 | |
15 | 15 | create_table "areas", force: :cascade do |t| |
16 | 16 | t.string "ns" |
@@ -195,6 +195,7 @@ ActiveRecord::Schema.define(version: 20170807093054) do | ||
195 | 195 | t.string "wi_tc_content_type" |
196 | 196 | t.integer "wi_tc_file_size" |
197 | 197 | t.datetime "wi_tc_updated_at" |
198 | + t.string "author" | |
198 | 199 | t.index ["key"], name: "index_drafts_on_key", unique: true |
199 | 200 | t.index ["user_id"], name: "index_drafts_on_user_id" |
200 | 201 | end |
@@ -215,6 +216,45 @@ ActiveRecord::Schema.define(version: 20170807093054) do | ||
215 | 216 | t.index ["area_id"], name: "index_forecasts_on_area_id" |
216 | 217 | end |
217 | 218 | |
219 | + create_table "themes", force: :cascade do |t| | |
220 | + t.string "name" | |
221 | + t.text "short_desc" | |
222 | + t.boolean "disabled", default: false, null: false | |
223 | + t.string "author" | |
224 | + t.text "url" | |
225 | + t.string "license", null: false | |
226 | + t.string "day_frame" | |
227 | + t.integer "user_id" | |
228 | + t.boolean "allow_orig_dl", default: true, null: false | |
229 | + t.integer "revision", default: 1, null: false | |
230 | + t.datetime "created_at", null: false | |
231 | + t.datetime "updated_at", null: false | |
232 | + t.string "preview1_file_name" | |
233 | + t.string "preview1_content_type" | |
234 | + t.integer "preview1_file_size" | |
235 | + t.datetime "preview1_updated_at" | |
236 | + t.string "preview2_file_name" | |
237 | + t.string "preview2_content_type" | |
238 | + t.integer "preview2_file_size" | |
239 | + t.datetime "preview2_updated_at" | |
240 | + t.string "preview3_file_name" | |
241 | + t.string "preview3_content_type" | |
242 | + t.integer "preview3_file_size" | |
243 | + t.datetime "preview3_updated_at" | |
244 | + t.string "theme_archive_file_name" | |
245 | + t.string "theme_archive_content_type" | |
246 | + t.integer "theme_archive_file_size" | |
247 | + t.datetime "theme_archive_updated_at" | |
248 | + t.string "theme_archive_fingerprint" | |
249 | + t.string "orig_archive_file_name" | |
250 | + t.string "orig_archive_content_type" | |
251 | + t.integer "orig_archive_file_size" | |
252 | + t.datetime "orig_archive_updated_at" | |
253 | + t.string "orig_archive_fingerprint" | |
254 | + t.index ["created_at"], name: "index_themes_on_created_at" | |
255 | + t.index ["user_id"], name: "index_themes_on_user_id" | |
256 | + end | |
257 | + | |
218 | 258 | create_table "users", force: :cascade do |t| |
219 | 259 | t.string "name" |
220 | 260 | t.string "lang" |
@@ -0,0 +1,141 @@ | ||
1 | +require 'rails_helper' | |
2 | + | |
3 | +# This spec was generated by rspec-rails when you ran the scaffold generator. | |
4 | +# It demonstrates how one might use RSpec to specify the controller code that | |
5 | +# was generated by Rails when you ran the scaffold generator. | |
6 | +# | |
7 | +# It assumes that the implementation code is generated by the rails scaffold | |
8 | +# generator. If you are using any extension libraries to generate different | |
9 | +# controller code, this generated spec may or may not pass. | |
10 | +# | |
11 | +# It only uses APIs available in rails and/or rspec-rails. There are a number | |
12 | +# of tools you can use to make these specs even more expressive, but we're | |
13 | +# sticking to rails and rspec-rails APIs to keep things simple and stable. | |
14 | +# | |
15 | +# Compared to earlier versions of this generator, there is very limited use of | |
16 | +# stubs and message expectations in this spec. Stubs are only used when there | |
17 | +# is no simpler way to get a handle on the object needed for the example. | |
18 | +# Message expectations are only used when there is no simpler way to specify | |
19 | +# that an instance is receiving a specific message. | |
20 | +# | |
21 | +# Also compared to earlier versions of this generator, there are no longer any | |
22 | +# expectations of assigns and templates rendered. These features have been | |
23 | +# removed from Rails core in Rails 5, but can be added back in via the | |
24 | +# `rails-controller-testing` gem. | |
25 | + | |
26 | +RSpec.describe ThemesController, type: :controller do | |
27 | + | |
28 | + # This should return the minimal set of attributes required to create a valid | |
29 | + # Theme. As you add validations to Theme, be sure to | |
30 | + # adjust the attributes here as well. | |
31 | + let(:valid_attributes) { | |
32 | + skip("Add a hash of attributes valid for your model") | |
33 | + } | |
34 | + | |
35 | + let(:invalid_attributes) { | |
36 | + skip("Add a hash of attributes invalid for your model") | |
37 | + } | |
38 | + | |
39 | + # This should return the minimal set of values that should be in the session | |
40 | + # in order to pass any filters (e.g. authentication) defined in | |
41 | + # ThemesController. Be sure to keep this updated too. | |
42 | + let(:valid_session) { {} } | |
43 | + | |
44 | + describe "GET #index" do | |
45 | + it "returns a success response" do | |
46 | + theme = Theme.create! valid_attributes | |
47 | + get :index, params: {}, session: valid_session | |
48 | + expect(response).to be_success | |
49 | + end | |
50 | + end | |
51 | + | |
52 | + describe "GET #show" do | |
53 | + it "returns a success response" do | |
54 | + theme = Theme.create! valid_attributes | |
55 | + get :show, params: {id: theme.to_param}, session: valid_session | |
56 | + expect(response).to be_success | |
57 | + end | |
58 | + end | |
59 | + | |
60 | + describe "GET #new" do | |
61 | + it "returns a success response" do | |
62 | + get :new, params: {}, session: valid_session | |
63 | + expect(response).to be_success | |
64 | + end | |
65 | + end | |
66 | + | |
67 | + describe "GET #edit" do | |
68 | + it "returns a success response" do | |
69 | + theme = Theme.create! valid_attributes | |
70 | + get :edit, params: {id: theme.to_param}, session: valid_session | |
71 | + expect(response).to be_success | |
72 | + end | |
73 | + end | |
74 | + | |
75 | + describe "POST #create" do | |
76 | + context "with valid params" do | |
77 | + it "creates a new Theme" do | |
78 | + expect { | |
79 | + post :create, params: {theme: valid_attributes}, session: valid_session | |
80 | + }.to change(Theme, :count).by(1) | |
81 | + end | |
82 | + | |
83 | + it "redirects to the created theme" do | |
84 | + post :create, params: {theme: valid_attributes}, session: valid_session | |
85 | + expect(response).to redirect_to(Theme.last) | |
86 | + end | |
87 | + end | |
88 | + | |
89 | + context "with invalid params" do | |
90 | + it "returns a success response (i.e. to display the 'new' template)" do | |
91 | + post :create, params: {theme: invalid_attributes}, session: valid_session | |
92 | + expect(response).to be_success | |
93 | + end | |
94 | + end | |
95 | + end | |
96 | + | |
97 | + describe "PUT #update" do | |
98 | + context "with valid params" do | |
99 | + let(:new_attributes) { | |
100 | + skip("Add a hash of attributes valid for your model") | |
101 | + } | |
102 | + | |
103 | + it "updates the requested theme" do | |
104 | + theme = Theme.create! valid_attributes | |
105 | + put :update, params: {id: theme.to_param, theme: new_attributes}, session: valid_session | |
106 | + theme.reload | |
107 | + skip("Add assertions for updated state") | |
108 | + end | |
109 | + | |
110 | + it "redirects to the theme" do | |
111 | + theme = Theme.create! valid_attributes | |
112 | + put :update, params: {id: theme.to_param, theme: valid_attributes}, session: valid_session | |
113 | + expect(response).to redirect_to(theme) | |
114 | + end | |
115 | + end | |
116 | + | |
117 | + context "with invalid params" do | |
118 | + it "returns a success response (i.e. to display the 'edit' template)" do | |
119 | + theme = Theme.create! valid_attributes | |
120 | + put :update, params: {id: theme.to_param, theme: invalid_attributes}, session: valid_session | |
121 | + expect(response).to be_success | |
122 | + end | |
123 | + end | |
124 | + end | |
125 | + | |
126 | + describe "DELETE #destroy" do | |
127 | + it "destroys the requested theme" do | |
128 | + theme = Theme.create! valid_attributes | |
129 | + expect { | |
130 | + delete :destroy, params: {id: theme.to_param}, session: valid_session | |
131 | + }.to change(Theme, :count).by(-1) | |
132 | + end | |
133 | + | |
134 | + it "redirects to the themes list" do | |
135 | + theme = Theme.create! valid_attributes | |
136 | + delete :destroy, params: {id: theme.to_param}, session: valid_session | |
137 | + expect(response).to redirect_to(themes_url) | |
138 | + end | |
139 | + end | |
140 | + | |
141 | +end |
@@ -0,0 +1,12 @@ | ||
1 | +FactoryGirl.define do | |
2 | + factory :theme do | |
3 | + name "MyString" | |
4 | + short_desc "MyText" | |
5 | + disabled false | |
6 | + author "MyString" | |
7 | + url "MyText" | |
8 | + license "MyString" | |
9 | + user nil | |
10 | + allow_orig_dl false | |
11 | + end | |
12 | +end |
@@ -0,0 +1,5 @@ | ||
1 | +require 'rails_helper' | |
2 | + | |
3 | +RSpec.describe Theme, type: :model do | |
4 | + pending "add some examples to (or delete) #{__FILE__}" | |
5 | +end |
@@ -0,0 +1,39 @@ | ||
1 | +require "rails_helper" | |
2 | + | |
3 | +RSpec.describe ThemesController, type: :routing do | |
4 | + describe "routing" do | |
5 | + | |
6 | + it "routes to #index" do | |
7 | + expect(:get => "/themes").to route_to("themes#index") | |
8 | + end | |
9 | + | |
10 | + it "routes to #new" do | |
11 | + expect(:get => "/themes/new").to route_to("themes#new") | |
12 | + end | |
13 | + | |
14 | + it "routes to #show" do | |
15 | + expect(:get => "/themes/1").to route_to("themes#show", :id => "1") | |
16 | + end | |
17 | + | |
18 | + it "routes to #edit" do | |
19 | + expect(:get => "/themes/1/edit").to route_to("themes#edit", :id => "1") | |
20 | + end | |
21 | + | |
22 | + it "routes to #create" do | |
23 | + expect(:post => "/themes").to route_to("themes#create") | |
24 | + end | |
25 | + | |
26 | + it "routes to #update via PUT" do | |
27 | + expect(:put => "/themes/1").to route_to("themes#update", :id => "1") | |
28 | + end | |
29 | + | |
30 | + it "routes to #update via PATCH" do | |
31 | + expect(:patch => "/themes/1").to route_to("themes#update", :id => "1") | |
32 | + end | |
33 | + | |
34 | + it "routes to #destroy" do | |
35 | + expect(:delete => "/themes/1").to route_to("themes#destroy", :id => "1") | |
36 | + end | |
37 | + | |
38 | + end | |
39 | +end |
@@ -0,0 +1,9 @@ | ||
1 | +require "application_system_test_case" | |
2 | + | |
3 | +class ThemesTest < ApplicationSystemTestCase | |
4 | + # test "visiting the index" do | |
5 | + # visit themes_url | |
6 | + # | |
7 | + # assert_selector "h1", text: "Theme" | |
8 | + # end | |
9 | +end |