noodnik 0.1.0

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 (82) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.md +52 -0
  3. data/Rakefile +39 -0
  4. data/app/assets/javascripts/noodnik/application.js +9 -0
  5. data/app/assets/javascripts/noodnik/nags.erb.coffee +12 -0
  6. data/app/assets/stylesheets/noodnik/application.css +7 -0
  7. data/app/assets/stylesheets/noodnik/nags.css +4 -0
  8. data/app/controllers/noodnik/application_controller.rb +4 -0
  9. data/app/controllers/noodnik/nags_controller.rb +47 -0
  10. data/app/helpers/noodnik/application_helper.rb +4 -0
  11. data/app/helpers/noodnik/nags_helper.rb +51 -0
  12. data/app/models/noodnik/nag.rb +4 -0
  13. data/app/views/layouts/application.html.erb +14 -0
  14. data/app/views/layouts/noodnik/application.html.erb +14 -0
  15. data/config/routes.rb +6 -0
  16. data/db/migrate/20110813042447_create_noodnik_nags.rb +11 -0
  17. data/db/migrate/20110813065655_add_user_id_to_nags.rb +5 -0
  18. data/db/migrate/20110813072011_add_topic_to_nags.rb +5 -0
  19. data/lib/noodnik.rb +10 -0
  20. data/lib/noodnik/engine.rb +5 -0
  21. data/lib/noodnik/railtie.rb +7 -0
  22. data/lib/tasks/noodnik_tasks.rake +4 -0
  23. data/test/dummy/Guardfile +29 -0
  24. data/test/dummy/Rakefile +7 -0
  25. data/test/dummy/app/assets/javascripts/application.js +9 -0
  26. data/test/dummy/app/assets/javascripts/home.js +2 -0
  27. data/test/dummy/app/assets/stylesheets/application.css +7 -0
  28. data/test/dummy/app/assets/stylesheets/home.css +4 -0
  29. data/test/dummy/app/controllers/application_controller.rb +3 -0
  30. data/test/dummy/app/controllers/home_controller.rb +4 -0
  31. data/test/dummy/app/helpers/application_helper.rb +2 -0
  32. data/test/dummy/app/helpers/home_helper.rb +2 -0
  33. data/test/dummy/app/views/home/index.html.erb +10 -0
  34. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  35. data/test/dummy/config.ru +4 -0
  36. data/test/dummy/config/application.rb +47 -0
  37. data/test/dummy/config/boot.rb +10 -0
  38. data/test/dummy/config/database.yml +25 -0
  39. data/test/dummy/config/environment.rb +5 -0
  40. data/test/dummy/config/environments/development.rb +27 -0
  41. data/test/dummy/config/environments/production.rb +51 -0
  42. data/test/dummy/config/environments/test.rb +39 -0
  43. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  44. data/test/dummy/config/initializers/inflections.rb +10 -0
  45. data/test/dummy/config/initializers/mime_types.rb +5 -0
  46. data/test/dummy/config/initializers/noodnik.rb +3 -0
  47. data/test/dummy/config/initializers/secret_token.rb +7 -0
  48. data/test/dummy/config/initializers/session_store.rb +8 -0
  49. data/test/dummy/config/initializers/wrap_parameters.rb +12 -0
  50. data/test/dummy/config/locales/en.yml +5 -0
  51. data/test/dummy/config/routes.rb +6 -0
  52. data/test/dummy/db/development.sqlite3 +0 -0
  53. data/test/dummy/db/migrate/20110813070108_create_noodnik_nags.rb +11 -0
  54. data/test/dummy/db/migrate/20110813070109_add_user_id_to_nags.rb +5 -0
  55. data/test/dummy/db/migrate/20110813072040_add_topic_to_nags.rb +5 -0
  56. data/test/dummy/db/schema.rb +24 -0
  57. data/test/dummy/db/test.sqlite3 +0 -0
  58. data/test/dummy/log/development.log +10612 -0
  59. data/test/dummy/log/test.log +26879 -0
  60. data/test/dummy/public/404.html +26 -0
  61. data/test/dummy/public/422.html +26 -0
  62. data/test/dummy/public/500.html +26 -0
  63. data/test/dummy/public/favicon.ico +0 -0
  64. data/test/dummy/script/rails +6 -0
  65. data/test/dummy/spec/controllers/noodnik_nags_controller_spec.rb +121 -0
  66. data/test/dummy/spec/helpers/nags_helper_spec.rb +130 -0
  67. data/test/dummy/spec/spec_helper.rb +74 -0
  68. data/test/dummy/tmp/cache/assets/C7E/8B0/sprockets%2F1a26023e8a9ac4a7477d84b980511817 +0 -0
  69. data/test/dummy/tmp/cache/assets/C9B/0A0/sprockets%2Fc184c48971885500d230701da1c1b0fb +0 -0
  70. data/test/dummy/tmp/cache/assets/CC7/610/sprockets%2Fd85d521b5f5052344563eef989889de0 +0 -0
  71. data/test/dummy/tmp/cache/assets/CDF/870/sprockets%2Fb878faf942403e313a5b103e5d80488e +0 -0
  72. data/test/dummy/tmp/cache/assets/CF8/F90/sprockets%2F7c5977cba909e2f75909ced513698d03 +0 -0
  73. data/test/dummy/tmp/cache/assets/D32/A10/sprockets%2F13fe41fee1fe35b49d145bcc06610705 +0 -0
  74. data/test/dummy/tmp/cache/assets/D54/ED0/sprockets%2F71c9fa01091d432b131da3bb73faf3d4 +0 -0
  75. data/test/dummy/tmp/cache/assets/D72/AD0/sprockets%2Fc4434fe69351b83a77ebaca291931fee +0 -0
  76. data/test/dummy/tmp/cache/assets/D7E/3B0/sprockets%2F942cff9f3e4e8a45ae06090e3d883e7b +0 -0
  77. data/test/dummy/tmp/cache/assets/D84/210/sprockets%2Fabd0103ccec2b428ac62c94e4c40b384 +0 -0
  78. data/test/dummy/tmp/cache/assets/D98/8B0/sprockets%2Fedbef6e0d0a4742346cf479f2c522eb0 +0 -0
  79. data/test/dummy/tmp/cache/assets/E04/890/sprockets%2F2f5173deea6c795b8fdde723bb4b63af +0 -0
  80. data/test/dummy/tmp/cache/assets/E38/C70/sprockets%2F7e7577dbecc6d06993be00b9daabcd9f +0 -0
  81. data/test/dummy/tmp/pids/server.pid +1 -0
  82. metadata +184 -0
