kublog 0.0.1.1 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -5
- data/.rspec +2 -0
- data/Gemfile +3 -1
- data/Gemfile.lock +89 -77
- data/README.rdoc +102 -61
- data/Rakefile +5 -10
- data/app/assets/javascripts/kublog/email.js.coffee +24 -9
- data/app/assets/javascripts/kublog/posts.js.coffee +46 -19
- data/app/assets/javascripts/kublog/shared.js.coffee.erb +1 -1
- data/app/assets/javascripts/kublog/wysiwyg.controls.js.coffee +0 -1
- data/app/assets/plugins/kublog/ajaxyupload/javascripts/jquery.ajaxyupload.js +1 -1
- data/app/assets/stylesheets/kublog/posts.css +2 -2
- data/app/controllers/kublog/application_controller.rb +18 -2
- data/app/controllers/kublog/categories_controller.rb +2 -2
- data/app/controllers/kublog/notifications_controller.rb +13 -0
- data/app/controllers/kublog/posts_controller.rb +7 -18
- data/app/helpers/kublog/application_helper.rb +15 -0
- data/app/helpers/kublog/notifications_helper.rb +4 -0
- data/app/helpers/kublog/posts_helper.rb +4 -0
- data/app/jobs/kublog/deliver_comment.rb +14 -0
- data/app/mailers/kublog/comment_mailer.rb +11 -0
- data/app/mailers/kublog/post_mailer.rb +4 -5
- data/app/models/kublog/category.rb +13 -5
- data/app/models/kublog/comment.rb +17 -6
- data/app/models/kublog/notification.rb +27 -0
- data/app/models/kublog/post.rb +11 -6
- data/app/presenters/kublog/post_form_presenter.rb +19 -0
- data/app/presenters/kublog/posts_presenter.rb +7 -1
- data/app/uploaders/kublog/file_uploader.rb +0 -3
- data/app/views/kublog/comment_mailer/new_comment.html.erb +11 -0
- data/app/views/kublog/post_mailer/new_post.html.erb +1 -1
- data/app/views/kublog/post_mailer/new_post.liquid.html.erb +9 -1
- data/app/views/kublog/posts/_email_form.html.erb +27 -9
- data/app/views/kublog/posts/_facebook_form.html.erb +10 -0
- data/app/views/kublog/posts/_form.html.erb +7 -45
- data/app/views/kublog/posts/_twitter_form.html.erb +11 -0
- data/app/views/kublog/posts/edit.html.erb +1 -1
- data/app/views/kublog/posts/index.atom.builder +1 -2
- data/app/views/kublog/posts/index.rss.builder +20 -0
- data/app/views/kublog/posts/new.html.erb +1 -1
- data/config/locales/kublog/en.yml +9 -0
- data/config/routes.rb +8 -0
- data/db/migrate/20110816211552_create_kublog_posts.rb +1 -9
- data/db/migrate/20110901205127_create_kublog_notifications.rb +18 -0
- data/index.html +10 -0
- data/kublog.gemspec +10 -10
- data/lib/generators/kublog/install/USAGE +8 -0
- data/lib/generators/kublog/install/install_generator.rb +78 -0
- data/lib/generators/kublog/install/templates/configuration.rb.tt +45 -0
- data/lib/kublog.rb +43 -13
- data/lib/kublog/author.rb +2 -3
- data/lib/kublog/engine.rb +1 -0
- data/lib/kublog/network/email.rb +113 -0
- data/lib/kublog/network/facebook.rb +54 -0
- data/lib/kublog/network/twitter.rb +55 -0
- data/lib/kublog/notifiable.rb +2 -5
- data/lib/kublog/processor.rb +27 -0
- data/lib/kublog/version.rb +2 -2
- data/script/rails +1 -1
- data/{test → spec}/dummy/Rakefile +0 -0
- data/{test → spec}/dummy/app/assets/javascripts/application.js +0 -0
- data/{test → spec}/dummy/app/assets/javascripts/sessions.js +0 -0
- data/{test → spec}/dummy/app/assets/javascripts/users.js +0 -0
- data/{test → spec}/dummy/app/assets/stylesheets/application.css +0 -0
- data/{test → spec}/dummy/app/assets/stylesheets/sessions.css +0 -0
- data/{test → spec}/dummy/app/assets/stylesheets/users.css +0 -0
- data/{test → spec}/dummy/app/controllers/application_controller.rb +0 -0
- data/{test → spec}/dummy/app/controllers/sessions_controller.rb +0 -0
- data/{test → spec}/dummy/app/controllers/users_controller.rb +0 -0
- data/{test → spec}/dummy/app/helpers/application_helper.rb +0 -0
- data/{test → spec}/dummy/app/helpers/error_messages_helper.rb +0 -0
- data/{test → spec}/dummy/app/helpers/layout_helper.rb +0 -0
- data/{test → spec}/dummy/app/helpers/sessions_helper.rb +0 -0
- data/{test → spec}/dummy/app/helpers/users_helper.rb +0 -0
- data/{test → spec}/dummy/app/mailers/.gitkeep +0 -0
- data/{test → spec}/dummy/app/models/.gitkeep +0 -0
- data/{test → spec}/dummy/app/models/ability.rb +0 -0
- data/{test → spec}/dummy/app/models/user.rb +1 -5
- data/{test → spec}/dummy/app/views/layouts/_account.html.erb +0 -0
- data/{test → spec}/dummy/app/views/layouts/application.html.erb +0 -0
- data/{test → spec}/dummy/app/views/layouts/kublog/application.html.erb +0 -0
- data/{test → spec}/dummy/app/views/sessions/new.html.erb +0 -0
- data/{test → spec}/dummy/app/views/users/new.html.erb +0 -0
- data/{test → spec}/dummy/config.ru +0 -0
- data/{test → spec}/dummy/config/application.rb +0 -0
- data/{test → spec}/dummy/config/boot.rb +0 -0
- data/{test → spec}/dummy/config/database.yml +0 -0
- data/{test → spec}/dummy/config/environment.rb +0 -0
- data/{test → spec}/dummy/config/environments/development.rb +0 -0
- data/{test → spec}/dummy/config/environments/production.rb +0 -0
- data/{test → spec}/dummy/config/environments/test.rb +0 -0
- data/{test → spec}/dummy/config/initializers/backtrace_silencers.rb +0 -0
- data/{test → spec}/dummy/config/initializers/inflections.rb +0 -0
- data/spec/dummy/config/initializers/kublog.rb +34 -0
- data/{test → spec}/dummy/config/initializers/mime_types.rb +0 -0
- data/{test → spec}/dummy/config/initializers/secret_token.rb +0 -0
- data/{test → spec}/dummy/config/initializers/session_store.rb +0 -0
- data/{test → spec}/dummy/config/initializers/wrap_parameters.rb +0 -0
- data/{test → spec}/dummy/config/locales/en.yml +9 -0
- data/{test → spec}/dummy/config/routes.rb +0 -0
- data/{test → spec}/dummy/db/migrate/20110816225222_create_users.rb +1 -0
- data/{test → spec}/dummy/db/migrate/20110819135547_create_delayed_jobs.rb +0 -0
- data/{test → spec}/dummy/db/schema.rb +16 -10
- data/{test → spec}/dummy/lib/assets/.gitkeep +0 -0
- data/{test → spec}/dummy/log/.gitkeep +0 -0
- data/{test → spec}/dummy/public/404.html +0 -0
- data/{test → spec}/dummy/public/422.html +0 -0
- data/{test → spec}/dummy/public/500.html +0 -0
- data/{test → spec}/dummy/public/favicon.ico +0 -0
- data/{test → spec}/dummy/script/delayed_job +0 -0
- data/{test → spec}/dummy/script/rails +0 -0
- data/spec/factories.rb +54 -0
- data/spec/fixtures/Adrian.png +0 -0
- data/spec/fixtures/rendered_email.html +15 -0
- data/spec/lib/author_spec.rb +25 -0
- data/spec/lib/network/email_spec.rb +113 -0
- data/spec/lib/network/facebook_spec.rb +68 -0
- data/spec/lib/network/twitter_spec.rb +68 -0
- data/spec/lib/notifiable_spec.rb +23 -0
- data/spec/lib/processor_spec.rb +25 -0
- data/spec/models/kublog/category_spec.rb +43 -0
- data/spec/models/kublog/comment_spec.rb +56 -0
- data/spec/models/kublog/image_spec.rb +37 -0
- data/spec/models/kublog/notification_spec.rb +53 -0
- data/spec/models/kublog/post_spec.rb +63 -0
- data/spec/spec_helper.rb +43 -0
- metadata +198 -208
- data/app/assets/stylesheets/kublog/categories.css +0 -4
- data/app/assets/stylesheets/kublog/comments.css +0 -4
- data/lib/kublog/notification/email.rb +0 -86
- data/lib/kublog/notification/email_job.rb +0 -14
- data/lib/kublog/notification/fb_post.rb +0 -43
- data/lib/kublog/notification/fb_post_job.rb +0 -16
- data/lib/kublog/notification/tweet.rb +0 -68
- data/lib/kublog/notification/tweet_job.rb +0 -16
- data/test/dummy/test/fixtures/users.yml +0 -9
- data/test/dummy/test/functional/sessions_controller_test.rb +0 -7
- data/test/dummy/test/functional/users_controller_test.rb +0 -7
- data/test/dummy/test/unit/helpers/sessions_helper_test.rb +0 -4
- data/test/dummy/test/unit/helpers/users_helper_test.rb +0 -4
- data/test/dummy/test/unit/user_test.rb +0 -7
- data/test/factories.rb +0 -9
- data/test/fixtures/kublog/categories.yml +0 -7
- data/test/fixtures/kublog/comments.yml +0 -7
- data/test/fixtures/kublog/images.yml +0 -9
- data/test/fixtures/kublog/posts.yml +0 -9
- data/test/functional/kublog/categories_controller_test.rb +0 -9
- data/test/functional/kublog/comments_controller_test.rb +0 -9
- data/test/functional/kublog/images_controller_test.rb +0 -9
- data/test/functional/kublog/post_mailer_test.rb +0 -9
- data/test/functional/kublog/posts_controller_test.rb +0 -9
- data/test/integration/navigation_test.rb +0 -10
- data/test/kublog_test.rb +0 -7
- data/test/test_helper.rb +0 -12
- data/test/unit/helpers/kublog/categories_helper_test.rb +0 -6
- data/test/unit/helpers/kublog/comments_helper_test.rb +0 -6
- data/test/unit/helpers/kublog/images_helper_test.rb +0 -6
- data/test/unit/helpers/kublog/posts_helper_test.rb +0 -6
- data/test/unit/kublog/category_test.rb +0 -9
- data/test/unit/kublog/comment_test.rb +0 -9
- data/test/unit/kublog/image_test.rb +0 -9
- data/test/unit/kublog/post_test.rb +0 -19
@@ -0,0 +1,55 @@
|
|
1
|
+
module Kublog
|
2
|
+
module Network
|
3
|
+
module Twitter
|
4
|
+
|
5
|
+
def self.included(base)
|
6
|
+
base.send :include, InstanceMethods
|
7
|
+
base.send :validate, :valid_twitter_content, :if => :twitter?
|
8
|
+
end
|
9
|
+
|
10
|
+
module InstanceMethods
|
11
|
+
|
12
|
+
# Calls processor to work on delivering the tweet
|
13
|
+
def deliver_twitter
|
14
|
+
Processor.work(Tweet.new(self.content, self.url))
|
15
|
+
end
|
16
|
+
|
17
|
+
# It's activated by default when a new post is created
|
18
|
+
# but not when editing the post
|
19
|
+
def default_twitter
|
20
|
+
post.new_record?
|
21
|
+
end
|
22
|
+
|
23
|
+
# Returns true when the notification behaves like a twitter
|
24
|
+
# notification
|
25
|
+
def twitter?
|
26
|
+
self.kind == 'twitter'
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
# Not valid when tweet content is empty
|
32
|
+
def valid_twitter_content
|
33
|
+
errors.add(:content, :twitter) if self.content.blank?
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
class Tweet
|
39
|
+
def initialize(content, url)
|
40
|
+
@content = content
|
41
|
+
@url = url
|
42
|
+
end
|
43
|
+
|
44
|
+
def perform
|
45
|
+
begin
|
46
|
+
update = [@content, @url].join(' ')
|
47
|
+
Kublog.twitter_client.update(update)
|
48
|
+
rescue Twitter::NotFound
|
49
|
+
nil # Dont do anything for now
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/lib/kublog/notifiable.rb
CHANGED
@@ -6,10 +6,7 @@ module Kublog
|
|
6
6
|
module Notifiable
|
7
7
|
|
8
8
|
def self.included(base)
|
9
|
-
base.
|
10
|
-
@@kublog_notifiable = true
|
11
|
-
cattr_accessor :kublog_notifiable
|
12
|
-
end
|
9
|
+
Kublog.notify_class = base.name
|
13
10
|
base.send :include, InstanceMethods
|
14
11
|
end
|
15
12
|
|
@@ -17,7 +14,7 @@ module Kublog
|
|
17
14
|
# If User Kinds are being used, this should be
|
18
15
|
# Overriden
|
19
16
|
module InstanceMethods
|
20
|
-
def notify_post?(
|
17
|
+
def notify_post?(roles)
|
21
18
|
true
|
22
19
|
end
|
23
20
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# Processes any given task with the method specified in the configuration
|
2
|
+
# Currently the available processing methods are
|
3
|
+
#
|
4
|
+
# config.notification_processing = :immediate
|
5
|
+
# config.notification_processing = :delayed_job
|
6
|
+
module Kublog
|
7
|
+
module Processor
|
8
|
+
|
9
|
+
# Proxy method that calls the configuration specified processor
|
10
|
+
def self.work(task)
|
11
|
+
self.send(Kublog.notification_processing, task)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
# Immediately calls perform on the task given (No background processing)
|
17
|
+
def self.immediate(task)
|
18
|
+
task.perform
|
19
|
+
end
|
20
|
+
|
21
|
+
# Should create a new Job for processing with DeleyedJob
|
22
|
+
def self.delayed_job(task)
|
23
|
+
Delayed::Job.enqueue(task)
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
data/lib/kublog/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
1
|
module Kublog
|
2
|
-
VERSION = "0.0
|
3
|
-
end
|
2
|
+
VERSION = "0.9.0"
|
3
|
+
end
|
data/script/rails
CHANGED
@@ -3,4 +3,4 @@
|
|
3
3
|
# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
|
4
4
|
|
5
5
|
ENGINE_PATH = File.expand_path('../..', __FILE__)
|
6
|
-
load File.expand_path('../../
|
6
|
+
load File.expand_path('../../spec/dummy/script/rails', __FILE__)
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,34 @@
|
|
1
|
+
Kublog.setup do |config|
|
2
|
+
|
3
|
+
# Blog name for title and RSS Feed
|
4
|
+
config.blog_name = 'Kublog'
|
5
|
+
|
6
|
+
config.author_email "Kublog Test <test@kublog.com>"
|
7
|
+
|
8
|
+
config.default_url_options = {:host => "www.kublog.com"}
|
9
|
+
|
10
|
+
#Delivers Post Notification as soon as created
|
11
|
+
config.notification_processing = {:development => :immediate,
|
12
|
+
:test => :immediate,
|
13
|
+
:staging => :delayed_job,
|
14
|
+
:production => :delayed_job }[Rails.env.to_sym]
|
15
|
+
|
16
|
+
#Types of users in your app to segment notfications
|
17
|
+
config.user_kinds = %w(cool semi-cool lame)
|
18
|
+
|
19
|
+
# Configure image storage for Image File Uploader
|
20
|
+
config.image_storage = {:development => :file,
|
21
|
+
:test => :file,
|
22
|
+
:staging => :s3,
|
23
|
+
:production => :s3}[Rails.env.to_sym]
|
24
|
+
#Twitter Sharing Settings
|
25
|
+
config.twitter do |twitter|
|
26
|
+
twitter.consumer_key = 'xxx'
|
27
|
+
twitter.consumer_secret = 'xxx'
|
28
|
+
twitter.oauth_token = 'xxx'
|
29
|
+
twitter.oauth_token_secret = 'xxx'
|
30
|
+
end
|
31
|
+
|
32
|
+
# Facebook Sharing Setting
|
33
|
+
config.facebook_page_token = 'xxx'
|
34
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -30,9 +30,18 @@ en:
|
|
30
30
|
cancel: 'cancel'
|
31
31
|
insert_size: 'Size'
|
32
32
|
alt: 'Alt Text'
|
33
|
+
email_form:
|
34
|
+
notify: 'Notify by E-mail'
|
35
|
+
or: 'or'
|
33
36
|
post_mailer:
|
34
37
|
new_post:
|
35
38
|
greetings: 'Greetings'
|
39
|
+
read_more: 'Read More'
|
40
|
+
comment_mailer:
|
41
|
+
new_comment:
|
42
|
+
subject: "New comment in post '%{post}'"
|
43
|
+
hi: 'Hi'
|
44
|
+
commenter_says: 'had this to say about your post '
|
36
45
|
activerecord:
|
37
46
|
models:
|
38
47
|
'kublog/opst': 'Post'
|
File without changes
|
File without changes
|
@@ -11,7 +11,7 @@
|
|
11
11
|
#
|
12
12
|
# It's strongly recommended to check this file into your version control system.
|
13
13
|
|
14
|
-
ActiveRecord::Schema.define(:version =>
|
14
|
+
ActiveRecord::Schema.define(:version => 20110901205127) do
|
15
15
|
|
16
16
|
create_table "delayed_jobs", :force => true do |t|
|
17
17
|
t.integer "priority", :default => 0
|
@@ -60,20 +60,25 @@ ActiveRecord::Schema.define(:version => 20110822194341) do
|
|
60
60
|
t.datetime "updated_at"
|
61
61
|
end
|
62
62
|
|
63
|
+
create_table "kublog_notifications", :force => true do |t|
|
64
|
+
t.string "kind"
|
65
|
+
t.text "content"
|
66
|
+
t.integer "provider_id"
|
67
|
+
t.integer "post_id"
|
68
|
+
t.datetime "sent_at"
|
69
|
+
t.datetime "created_at"
|
70
|
+
t.text "roles"
|
71
|
+
t.integer "times_delivered", :default => 0
|
72
|
+
end
|
73
|
+
|
74
|
+
add_index "kublog_notifications", ["kind"], :name => "index_kublog_notifications_on_kind"
|
75
|
+
add_index "kublog_notifications", ["post_id"], :name => "index_kublog_notifications_on_post_id"
|
76
|
+
|
63
77
|
create_table "kublog_posts", :force => true do |t|
|
64
78
|
t.string "title"
|
65
79
|
t.text "body"
|
66
|
-
t.boolean "email_notify", :default => false
|
67
|
-
t.text "email_body"
|
68
|
-
t.integer "users_notified"
|
69
|
-
t.boolean "twitter_notify", :default => false
|
70
|
-
t.string "tweet_id"
|
71
|
-
t.string "tweet_text"
|
72
|
-
t.boolean "facebook_notify", :default => false
|
73
|
-
t.text "facebook_text"
|
74
80
|
t.integer "user_id"
|
75
81
|
t.integer "category_id"
|
76
|
-
t.string "intended_for"
|
77
82
|
t.string "slug"
|
78
83
|
t.datetime "created_at"
|
79
84
|
t.datetime "updated_at"
|
@@ -89,6 +94,7 @@ ActiveRecord::Schema.define(:version => 20110822194341) do
|
|
89
94
|
t.string "email"
|
90
95
|
t.string "password_digest"
|
91
96
|
t.boolean "admin", :default => false
|
97
|
+
t.string "kind", :default => "semi-cool"
|
92
98
|
t.datetime "created_at"
|
93
99
|
t.datetime "updated_at"
|
94
100
|
end
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
data/spec/factories.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
Factory.define :post, :class => Kublog::Post do |f|
|
2
|
+
f.title 'Nuevos features'
|
3
|
+
f.body '<p>Este mes estuvimos trabajando en nuevos features...</p>'
|
4
|
+
f.association :user, :factory => :user
|
5
|
+
end
|
6
|
+
|
7
|
+
Factory.define :category, :class=> Kublog::Category do |f|
|
8
|
+
f.sequence(:name) { |n| "#{rand(n*1000)} Nuevos Features" }
|
9
|
+
end
|
10
|
+
|
11
|
+
Factory.define :notification, :class=> Kublog::Notification do |f|
|
12
|
+
f.kind 'fake_kind'
|
13
|
+
f.content 'Awesome post just published'
|
14
|
+
f.association :post, :factory => :post
|
15
|
+
end
|
16
|
+
|
17
|
+
Factory.define :twitter_notification, :class => Kublog::Notification do |f|
|
18
|
+
f.kind 'twitter'
|
19
|
+
f.content 'tweet content'
|
20
|
+
f.association :post, :factory => :post
|
21
|
+
end
|
22
|
+
|
23
|
+
Factory.define :facebook_notification, :class => Kublog::Notification do |f|
|
24
|
+
f.kind 'facebook'
|
25
|
+
f.content 'wall post content'
|
26
|
+
f.association :post, :factory => :post
|
27
|
+
end
|
28
|
+
|
29
|
+
Factory.define :email_notification, :class => Kublog::Notification do |f|
|
30
|
+
f.kind 'email'
|
31
|
+
f.content 'email content for {{user}} with a link to the post {{link}}'
|
32
|
+
f.association :post, :factory => :post
|
33
|
+
end
|
34
|
+
|
35
|
+
Factory.define :user_comment, :class => Kublog::Comment do |f|
|
36
|
+
f.body 'Great stuff on the blog'
|
37
|
+
f.association :user, :factory => :user
|
38
|
+
f.association :post, :factory => :post
|
39
|
+
end
|
40
|
+
|
41
|
+
Factory.define :anonymous_comment, :class => Kublog::Comment do |f|
|
42
|
+
f.body 'Great stuff on the site'
|
43
|
+
f.author_name 'Adrian Cuadros'
|
44
|
+
f.author_email 'adrian@innku.com'
|
45
|
+
f.association :post, :factory => :post
|
46
|
+
end
|
47
|
+
|
48
|
+
Factory.define :user do |f|
|
49
|
+
f.name 'Adrian Cuadros'
|
50
|
+
f.sequence(:email) {|n| "adrian#{n}@innku.com" }
|
51
|
+
f.password 'secret'
|
52
|
+
f.password_confirmation 'secret'
|
53
|
+
end
|
54
|
+
|
Binary file
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Kublog::Author do
|
4
|
+
|
5
|
+
class TestAuthor < ActiveRecord::Base
|
6
|
+
set_table_name 'users'
|
7
|
+
end
|
8
|
+
|
9
|
+
describe '.included' do
|
10
|
+
|
11
|
+
before :all do
|
12
|
+
TestAuthor.send :include, Kublog::Author
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'sets the environment variable to the class that included the module' do
|
16
|
+
Kublog.author_class.should == TestAuthor.name
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should respond to posts' do
|
20
|
+
TestAuthor.new.should respond_to(:posts)
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|