days 0.2.0 → 1.0.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +21 -4
  3. data/app/javascripts/admin/bootstrap.min.js +7 -0
  4. data/app/javascripts/jquery-2.1.3.min.js +4 -0
  5. data/app/stylesheets/admin/bootstrap-theme.min.css +5 -0
  6. data/app/stylesheets/admin/bootstrap.min.css +5 -0
  7. data/app/stylesheets/admin/login.scss +3 -5
  8. data/app/stylesheets/admin.scss +4 -0
  9. data/app/views/admin/categories.haml +3 -3
  10. data/app/views/admin/entries/form.haml +22 -17
  11. data/app/views/admin/entries/index.haml +46 -28
  12. data/app/views/admin/login.haml +11 -8
  13. data/app/views/admin/setup.haml +16 -9
  14. data/app/views/admin.haml +31 -21
  15. data/days.gemspec +14 -11
  16. data/lib/days/app/admin/entries.rb +11 -5
  17. data/lib/days/app/entries.rb +24 -13
  18. data/lib/days/app.rb +2 -3
  19. data/lib/days/command.rb +1 -1
  20. data/lib/days/config.rb +18 -5
  21. data/lib/days/helpers.rb +13 -11
  22. data/lib/days/models/base.rb +11 -0
  23. data/lib/days/models/category.rb +2 -2
  24. data/lib/days/models/entry.rb +41 -8
  25. data/lib/days/models/user.rb +2 -2
  26. data/lib/days/version.rb +1 -1
  27. data/scripts/tumblr_export.rb +1 -1
  28. data/spec/controllers/admin/categories_spec.rb +22 -22
  29. data/spec/controllers/admin/entries_spec.rb +155 -44
  30. data/spec/controllers/admin/session_spec.rb +16 -25
  31. data/spec/controllers/admin/setup_spec.rb +22 -25
  32. data/spec/controllers/admin/users_spec.rb +39 -40
  33. data/spec/controllers/entries_spec.rb +71 -42
  34. data/spec/helpers_spec.rb +18 -29
  35. data/spec/models/entry_spec.rb +117 -47
  36. data/spec/shared/admin.rb +2 -2
  37. data/spec/spec_helper.rb +25 -25
  38. metadata +111 -86
  39. data/app/javascripts/bootstrap.js +0 -2159
  40. data/app/javascripts/bootstrap.min.js +0 -6
  41. data/app/javascripts/jquery-1.8.3.min.js +0 -2
  42. data/app/stylesheets/bootstrap-responsive.css +0 -1092
  43. data/app/stylesheets/bootstrap-responsive.min.css +0 -9
  44. data/app/stylesheets/bootstrap.css +0 -6039
  45. data/app/stylesheets/bootstrap.min.css +0 -9
data/app/views/admin.haml CHANGED
@@ -3,35 +3,45 @@
3
3
  %head
4
4
  %meta{charset: 'UTF-8'}
5
5
  %meta{name: "viewport", content: "width=device-width, initial-scale=1.0"}
6
- %link{href: "/assets/bootstrap.min.css", rel: "stylesheet"}
6
+ %link{href: "/assets/admin/bootstrap.min.css", rel: "stylesheet"}
7
7
  %link{href: "/assets/admin.css", rel: "stylesheet", media: "screen"}
8
- %link{href: "/assets/bootstrap-responsive.min.css", rel: "stylesheet"}
9
- %script{src: '/assets/jquery-1.8.3.min.js'}
10
- %script{src: '/assets/bootstrap.min.js'}
8
+ %script{src: '/assets/jquery-2.1.3.min.js'}
9
+ %script{src: '/assets/admin/bootstrap.min.js'}
11
10
  - if @title
12
11
  %title #{@title} - Days Admin
13
12
  - else
14
13
  %title Days Admin
15
14
  %body
16
- .navbar.navbar-inverse.navbar-fixed-top
17
- .navbar-inner
18
- .container
19
- %a.btn.btn-navbar{data: {toggle: 'collapse', target: '.nav-collapse'}}
15
+ %nav.navbar.navbar-default.navbar-fixed-top
16
+ .container
17
+ .navbar-header
18
+ %button.navbar-toggle.collapsed{type: 'button', data: {toggle: 'collapse', target: '#navbar-collapse-1'}}
19
+ %span.sr-only Toggle navigation
20
20
  %span.icon-bar