@@ -0,0 +1,26 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The page you were looking for doesn't exist (404)</title>
5
+ <style type="text/css">
6
+ body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
7
+ div.dialog {
8
+ width: 25em;
9
+ padding: 0 4em;
10
+ margin: 4em auto 0 auto;
11
+ border: 1px solid #ccc;
12
+ border-right-color: #999;
13
+ border-bottom-color: #999;
14
+ }
15
+ h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <!-- This file lives in public/404.html -->
21
+ <div class="dialog">
22
+ <h1>The page you were looking for doesn't exist.</h1>
23
+ <p>You may have mistyped the address or the page may have moved.</p>
24
+ </div>
25
+ </body>
26
+ </html>
@@ -0,0 +1,26 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The change you wanted was rejected (422)</title>
5
+ <style type="text/css">
6
+ body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
7
+ div.dialog {
8
+ width: 25em;
9
+ padding: 0 4em;
10
+ margin: 4em auto 0 auto;
11
+ border: 1px solid #ccc;
12
+ border-right-color: #999;
13
+ border-bottom-color: #999;
14
+ }
15
+ h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <!-- This file lives in public/422.html -->
21
+ <div class="dialog">
22
+ <h1>The change you wanted was rejected.</h1>
23
+ <p>Maybe you tried to change something you didn't have access to.</p>
24
+ </div>
25
+ </body>
26
+ </html>
@@ -0,0 +1,26 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>We're sorry, but something went wrong (500)</title>
5
+ <style type="text/css">
6
+ body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
7
+ div.dialog {
8
+ width: 25em;
9
+ padding: 0 4em;
10
+ margin: 4em auto 0 auto;
11
+ border: 1px solid #ccc;
12
+ border-right-color: #999;
13
+ border-bottom-color: #999;
14
+ }
15
+ h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <!-- This file lives in public/500.html -->
21
+ <div class="dialog">
22
+ <h1>We're sorry, but something went wrong.</h1>
23
+ <p>We've been notified about this issue and we'll take a look at it shortly.</p>
24
+ </div>
25
+ </body>
26
+ </html>
File without changes
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3
+
4
+ APP_PATH = File.expand_path('../../config/application', __FILE__)
5
+ require File.expand_path('../../config/boot', __FILE__)
6
+ require 'rails/commands'
@@ -0,0 +1,121 @@
1
+ require 'spec_helper'
2
+
3
+ describe Noodnik::NagsController do
4
+ before :each do
5
+ @topic = :complete_your_registration
6
+ @attr = {use_route: :noodnik, topic: @topic}
7
+
8
+ Noodnik.setup do |config|
9
+ config.current_user_id = lambda { nil }
10
+ end
11
+ end
12
+
13
+ describe "when not signed in" do
14
+ before :each do
15
+ @cookies = mock('cookies')
16
+ controller.stub!(:cookies).and_return(@cookies)
17
+ set_current_user_id(nil)
18
+ end
19
+
20
+ describe "GET 'postpone'" do
21
+ before :each do
22
+ @attr.merge! period: 2.weeks
23
+ end
24
+
25
+ after :each do
26
+ cookies.clear
27
+ end
28
+
29
+ it "creates a cookie" do
30
+ @cookies.should_receive(:[]=)
31
+ get :postpone, @attr
32
+ end
33
+
34
+ it "sets the provided topic as the cookie name" do
35
+ @cookies.should_receive(:[]=).with(@topic.to_s, anything)
36
+ get :postpone, @attr
37
+ end
38
+
39
+ it "sets the next nag time correctly" do
40
+ @cookies.should_receive(:[]=).with(anything, 2.weeks.from_now.to_s)
41
+ get :postpone, @attr
42
+ end
43
+ end
44
+
45
+ describe "GET 'complete'" do
46
+ it "removes the nag cookie" do
47
+ @cookies.should_receive(:delete).with(@topic.to_s)
48
+ get :complete, @attr
49
+ end
50
+ end
51
+ end
52
+
53
+ describe "when signed in" do
54
+ before :each do
55
+ @user_id = 1
56
+ set_current_user_id(@user_id)
57
+ end
58
+
59
+ describe "GET 'postpone'" do
60
+ before :each do
61
+ @attr.merge! period: 2.weeks
62
+ end
63
+
64
+ after :each do
65
+ Noodnik::Nag.delete_all
66
+ end
67
+
68
+ describe "for the first time" do
69
+ before :each do
70
+ stub_time
71
+ get :postpone, @attr
72
+ end
73
+
74
+ it "creates a nag instance" do
75
+ Noodnik::Nag.count.should == 1
76
+ end
77
+
78
+ it "sets the correct user id" do
79
+ Noodnik::Nag.last.user_id.should == @user_id
80
+ end
81
+
82
+ it "sets the provided topic" do
83
+ Noodnik::Nag.last.topic.should == @topic.to_s
84
+ end
85
+
86
+ it "sets the next nag time correctly" do
87
+ Noodnik::Nag.last.next_nag.should == 2.weeks.from_now
88
+ end
89
+ end
90
+
91
+ describe "not for the first time" do
92
+ it "modifies the next nag time correctly" do
93
+ nag = Noodnik::Nag.create! user_id: 1, topic: @topic
94
+
95
+ stub_time
96
+ get :postpone, @attr
97
+ nag.reload.next_nag.should == 2.weeks.from_now
98
+ end
99
+ end
100
+ end
101
+
102
+ describe "GET 'complete'" do
103
+ it "marks the nag as complete" do
104
+ nag = Noodnik::Nag.create! user_id: 1, topic: @topic
105
+ get :complete, @attr
106
+ nag.reload.completed.should be_true
107
+ end
108
+ end
109
+ end
110
+
111
+ def set_current_user_id(user_id)
112
+ Noodnik.setup do |config|
113
+ config.current_user_id = lambda { user_id }
114
+ end
115
+ end
116
+
117
+ def stub_time
118
+ t = Time.parse("01/01/2010 10:00")
119
+ Time.stub!(:now).and_return(t)
120
+ end
121
+ end
@@ -0,0 +1,130 @@
1
+ require 'spec_helper'
2
+
3
+ describe Noodnik::NagsHelper do
4
+
5
+ describe "nag_user_to" do
6
+ before :each do
7
+ @topic = :register
8
+ end
9
+
10
+ describe "when signed in" do
11
+ before :each do
12
+ @user_id = 1
13
+ Noodnik.setup do |config|
14
+ config.current_user_id = lambda { @user_id }
15
+ end
16
+ end
17
+
18
+ after :each do
19
+ Noodnik::Nag.delete_all
20
+ end
21
+
22
+ it "yields the block in a div with class 'noodnik-nag'" do
23
+ helper.nag_user_to :register do |nag|
24
+ "I should be in a <div>!"
25
+ end.should match(%r[<div class="noodnik-nag">.*</div>])
26
+ end
27
+
28
+ it "should yield the block for a new topic" do
29
+ helper.nag_user_to :register do |nag|
30
+ "Register!"
31
+ end.should include("Register!")
32
+ end
33
+
34
+ it "should not yield the block if postponed" do
35
+ Noodnik::Nag.create! user_id: @user_id, topic: @topic, next_nag: 2.weeks.from_now
36
+
37
+ helper.nag_user_to :register do |nag|
38
+ "I should not be returned!"
39
+ end.should be_nil
40
+ end
41
+
42
+ it "should yield the block if postpone expired" do
43
+ Noodnik::Nag.create! user_id: @user_id, topic: @topic, next_nag: 1.week.ago
44
+
45
+ helper.nag_user_to :register do |nag|
46
+ "Register!"
47
+ end.should include("Register!")
48
+ end
49
+
50
+ it "should not yield the block if completed" do
51
+ Noodnik::Nag.create! user_id: @user_id, topic: @topic, next_nag: 10.weeks.ago, completed: true
52
+
53
+ helper.nag_user_to :register do |nag|
54
+ "I should not be returned!"
55
+ end.should be_nil
56
+ end
57
+
58
+ end
59
+ end
60
+
61
+ describe "link_to" do
62
+ describe "with html_options provided" do
63
+ before :each do
64
+ @link = nag_user_to :register do
65
+ link_to 'google.com', 'www.google.com', class: 'foo'
66
+ end
67
+ end
68
+
69
+ it "adds 'data-noodnik-topic' with the correct topic" do
70
+ @link.should include('data-noodnik-topic="register"')
71
+ end
72
+
73
+ it "adds class 'noodnik-complete'" do
74
+ @link.should include("class=\"foo noodnik-complete\"")
75
+ end
76
+ end
77
+
78
+ describe "with no html_options provided" do
79
+ before :each do
80
+ @link = nag_user_to :register do
81
+ link_to 'google.com', 'www.google.com'
82
+ end
83
+ end
84
+
85
+ it "adds 'data-noodnik-topic' with the correct topic when no html_options provided" do
86
+ @link.should include('data-noodnik-topic="register"')
87
+ end
88
+
89
+ it "adds class 'noodnik-complete'" do
90
+ @link.should include("class=\"noodnik-complete\"")
91
+ end
92
+ end
93
+ end
94
+
95
+ describe "postpone_for" do
96
+ before :each do
97
+ @link = nag_user_to :register do
98
+ postpone_for 14.days
99
+ end
100
+ end
101
+
102
+ it "prompts a default message of 'Remind me in 14 days'" do
103
+ @link.should include('Remind me in 14 days')
104
+ end
105
+
106
+ it "links to /noodnik/postpone" do
107
+ @link.should include('/noodnik/postpone')
108
+ end
109
+
110
+ it "specifies the correct period in the link" do
111
+ @link.should include("period=#{14.days}")
112
+ end
113
+
114
+ it "specifies the correct topic" do
115
+ @link.should include("topic=register")
116
+ end
117
+
118
+ it "should have class 'noodnik-postpone'" do
119
+ @link.should include("noodnik-postpone")
120
+ end
121
+
122
+ it "does not add class 'noodnik-complete'" do
123
+ @link.should_not include("noodnik-complete")
124
+ end
125
+
126
+ it "does not mark postpone links with 'data_noodnik_complete-path'" do
127
+ @link.should_not include("data-noodnik-complete-path=\"/noodnik/complete/register\"")
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,74 @@
1
+ require 'rubygems'
2
+ require 'spork'
3
+
4
+ Spork.prefork do
5
+ # Loading more in this block will cause your tests to run faster. However,
6
+ # if you change any configuration or code from libraries loaded here, you'll
7
+ # need to restart spork for it take effect.
8
+
9
+ end
10
+
11
+ Spork.each_run do
12
+ # This code will be run each time you run your specs.
13
+
14
+ end
15
+
16
+ # --- Instructions ---
17
+ # Sort the contents of this file into a Spork.prefork and a Spork.each_run
18
+ # block.
19
+ #
20
+ # The Spork.prefork block is run only once when the spork server is started.
21
+ # You typically want to place most of your (slow) initializer code in here, in
22
+ # particular, require'ing any 3rd-party gems that you don't normally modify
23
+ # during development.
24
+ #
25
+ # The Spork.each_run block is run each time you run your specs. In case you
26
+ # need to load files that tend to change during development, require them here.
27
+ # With Rails, your application modules are loaded automatically, so sometimes
28
+ # this block can remain empty.
29
+ #
30
+ # Note: You can modify files loaded *from* the Spork.each_run block without
31
+ # restarting the spork server. However, this file itself will not be reloaded,
32
+ # so if you change any of the code inside the each_run block, you still need to
33
+ # restart the server. In general, if you have non-trivial code in this file,
34
+ # it's advisable to move it into a separate file so you can easily edit it
35
+ # without restarting spork. (For example, with RSpec, you could move
36
+ # non-trivial code into a file spec/support/my_helper.rb, making sure that the
37
+ # spec/support/* files are require'd from inside the each_run block.)
38
+ #
39
+ # Any code that is left outside the two blocks will be run during preforking
40
+ # *and* during each_run -- that's probably not what you want.
41
+ #
42
+ # These instructions should self-destruct in 10 seconds. If they don't, feel
43
+ # free to delete them.
44
+
45
+
46
+
47
+
48
+ # This file is copied to spec/ when you run 'rails generate rspec:install'
49
+ ENV["RAILS_ENV"] ||= 'test'
50
+ require File.expand_path("../../config/environment", __FILE__)
51
+ require 'rspec/rails'
52
+
53
+ # Requires supporting ruby files with custom matchers and macros, etc,
54
+ # in spec/support/ and its subdirectories.
55
+ Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
56
+
57
+ RSpec.configure do |config|
58
+ # == Mock Framework
59
+ #
60
+ # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
61
+ #
62
+ # config.mock_with :mocha
63
+ # config.mock_with :flexmock
64
+ # config.mock_with :rr
65
+ config.mock_with :rspec
66
+
67
+ # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
68
+ config.fixture_path = "#{::Rails.root}/spec/fixtures"
69
+
70
+ # If you're not using ActiveRecord, or you'd prefer not to run each of your
71
+ # examples within a transaction, remove the following line or assign false
72
+ # instead of true.
73
+ #config.use_transactional_fixtures = true
74
+ end
@@ -0,0 +1 @@
1
+ 11712