noodnik 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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