21
21
  %span.icon-bar
22
22
  %span.icon-bar
23
- %a.brand{href: '/admin/'} Days
24
- %form.navbar-form.pull-right{action: "/admin/logout", method: "POST"}
25
- != csrf_tag
26
- %button.btn.btn-link{type: 'submit'} Log out
27
- %a.btn.btn-primary{href: '/admin/entries/new'} New Entry
28
23
 
29
- %div.nav-collapse.collapse
30
- %ul.nav
31
- %li
32
- %a{href: '/admin/entries'} Entries
33
- %li
34
- %a{href: '/admin/categories'} Categories
35
- %li
36
- %a{href: '/admin/users'} Users
24
+ %a.navbar-brand{href: '/admin/'} Days
25
+
26
+ %form.navbar-form.navbar-right.hidden-xs{action: "/admin/logout", method: "POST"}
27
+ != csrf_tag
28
+ %button.btn.btn-link{type: 'submit'} Log out
29
+ %a.btn.btn-default{href: '/admin/entries/new'} New Entry
30
+
31
+ %div.collapse.navbar-collapse#navbar-collapse-1
32
+ %ul.nav.navbar-nav
33
+ %li.visible-xs
34
+ %form
35
+ %a.btn.btn-default.visible-xs{href: '/admin/entries/new'} New Entry
36
+ %li
37
+ %a{href: '/admin/entries'} Entries
38
+ %li
39
+ %a{href: '/admin/categories'} Categories
40
+ %li
41
+ %a{href: '/admin/users'} Users
42
+ %li.visible-xs
43
+ %form.form-inline{action: "/admin/logout", method: "POST"}
44
+ != csrf_tag
45
+ %button.btn.btn-link{type: 'submit'} Log out
46
+
37
47
  != yield
data/days.gemspec CHANGED
@@ -17,31 +17,34 @@ Gem::Specification.new do |gem|
17
17
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
18
  gem.require_paths = ["lib"]
19
19
 
20
- gem.add_dependency "sinatra", '~> 1.3.3'
20
+ gem.add_dependency "sinatra", '>= 1.4.5'
21
21
  gem.add_dependency "thor", '~> 0.16.0'
22
- gem.add_dependency "rack_csrf", '~> 2.4.0'
22
+ gem.add_dependency "rack_csrf", '~> 2.5.0'
23
23
 
24
24
  gem.add_dependency "settingslogic", '~> 2.0.9'
25
25
 
26
- gem.add_dependency "sprockets", '~> 2.2.2'
27
- gem.add_dependency "haml", '~> 3.1.7'
26
+ gem.add_dependency "sprockets", '~> 2.12.3'
27
+ gem.add_dependency "faml", '>= 0.2.4'
28
28
  gem.add_dependency "sass", '~> 3.2.5'
29
29
 
30
- gem.add_dependency "redcarpet", '~> 2.2.2'
31
- gem.add_dependency "builder", '~> 3.0.0'
30
+ gem.add_dependency "builder", '~> 3.1'
32
31
 
33
- gem.add_dependency "activerecord", "~> 3.2.14"
34
- gem.add_dependency "kaminari", "~> 0.13"
32
+ gem.add_dependency "activerecord", "~> 4.2.0"
33
+ gem.add_dependency "protected_attributes"
34
+ gem.add_dependency "kaminari", "~> 0.16.1"
35
35
  gem.add_dependency "padrino-helpers", '~> 0.9.21'
36
36
  gem.add_dependency "stringex", '~> 1.5.1'
37
- gem.add_dependency "bcrypt-ruby", '~> 3.0.1'
37
+ gem.add_dependency "bcrypt", '~> 3.1.9'
38
+
39
+ gem.add_dependency "html-pipeline", '>= 1.11.0'
40
+ gem.add_dependency "github-markdown"
38
41
 
39
42
  gem.add_development_dependency "sqlite3"
40
43
 
