• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
Aucun tag

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

Commit MetaInfo

Révision6795717c3801cc4d3503eeca5eff8ee2f775f65b (tree)
l'heure2017-08-14 03:00:50
AuteurHMML <hmml3939@gmai...>
CommiterHMML

Message de Log

Add theme class (WIP).

Change Summary

Modification

--- a/.gitignore
+++ b/.gitignore
@@ -24,6 +24,7 @@
2424 /yarn-error.log
2525 /public/packs
2626 /public/system
27+/private
2728
2829 /.vagrant
2930 /erd.*
--- a/Gemfile
+++ b/Gemfile
@@ -57,6 +57,8 @@ gem 'daemons'
5757 gem 'exception_notification', group: :production
5858 gem 'paperclip'
5959 gem 'rqrcode', github: 'sugi/rqrcode', branch: 'inline-svg'
60+gem 'rubyzip', '>= 1.0.0', require: 'zip'
61+#gem 'counter_culture', '~> 1.0'
6062
6163 group :development, :test do
6264 # Call 'byebug' anywhere in the code to stop execution and get a debugger console
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -472,6 +472,7 @@ DEPENDENCIES
472472 responders
473473 rqrcode!
474474 rspec-rails
475+ rubyzip (>= 1.0.0)
475476 sass-rails (~> 5.0)
476477 sdoc (~> 0.4.0)
477478 selenium-webdriver
--- /dev/null
+++ b/app/assets/javascripts/themes.coffee
@@ -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/
--- /dev/null
+++ b/app/assets/stylesheets/themes.scss
@@ -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/
--- /dev/null
+++ b/app/controllers/themes_controller.rb
@@ -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
--- /dev/null
+++ b/app/helpers/themes_helper.rb
@@ -0,0 +1,2 @@
1+module ThemesHelper
2+end
--- a/app/models/application_record.rb
+++ b/app/models/application_record.rb
@@ -1,3 +1,10 @@
1+require 'fileutils'
12 class ApplicationRecord < ActiveRecord::Base
23 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
310 end
--- a/app/models/draft.rb
+++ b/app/models/draft.rb
@@ -31,7 +31,7 @@ class Draft < ApplicationRecord
3131 belongs_to :user, required: false
3232 before_save :renew_expire
3333 after_initialize :set_key
34- validates :title, :url, length: { maximum: 255 }
34+ validates :title, length: { maximum: 60 }
3535 validates :url, format: { with: %r{\Ahttps?://[a-z0-9-]+(\.[a-z0-9-]+){1,}/}i }, allow_blank: true
3636 validates :key, uniqueness: true
3737
@@ -48,6 +48,10 @@ class Draft < ApplicationRecord
4848 size: { less_than: 20.megabyte }
4949 end
5050
51+ def name
52+ title
53+ end
54+
5155 def renew_expire
5256 self.expires_at = Time.now + EXPIRES_IN
5357 end
@@ -66,6 +70,35 @@ class Draft < ApplicationRecord
6670 key
6771 end
6872
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+
69102 def as_json(opts = {})
70103 ret = super(opts)
71104 ret["path"] = Rails.application.routes.url_helpers.draft_path(self, format: :json)
--- /dev/null
+++ b/app/models/theme.rb
@@ -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
--- /dev/null
+++ b/app/models/theme_definition.rb
@@ -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
--- a/app/views/layouts/_topnav.html.haml
+++ b/app/views/layouts/_topnav.html.haml
@@ -5,11 +5,11 @@
55 root_path, class: "navbar-brand"
66 .collapse.navbar-collapse#topnavbar-nav
77 %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'
810 - if user_signed_in?
911 %li.nav-item.active
1012 = link_to 'Signal', dist_signals_path, class: 'nav-link'
11- - if false # signed_in?
12- = render "layouts/topnav"
1313 // %li.visible-sm= link_to t('logout'), logout_path
1414 - else
1515 // %li.visible-sm= link_to t('login'), login_path
--- /dev/null
+++ b/app/views/themes/_form.html.haml
@@ -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
--- /dev/null
+++ b/app/views/themes/_theme.json.jbuilder
@@ -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)
--- /dev/null
+++ b/app/views/themes/edit.html.haml
@@ -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
--- /dev/null
+++ b/app/views/themes/index.html.haml
@@ -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
--- /dev/null
+++ b/app/views/themes/index.json.jbuilder
@@ -0,0 +1 @@
1+json.array! @themes, partial: 'themes/theme', as: :theme
--- /dev/null
+++ b/app/views/themes/new.html.haml
@@ -0,0 +1,5 @@
1+%h1 New theme
2+
3+= render 'form'
4+
5+= link_to 'Back', themes_path
--- /dev/null
+++ b/app/views/themes/show.html.haml
@@ -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
--- /dev/null
+++ b/app/views/themes/show.json.jbuilder
@@ -0,0 +1 @@
1+json.partial! "themes/theme", theme: @theme
--- a/config/application.rb
+++ b/config/application.rb
@@ -31,6 +31,11 @@ module MmwPsh
3131 g.fixture_replacement :factory_girl, dir: "spec/factories"
3232 end
3333
34+ config.action_controller.default_url_options =
35+ config.action_mailer.default_url_options = {
36+ protocol: 'http', host: 'localhost', port: 3000,
37+ }
38+
3439 config.i18n.default_locale = :en
3540 config.i18n.available_locales = [:en, :ja]
3641 config.i18n.enforce_available_locales = true
@@ -40,3 +45,7 @@ module MmwPsh
4045 config.hub_secrets = {}
4146 end
4247 end
48+
49+Rails.application.routes.default_url_options = {
50+ protocol: 'http', host: 'localhost', port: 3000,
51+}
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -1,6 +1,7 @@
11 en:
22 activerecord:
33 models:
4+ theme: Theme
45 attributes:
56
67 drafts:
--- a/config/locales/ja.yml
+++ b/config/locales/ja.yml
@@ -1,7 +1,9 @@
11 ja:
22 activerecord:
33 models:
4+ theme: テーマ
45 attributes:
6+
57
68 drafts:
79 show:
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,4 +1,5 @@
11 Rails.application.routes.draw do
2+ resources :themes
23 namespace :api, defaults: {format: :json} do
34 namespace :v1 do
45 get 'forecasts/:area_ns/:area_code', to: 'forecasts#show', as: :forecasts
--- /dev/null
+++ b/db/migrate/20170811160939_create_themes.rb
@@ -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
--- /dev/null
+++ b/db/migrate/20170813041825_add_author_to_draft.rb
@@ -0,0 +1,5 @@
1+class AddAuthorToDraft < ActiveRecord::Migration[5.1]
2+ def change
3+ add_column :drafts, :author, :string
4+ end
5+end
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
1010 #
1111 # It's strongly recommended that you check this file into your version control system.
1212
13-ActiveRecord::Schema.define(version: 20170807093054) do
13+ActiveRecord::Schema.define(version: 20170813041825) do
1414
1515 create_table "areas", force: :cascade do |t|
1616 t.string "ns"
@@ -195,6 +195,7 @@ ActiveRecord::Schema.define(version: 20170807093054) do
195195 t.string "wi_tc_content_type"
196196 t.integer "wi_tc_file_size"
197197 t.datetime "wi_tc_updated_at"
198+ t.string "author"
198199 t.index ["key"], name: "index_drafts_on_key", unique: true
199200 t.index ["user_id"], name: "index_drafts_on_user_id"
200201 end
@@ -215,6 +216,45 @@ ActiveRecord::Schema.define(version: 20170807093054) do
215216 t.index ["area_id"], name: "index_forecasts_on_area_id"
216217 end
217218
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+
218258 create_table "users", force: :cascade do |t|
219259 t.string "name"
220260 t.string "lang"
--- /dev/null
+++ b/spec/controllers/themes_controller_spec.rb
@@ -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
--- /dev/null
+++ b/spec/factories/themes.rb
@@ -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
--- /dev/null
+++ b/spec/models/theme_spec.rb
@@ -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
--- /dev/null
+++ b/spec/routing/themes_routing_spec.rb
@@ -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
--- /dev/null
+++ b/test/system/themes_test.rb
@@ -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