41
- gem.add_development_dependency "rspec"
44
+ gem.add_development_dependency "rspec", '~> 3.2.0'
42
45
  gem.add_development_dependency "rack-test"
43
46
  gem.add_development_dependency "fuubar"
47
+ gem.add_development_dependency "database_rewinder"
44
48
 
45
49
  gem.add_dependency "pry"
46
- gem.add_development_dependency "pry-nav"
47
50
  end
@@ -1,7 +1,11 @@
1
1
  module Days
2
2
  class App < Sinatra::Base
3
3
  get "/admin/entries", :admin_only => true do
4
- @entries = Entry.order('id DESC').all
4
+ @entries = Entry.order(id: :desc)
5
+ @entries = @entries.draft if params[:draft] && !params[:draft].empty?
6
+ @entries = @entries.scheduled if params[:scheduled] && !params[:scheduled].empty?
7
+ @entries = @entries.published if params[:published] && !params[:published].empty?
8
+ @entries = @entries.page(params[:page] || 1)
5
9
  haml :'admin/entries/index', layout: :admin
6
10
  end
7
11
 
@@ -22,6 +26,7 @@ module Days
22
26
 
23
27
  @entry = Entry.new(entry)
24
28
  @entry.user = current_user
29
+ @entry.pipeline = config.html_pipeline if config.html_pipeline
25
30
 
26
31
  if @entry.save
27
32
  redirect "/admin/entries/#{@entry.id}" # FIXME: Permalink
@@ -36,19 +41,20 @@ module Days
36
41
  end
37
42
 
38
43
  get "/admin/entries/:id", :admin_only => true do
39
- @entry = Entry.where(id: params[:id]).first || halt(404)
44
+ @entry = Entry.find_by(id: params[:id]) || halt(404)
40
45
  @categories = Category.all
41
46
  haml :'admin/entries/form', layout: :admin
42
47
  end
43
48
 
44
49
  put "/admin/entries/:id", :admin_only => true do
45
50
  entry = params[:entry] || halt(400)
46
- @entry = Entry.where(id: params[:id]).first || halt(404)
51
+ @entry = Entry.find_by(id: params[:id]) || halt(404)
52
+ @entry.pipeline = config.html_pipeline if config.html_pipeline
47
53
 
48
54
  entry[:categories] = Category.where(
49
55
  id: (entry[:categories] || {}).keys.map(&:to_i)
50
56
  )
51
- @entry.update_attributes(entry)
57
+ @entry.assign_attributes(entry)
52
58
 
53
59
  if @entry.save
54
60
  redirect "/admin/entries/#{@entry.id}"
@@ -60,7 +66,7 @@ module Days
60
66
  end
61
67
 
62
68
  delete "/admin/entries/:id", :admin_only => true do
63
- @entry = Entry.where(id: params[:id]).first || halt(404)
69
+ @entry = Entry.find_by(id: params[:id]) || halt(404)
64
70
  @entry.destroy
65
71
 
66
72
  redirect "/admin/entries"
@@ -20,7 +20,7 @@ module Days
20
20
  end
21
21
  end
22
22
 
23
- entry = Entry.where(old_path: request.path).first
23
+ entry = Entry.find_by(old_path: request.path)
24
24
  if entry
25
25
  return [301, {'Location' => entry_path(entry)}, ""]
26
26
  end
@@ -32,7 +32,7 @@ module Days
32
32
  end
33
33
 
34
34
  get '/category/:name' do
35
- category = Category.where(name: params[:name]).first || halt(404)
35
+ category = Category.find_by(name: params[:name]) || halt(404)
36
36
  @entries = category.entries.published.page(params[:page] || 1)
37
37
  haml :entries
38
38
  end
@@ -50,20 +50,15 @@ module Days
50
50
  haml :entries
51
51
  end
52
52
 
53
- get '/feed' do
54
- content_type 'application/atom+xml'
55
- entries = Entry.published.first(50)
56
-
53
+ private def generate_atom_feed(entries, title: config.title, html_path: '/feed')
57
54
  xml = Builder::XmlMarkup.new
58
-
59
55
  xml.instruct!
60
-
61
56
  xml.feed("xmlns" => 'http://www.w3.org/2005/Atom') do
62
57
  xml.id("tag:#{request.host},2005:#{request.fullpath.split(".")[0]}")
63
58
 
64
- xml.link(:rel => 'alternate', :type => 'text/html', :href => request.url.gsub(/feed$/,''))
59
+ xml.link(:rel => 'alternate', :type => 'text/html', :href => [request.base_url, config.base_path, html_path].join.gsub(%r{//}, '/'))
65
60
  xml.link(:rel => 'self', :type => 'application/atom+xml', :href => request.url)
66
- xml.title config.title
61
+ xml.title title
67
62
 
68
63
  xml.updated(entries.map(&:updated_at).max)
69
64
 
@@ -74,14 +69,30 @@ module Days
74
69
  xml.published entry.published_at.xmlschema
75
70
  xml.updated entry.updated_at.xmlschema
76
71
 
77
- xml.link(rel: 'alternate', type: 'text/html', href: "#{request.url.gsub(/\/feed$/,'')}#{entry_path(entry)}")
78
-
79
72
  xml.title entry.title
80
73
 
81
- xml.content(entry.short_rendered { '... <a href="'+entry_path(entry)+'">Continue Reading</a>' }, type: 'html')
74
+ href = [request.base_url, config.base_path, entry_path(entry)].join.gsub(%r{//}, '/')
75
+ xml.link(rel: 'alternate', type: 'text/html', href: href)
76
+ xml.content(entry.short_rendered { '... <a href="'+href+'">Continue Reading</a>' }, type: 'html')
82
77
  end
83
78
  end
84
79
  end
85
80
  end
81
+
82
+ get '/feed' do
83
+ entries = Entry.published.page(params[:page])
84
+
85
+ content_type 'application/atom+xml'
86
+ generate_atom_feed(entries)
87
+ end
88
+
89
+ get '/feed/category/:name' do
90
+ category = Category.find_by(name: params[:name]) || halt(404)
91
+ entries = category.entries.published.page(params[:page])
92
+
93
+ content_type 'application/atom+xml'
94
+ generate_atom_feed(entries, title: "#{config.title} (Category: #{category.name})", html_path: "/category/#{category.name}")
95
+ end
96
+
86
97
  end
87
98
  end
data/lib/days/app.rb CHANGED
@@ -5,7 +5,7 @@ require 'rack/csrf'
5
5
  require_relative 'config'
6
6
  require_relative 'models'
7
7
  require_relative 'helpers'
8
- require 'haml'
8
+ require 'faml'
9
9
  require 'sass'
10
10
 
11
11
  I18n.load_path.reject! {|_| _.match(/padrino/) }
@@ -48,8 +48,6 @@ module Days
48
48
  set(:config, nil)
49
49
  set :method_override, true
50
50
 
51
- set :haml, :escape_html => true
52
-
53
51
  helpers Helpers
54
52
  helpers Kaminari::Helpers::SinatraHelpers
55
53
 
@@ -106,6 +104,7 @@ module Days
106
104
  env.append_path "#{self.root}/images"
107
105
  })
108
106
  config.establish_db_connection()
107
+ config.run_scripts()
109
108
  x
110
109
  end
111
110
  end
data/lib/days/command.rb CHANGED
@@ -55,7 +55,7 @@ module Days
55
55
  desc "server", "Starts the server"
56
56
  method_option :config, :type => :string, :aliases => "-c"
57
57
  method_option :port, :type => :numeric, :aliases => "-p", :default => 3162
58
- method_option :bind, :type => :string, :aliases => "-b", :default => nil
58
+ method_option :bind, :type => :string, :aliases => "-b", :default => 'localhost'
59
59
  method_option :environment, :type => :string, :aliases => "-e", :default => "development"
60
60
  method_option :pid, :type => :string, :aliases => "-c"
61
61
  def server
data/lib/days/config.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require_relative 'app'
2
- require 'active_record'
2
+ require 'days/models/base'
3
+ require 'html/pipeline'
3
4
  require 'logger'
4
5
  require 'settingslogic'
5
6
 
@@ -33,17 +34,29 @@ module Days
33
34
  end
34
35
  end
35
36
 
37
+ attr_accessor :html_pipeline
36
38
 
37
- def establish_db_connection(force=false)
39
+ def run_scripts
40
+ instance_eval (self[:script_lines] || []).join("\n")
41
+
42
+ (self[:scripts] || []).each do |_|
43
+ path = File.expand_path(_, self[:root])
44
+ instance_eval File.read(path), path, 1
45
+ end
46
+ end
47
+
48
+ def establish_db_connection(force=false, base: ActiveRecord::Base)
38
49
  if Days::App.environment.to_sym == :development && (self.has_key?(:activerecord_log) ? self.activerecord_log == true : true)
39
- ActiveRecord::Base.logger = Logger.new($stdout)
50
+ base.logger = Logger.new($stdout)
40
51
  end
41
52
 
53
+ base.default_timezone = self['database_timezone'] ? self['database_timezone'].to_sym : :local
54
+
42
55
  begin
43
56
  raise ActiveRecord::ConnectionNotEstablished if force
44
- return ActiveRecord::Base.connection
57
+ return base.connection
45
58
  rescue ActiveRecord::ConnectionNotEstablished
46
- ActiveRecord::Base.establish_connection(self['database'] ? Hash[self.database] : ENV["DATABASE_URL"])
59
+ base.establish_connection(self['database'] ? Hash[self.database] : ENV["DATABASE_URL"])
47
60
  retry
48
61
  end
49
62
  end
data/lib/days/helpers.rb CHANGED
@@ -38,8 +38,12 @@ module Days
38
38
  config.permalink.gsub(/{(\w+?)}/) { hash[$1.to_sym] }
39
39
  end
40
40
 
41
+ def self.lookup_entry_regexp_for(permalink_format)
42
+ (@lookup_entry_regexp_cache ||= {})[permalink_format] ||= Regexp.compile(Regexp.escape(permalink_format).gsub(/\\{(\w+?)\\}/) { "(?<#{$1}>.+?)" } + "$")
43
+ end
44
+
41
45
  def lookup_entry(path)
42
- regexp = Regexp.compile(Regexp.escape(config.permalink).gsub(/\\{(\w+?)\\}/) { "(?<#{$1}>.+?)" } + "$")
46
+ regexp = Helpers.lookup_entry_regexp_for(config.permalink)
43
47
  m = regexp.match(path)
44
48
  return nil unless m
45
49
 
@@ -48,27 +52,25 @@ module Days
48
52
  hash
49
53
  end
50
54
 
51
-
52
55
  if match[:id] || match[:slug]
53
56
  if match[:id]
54
- query = Entry.where(id: match[:id])
57
+ entry = Entry.find(match[:id])
55
58
  else
56
- query = Entry.where(slug: match[:slug])
59
+ entry = Entry.find_by(slug: match[:slug])
57
60
  end
58
61
 
59
- entry = query.first
60
62
  return nil unless entry
61
63
  published_at = entry.published_at
62
64
  return nil unless published_at
63
65
 
64
66
  return nil if match[:slug] && match[:slug] != entry.slug
65
67
  return nil if match[:id] && match[:id].to_i != entry.id
66
- return nil if match[:year] && match[:year].to_i != published_at.year
67
- return nil if match[:month] && match[:month].to_i != published_at.month
68
- return nil if match[:day] && match[:day].to_i != published_at.day
69
- return nil if match[:hour] && match[:hour].to_i != published_at.hour
70
- return nil if match[:minute] && match[:minute].to_i != published_at.min
71
- return nil if match[:second] && match[:second].to_i != published_at.sec
68
+ return nil if match[:year] && match[:year].to_i != published_at.localtime.year
69
+ return nil if match[:month] && match[:month].to_i != published_at.localtime.month
70
+ return nil if match[:day] && match[:day].to_i != published_at.localtime.day
71
+ return nil if match[:hour] && match[:hour].to_i != published_at.localtime.hour
72
+ return nil if match[:minute] && match[:minute].to_i != published_at.localtime.min
73
+ return nil if match[:second] && match[:second].to_i != published_at.localtime.sec
72
74
 
73
75
  return entry
74
76
  else
@@ -0,0 +1,11 @@
1
+ require 'active_record'
2
+ require 'protected_attributes'
3
+ require 'active_record/mass_assignment_security'
4
+
5
+ module Days
6
+ module Models
7
+ class Base < ActiveRecord::Base
8
+ self.abstract_class = true
9
+ end
10
+ end
11
+ end
@@ -1,7 +1,7 @@
1
- require 'active_record'
1
+ require 'days/models/base'
2
2
 
3
3
  module Days
4
- class Category < ActiveRecord::Base
4
+ class Category < Days::Models::Base
5
5
  attr_accessible :name
6
6
 
7
7
  validates_presence_of :name
@@ -1,9 +1,9 @@
1
- require 'active_record'
1
+ require 'days/models/base'
2
+ require 'html/pipeline'
2
3
  require 'stringex'
3
- require 'redcarpet'
4
4
 
5
5
  module Days
6
- class Entry < ActiveRecord::Base
6
+ class Entry < Days::Models::Base
7
7
  attr_accessible :title, :body, :slug, :published_at, :categories, :user, :draft, :old_path
8
8
 
9
9
  validates_uniqueness_of :slug
@@ -18,6 +18,16 @@ module Days
18
18
  order('published_at DESC')
19
19
  end
20
20
 
21
+ scope :draft, -> do
22
+ where(published_at: nil)
23
+ end
24
+
25
+ scope :scheduled, -> do
26
+ includes(:categories).
27
+ where('published_at IS NOT NULL AND published_at >= ?', Time.now).
28
+ order('published_at DESC')
29
+ end
30
+
21
31
  paginates_per 12
22
32
 
23
33
  def draft=(x)
@@ -45,6 +55,32 @@ module Days
45
55
  self.rendered.gsub(/<!-- *more *-->.+\z/m, block_given? ? yield(self) : '')
46
56
  end
47
57
 
58
+ def body=(*)
59
+ @need_rendering = true
60
+ super
61
+ end
62
+
63
+ def self.default_pipeline
64
+ HTML::Pipeline.new([
65
+ HTML::Pipeline::MarkdownFilter,
66
+ ])
67
+ end
68
+
69
+ def pipeline=(other)
70
+ @pipeline = other
71
+ end
72
+
73
+ def pipeline
74
+ @pipeline ||= self.class.default_pipeline
75
+ end
76
+
77
+ def render!(pipeline: self.pipeline)
78
+ result = pipeline.call(self.body)
79
+ self.rendered = result[:output].to_s
80
+ @need_rendering = false
81
+ nil
82
+ end
83
+
48
84
  before_validation do
49
85
  if draft?
50
86
  self.published_at = nil
@@ -55,11 +91,8 @@ module Days
55
91
  if self.title && (!self.slug || self.slug.empty?)
56
92
  self.slug = self.title.to_url
57
93
  end
58
- markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML,
59
- :autolink => true, :space_after_headers => true,
60
- :no_intra_emphasis => true, :fenced_code_blocks => true,
61
- :tables => true, :superscript => true)
62
- self.rendered = markdown.render(self.body)
94
+
95
+ self.render! if @need_rendering
63
96
  end
64
97
  end
65
98
  end
@@ -1,7 +1,7 @@
1
- require 'active_record'
1
+ require 'days/models/base'
2
2
 
3
3
  module Days
4
- class User < ActiveRecord::Base
4
+ class User < Days::Models::Base
5
5
  has_secure_password
6
6
 
7
7
  attr_accessible :login_name, :name, :password, :password_confirmation
data/lib/days/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Days
2
- VERSION = "0.2.0"
2
+ VERSION = "1.0.0.rc1"
3
3
  end
@@ -71,7 +71,7 @@ loop do
71
71
  <div class="t-photos-caption">
72
72
  #{post['caption']}
73
73
  </div>
74
- </div>
74
+ </section>
75
75
  EOF
76
76
  when 'quote'
77
77
  entry[:title] = post['text'] ? post['text'].dup : ''
@@ -2,9 +2,8 @@ require 'spec_helper'
2
2
 
3
3
  describe Days::App, type: :controller do
4
4
  describe "admin: categories" do
5
- fixtures :users, :categories
6
- let(:user) { users(:blogger) }
7
- let(:category) { categories(:daily) }
5
+ let(:user) { Days::User.create!(login_name: 'blogger', name: 'blogger', password: 'x', password_confirmation: 'x') }
6
+ let!(:category) { Days::Category.create!(name: 'daily') }
8
7
 
9
8
  before { login(user) }
10
9
 
@@ -13,13 +12,13 @@ describe Days::App, type: :controller do
13
12
 
14
13
  it_behaves_like 'an admin page'
15
14
 
16
- it { should be_ok }
15
+ it { is_expected.to be_ok }
17
16
 
18
17
  it "lists up categories" do
19
- render[:data].should == :'admin/categories'
18
+ expect(render[:data]).to eq(:'admin/categories')
20
19
 
21
20
  categories = render[:ivars][:@categories]
22
- categories.should == Days::Category.all
21
+ expect(categories.to_a).to eq([category])
23
22
  end
24
23
  end
25
24
 
@@ -30,20 +29,21 @@ describe Days::App, type: :controller do
30
29
  it_behaves_like 'an admin page'
31
30
 
32
31
  it "creates category" do
33
- subject.should be_redirect
32
+ expect(subject).to be_redirect
34
33
 
35
- Days::Category.last.name.should == params[:category][:name]
34
+ expect(Days::Category.last.name).to eq(params[:category][:name])
36
35
  end
37
36
 
38
37
  context "when category is invalid" do
39
38
  before do
40
- Days::Category.any_instance.stub(:valid? => false, :save => false)
39
+ allow_any_instance_of(Days::Category).to receive(:valid?).and_return(false)
40
+ allow_any_instance_of(Days::Category).to receive(:save).and_return(false)
41
41
  end
42
42
 
43
- specify { subject.status.should == 406 } # not acceptable
43
+ specify { expect(subject.status).to eq(406) } # not acceptable
44
44
 
45
45
  it "renders form" do
46
- render[:data].should == :'admin/categories'
46
+ expect(render[:data]).to eq(:'admin/categories')
47
47
  end
48
48
  end
49
49
  end
@@ -55,27 +55,27 @@ describe Days::App, type: :controller do
55
55
  it_behaves_like 'an admin page'
56
56
 
57
57
  it "updates category" do
58
- subject.should be_redirect
59
- URI.parse(subject['Location']).path.should == '/admin/categories'
58
+ expect(subject).to be_redirect
59
+ expect(URI.parse(subject['Location']).path).to eq('/admin/categories')
60
60
 
61
61
  category.reload
62
- category.name.should == 'Storm'
62
+ expect(category.name).to eq('Storm')
63
63
  end
64
64
 
65
65
  context "when invalid" do
66
66
  before do
67
- Days::Category.any_instance.stub(:valid? => false, :save => false)
67
+ allow_any_instance_of(Days::Category).to receive_messages(:valid? => false, :save => false)
68
68
  end
69
69
 
70
70
  it "renders form" do
71
- render[:data].should == :'admin/categories'
71
+ expect(render[:data]).to eq(:'admin/categories')
72
72
  end
73
73
  end
74
74
 
75
75
  context "with invalid category" do
76
- let(:category) { double.tap { |_| _.stub(id: Days::Category.last.id.succ) } }
76
+ before { category.destroy }
77
77
 
78
- it { should be_not_found }
78
+ it { is_expected.to be_not_found }
79
79
  end
80
80
  end
81
81
 
@@ -86,14 +86,14 @@ describe Days::App, type: :controller do
86
86
 
87
87
  it "destroys category" do
88
88
  expect { subject }.to change { Days::Category.where(id: category.id).count }.from(1).to(0)
89
- subject.should be_redirect
90
- URI.parse(subject.location).path.should == "/admin/categories"
89
+ expect(subject).to be_redirect
90
+ expect(URI.parse(subject.location).path).to eq("/admin/categories")
91
91
  end
92
92
 
93
93
  context "with invalid category" do
94
- let(:category) { double.tap { |_| _.stub(id: Days::Category.last.id.succ) } }
94
+ before { category.destroy }
95
95
 
96
- it { should be_not_found }
96
+ it { is_expected.to be_not_found }
97
97
  end
98
98
  end
99
99
  end