From 71fe24096c612996cb2a827c919a4c88ae1e3495 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 25 Feb 2016 00:17:01 +0100 Subject: [PATCH] Adding a Mention model, test stubs --- .gitignore | 1 + .rspec | 3 ++ Gemfile | 8 +++- Gemfile.lock | 13 +++++- app/models/mention.rb | 7 +++ app/models/status.rb | 1 + app/services/post_status_service.rb | 23 ++-------- app/services/process_feed_service.rb | 6 +++ app/services/process_mentions_service.rb | 33 ++++++++++++++ db/migrate/20160224223247_create_mentions.rb | 12 +++++ db/schema.rb | 11 ++++- spec/controllers/atom_controller_spec.rb | 6 +++ spec/controllers/home_controller_spec.rb | 4 +- spec/controllers/profile_controller_spec.rb | 11 +++-- spec/controllers/xrd_controller_spec.rb | 6 +++ spec/helpers/routing_helper.rb | 15 +++++++ spec/models/account_spec.rb | 44 ++++++++++++++++++- spec/models/favourite_spec.rb | 28 +++++++++++- spec/models/follow_spec.rb | 24 +++++++++- spec/models/mention_spec.rb | 5 +++ spec/models/status_spec.rb | 32 +++++++++++++- spec/models/stream_entry_spec.rb | 11 +++++ spec/models/stream_spec.rb | 5 --- spec/models/user_spec.rb | 2 +- spec/rails_helper.rb | 16 +++++++ spec/services/fetch_feed_service_spec.rb | 5 +++ .../follow_remote_account_service_spec.rb | 5 +++ spec/services/follow_service_spec.rb | 5 +++ spec/services/post_status_service_spec.rb | 5 +++ spec/services/process_feed_service_spec.rb | 5 +++ .../process_interaction_service_spec.rb | 5 +++ .../services/process_mentions_service_spec.rb | 5 +++ spec/services/reblog_service_spec.rb | 5 +++ .../services/send_interaction_service_spec.rb | 5 +++ .../setup_local_account_service_spec.rb | 5 +++ spec/services/unfollow_service_spec.rb | 5 +++ spec/spec_helper.rb | 15 +++++++ spec/views/profile/show.html.haml_spec.rb | 5 --- 38 files changed, 355 insertions(+), 47 deletions(-) create mode 100644 .rspec create mode 100644 app/models/mention.rb create mode 100644 app/services/process_mentions_service.rb create mode 100644 db/migrate/20160224223247_create_mentions.rb create mode 100644 spec/helpers/routing_helper.rb create mode 100644 spec/models/mention_spec.rb create mode 100644 spec/models/stream_entry_spec.rb delete mode 100644 spec/models/stream_spec.rb create mode 100644 spec/rails_helper.rb create mode 100644 spec/services/fetch_feed_service_spec.rb create mode 100644 spec/services/follow_remote_account_service_spec.rb create mode 100644 spec/services/follow_service_spec.rb create mode 100644 spec/services/post_status_service_spec.rb create mode 100644 spec/services/process_feed_service_spec.rb create mode 100644 spec/services/process_interaction_service_spec.rb create mode 100644 spec/services/process_mentions_service_spec.rb create mode 100644 spec/services/reblog_service_spec.rb create mode 100644 spec/services/send_interaction_service_spec.rb create mode 100644 spec/services/setup_local_account_service_spec.rb create mode 100644 spec/services/unfollow_service_spec.rb create mode 100644 spec/spec_helper.rb delete mode 100644 spec/views/profile/show.html.haml_spec.rb diff --git a/.gitignore b/.gitignore index 050c9d95c..6d3b79652 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ /log/* !/log/.keep /tmp +coverage diff --git a/.rspec b/.rspec new file mode 100644 index 000000000..9a8e706d0 --- /dev/null +++ b/.rspec @@ -0,0 +1,3 @@ +--color +--require spec_helper +--format Fuubar diff --git a/Gemfile b/Gemfile index ef4273993..a922e7a9d 100644 --- a/Gemfile +++ b/Gemfile @@ -28,11 +28,15 @@ gem 'ostatus2' gem 'goldfinger' group :development, :test do - gem 'byebug' gem 'rspec-rails' gem 'quiet_assets' - gem 'nyan-cat-formatter' gem 'pry-rails' + gem 'nyan-cat-formatter' + gem 'fuubar' +end + +group :test do + gem 'simplecov', require: false end group :development do diff --git a/Gemfile.lock b/Gemfile.lock index 434d72f42..44d14929f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -50,7 +50,6 @@ GEM binding_of_caller (0.7.2) debug_inspector (>= 0.0.1) builder (3.2.2) - byebug (8.2.2) coderay (1.1.1) coercible (1.0.0) descendants_tracker (~> 0.0.1) @@ -66,6 +65,7 @@ GEM descendants_tracker (0.0.4) thread_safe (~> 0.3, >= 0.3.1) diff-lcs (1.2.5) + docile (1.1.5) domain_name (0.5.20160128) unf (>= 0.0.5, < 1.0.0) dotenv (2.1.0) @@ -75,6 +75,9 @@ GEM equalizer (0.0.11) erubis (2.7.0) execjs (2.6.0) + fuubar (2.0.0) + rspec (~> 3.0) + ruby-progressbar (~> 1.4) globalid (0.3.6) activesupport (>= 4.1.0) goldfinger (1.0.1) @@ -249,6 +252,11 @@ GEM json (~> 1.7, >= 1.7.7) rdoc (~> 4.0) sexp_processor (4.7.0) + simplecov (0.11.2) + docile (~> 1.1.0) + json (~> 1.8) + simplecov-html (~> 0.10.0) + simplecov-html (0.10.0) slop (3.6.0) spring (1.6.3) sprockets (3.5.2) @@ -292,9 +300,9 @@ DEPENDENCIES addressable better_errors binding_of_caller - byebug coffee-rails (~> 4.1.0) dotenv-rails + fuubar goldfinger grape grape-entity @@ -318,6 +326,7 @@ DEPENDENCIES rubocop sass-rails (~> 5.0) sdoc (~> 0.4.0) + simplecov spring sqlite3 therubyracer diff --git a/app/models/mention.rb b/app/models/mention.rb new file mode 100644 index 000000000..52f40e4b2 --- /dev/null +++ b/app/models/mention.rb @@ -0,0 +1,7 @@ +class Mention < ActiveRecord::Base + belongs_to :account, inverse_of: :mentions + belongs_to :status, inverse_of: :mentions + + validates :account, :status, presence: true + validates :account, uniqueness: { scope: :status } +end diff --git a/app/models/status.rb b/app/models/status.rb index 80719140e..d95870393 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -9,6 +9,7 @@ class Status < ActiveRecord::Base has_many :favourites, inverse_of: :status, dependent: :destroy has_many :reblogs, foreign_key: 'reblog_of_id', class_name: 'Status' has_many :replies, foreign_key: 'in_reply_to_id', class_name: 'Status' + has_many :mentioned_accounts, class_name: 'Mention', dependent: :destroy validates :account, presence: true validates :uri, uniqueness: true, unless: 'local?' diff --git a/app/services/post_status_service.rb b/app/services/post_status_service.rb index 3150a0bad..17cc8e323 100644 --- a/app/services/post_status_service.rb +++ b/app/services/post_status_service.rb @@ -6,30 +6,13 @@ class PostStatusService < BaseService # @return [Status] def call(account, text, in_reply_to = nil) status = account.statuses.create!(text: text, thread: in_reply_to) - - status.text.scan(Account::MENTION_RE).each do |match| - next if match.first.split('@').size == 1 - username, domain = match.first.split('@') - local_account = Account.find_by(username: username, domain: domain) - next unless local_account.nil? - follow_remote_account_service.("acct:#{match.first}") - end - - status.mentions.each do |mentioned_account| - next if mentioned_account.local? - send_interaction_service.(status.stream_entry, mentioned_account) - end - + process_mentions_service.(status) status end private - def follow_remote_account_service - @follow_remote_account_service ||= FollowRemoteAccountService.new - end - - def send_interaction_service - @send_interaction_service ||= SendInteractionService.new + def process_mentions_service + @process_mentions_service ||= ProcessMentionsService.new end end diff --git a/app/services/process_feed_service.rb b/app/services/process_feed_service.rb index 703938b46..210de8cdb 100644 --- a/app/services/process_feed_service.rb +++ b/app/services/process_feed_service.rb @@ -21,6 +21,8 @@ class ProcessFeedService < BaseService else add_post!(entry, status) end + + process_mentions_service.(status) unless status.new_record? end end @@ -120,4 +122,8 @@ class ProcessFeedService < BaseService def follow_remote_account_service @follow_remote_account_service ||= FollowRemoteAccountService.new end + + def process_mentions_service + @process_mentions_service ||= ProcessMentionsService.new + end end diff --git a/app/services/process_mentions_service.rb b/app/services/process_mentions_service.rb new file mode 100644 index 000000000..93866666a --- /dev/null +++ b/app/services/process_mentions_service.rb @@ -0,0 +1,33 @@ +class ProcessMentionsService < BaseService + # Scan status for mentions and fetch remote mentioned users, create + # local mention pointers, send Salmon notifications to mentioned + # remote users + # @param [Status] status + def call(status) + status.text.scan(Account::MENTION_RE).each do |match| + username, domain = match.first.split('@') + local_account = Account.find_by(username: username, domain: domain) + + if local_account.nil? + local_account = follow_remote_account_service.("acct:#{match.first}") + end + + local_account.mentions.first_or_create(status: status) + end + + status.mentions.each do |mentioned_account| + next if mentioned_account.local? + send_interaction_service.(status.stream_entry, mentioned_account) + end + end + + private + + def follow_remote_account_service + @follow_remote_account_service ||= FollowRemoteAccountService.new + end + + def send_interaction_service + @send_interaction_service ||= SendInteractionService.new + end +end diff --git a/db/migrate/20160224223247_create_mentions.rb b/db/migrate/20160224223247_create_mentions.rb new file mode 100644 index 000000000..095f6b7d2 --- /dev/null +++ b/db/migrate/20160224223247_create_mentions.rb @@ -0,0 +1,12 @@ +class CreateMentions < ActiveRecord::Migration + def change + create_table :mentions do |t| + t.integer :account_id + t.integer :status_id + + t.timestamps null: false + end + + add_index :mentions, [:account_id, :status_id], unique: true + end +end diff --git a/db/schema.rb b/db/schema.rb index 28b382906..7eb560d96 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160223171800) do +ActiveRecord::Schema.define(version: 20160224223247) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -54,6 +54,15 @@ ActiveRecord::Schema.define(version: 20160223171800) do add_index "follows", ["account_id", "target_account_id"], name: "index_follows_on_account_id_and_target_account_id", unique: true, using: :btree + create_table "mentions", force: :cascade do |t| + t.integer "account_id" + t.integer "status_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + add_index "mentions", ["account_id", "status_id"], name: "index_mentions_on_account_id_and_status_id", unique: true, using: :btree + create_table "statuses", force: :cascade do |t| t.string "uri" t.integer "account_id", null: false diff --git a/spec/controllers/atom_controller_spec.rb b/spec/controllers/atom_controller_spec.rb index ec14db007..6f04ad347 100644 --- a/spec/controllers/atom_controller_spec.rb +++ b/spec/controllers/atom_controller_spec.rb @@ -1,5 +1,11 @@ require 'rails_helper' RSpec.describe AtomController, type: :controller do + describe 'GET #user_stream' do + pending + end + describe 'GET #entry' do + pending + end end diff --git a/spec/controllers/home_controller_spec.rb b/spec/controllers/home_controller_spec.rb index e672b25e4..e609ab6be 100644 --- a/spec/controllers/home_controller_spec.rb +++ b/spec/controllers/home_controller_spec.rb @@ -1,5 +1,7 @@ require 'rails_helper' RSpec.describe HomeController, type: :controller do - + describe 'GET #index' do + pending + end end diff --git a/spec/controllers/profile_controller_spec.rb b/spec/controllers/profile_controller_spec.rb index 5904f5140..e4d124e29 100644 --- a/spec/controllers/profile_controller_spec.rb +++ b/spec/controllers/profile_controller_spec.rb @@ -1,12 +1,11 @@ require 'rails_helper' RSpec.describe ProfileController, type: :controller do - - describe "GET #show" do - it "returns http success" do - get :show - expect(response).to have_http_status(:success) - end + describe 'GET #show' do + pending end + describe 'GET #entry' do + pending + end end diff --git a/spec/controllers/xrd_controller_spec.rb b/spec/controllers/xrd_controller_spec.rb index 03a4b5800..669c02c40 100644 --- a/spec/controllers/xrd_controller_spec.rb +++ b/spec/controllers/xrd_controller_spec.rb @@ -1,5 +1,11 @@ require 'rails_helper' RSpec.describe XrdController, type: :controller do + describe 'GET #host_meta' do + pending + end + describe 'GET #webfinger' do + pending + end end diff --git a/spec/helpers/routing_helper.rb b/spec/helpers/routing_helper.rb new file mode 100644 index 000000000..9ccb4a38a --- /dev/null +++ b/spec/helpers/routing_helper.rb @@ -0,0 +1,15 @@ +require 'rails_helper' + +# Specs in this file have access to a helper object that includes +# the RoutingHelper. For example: +# +# describe RoutingHelper do +# describe "string concat" do +# it "concats two strings with spaces" do +# expect(helper.concat_strings("this","that")).to eq("this that") +# end +# end +# end +RSpec.describe RoutingHelper, type: :helper do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/models/account_spec.rb b/spec/models/account_spec.rb index 74410ece7..fbcc972cf 100644 --- a/spec/models/account_spec.rb +++ b/spec/models/account_spec.rb @@ -1,5 +1,47 @@ require 'rails_helper' RSpec.describe Account, type: :model do - pending "add some examples to (or delete) #{__FILE__}" + describe '#follow!' do + pending + end + + describe '#unfollow!' do + pending + end + + describe '#following?' do + pending + end + + describe '#local?' do + pending + end + + describe '#acct' do + pending + end + + describe '#subscribed?' do + pending + end + + describe '#keypair' do + pending + end + + describe '#subscription' do + pending + end + + describe '#object_type' do + pending + end + + describe '#title' do + pending + end + + describe '#content' do + pending + end end diff --git a/spec/models/favourite_spec.rb b/spec/models/favourite_spec.rb index 271aef4a4..ad803ec4b 100644 --- a/spec/models/favourite_spec.rb +++ b/spec/models/favourite_spec.rb @@ -1,5 +1,31 @@ require 'rails_helper' RSpec.describe Favourite, type: :model do - pending "add some examples to (or delete) #{__FILE__}" + describe '#verb' do + pending + end + + describe '#title' do + pending + end + + describe '#content' do + pending + end + + describe '#object_type' do + pending + end + + describe '#target' do + pending + end + + describe '#mentions' do + pending + end + + describe '#thread' do + pending + end end diff --git a/spec/models/follow_spec.rb b/spec/models/follow_spec.rb index 9b76332f6..edb084701 100644 --- a/spec/models/follow_spec.rb +++ b/spec/models/follow_spec.rb @@ -1,5 +1,27 @@ require 'rails_helper' RSpec.describe Follow, type: :model do - pending "add some examples to (or delete) #{__FILE__}" + describe '#verb' do + pending + end + + describe '#title' do + pending + end + + describe '#content' do + pending + end + + describe '#object_type' do + pending + end + + describe '#target' do + pending + end + + describe '#mentions' do + pending + end end diff --git a/spec/models/mention_spec.rb b/spec/models/mention_spec.rb new file mode 100644 index 000000000..5c91fda02 --- /dev/null +++ b/spec/models/mention_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe Mention, type: :model do + +end diff --git a/spec/models/status_spec.rb b/spec/models/status_spec.rb index c185efc3c..070e7b87f 100644 --- a/spec/models/status_spec.rb +++ b/spec/models/status_spec.rb @@ -1,5 +1,35 @@ require 'rails_helper' RSpec.describe Status, type: :model do - pending "add some examples to (or delete) #{__FILE__}" + describe '#local?' do + pending + end + + describe '#reblog?' do + pending + end + + describe '#reply?' do + pending + end + + describe '#mentions' do + pending + end + + describe '#verb' do + pending + end + + describe '#object_type' do + pending + end + + describe '#title' do + pending + end + + describe '#target' do + pending + end end diff --git a/spec/models/stream_entry_spec.rb b/spec/models/stream_entry_spec.rb new file mode 100644 index 000000000..6386cac0f --- /dev/null +++ b/spec/models/stream_entry_spec.rb @@ -0,0 +1,11 @@ +require 'rails_helper' + +RSpec.describe StreamEntry, type: :model do + describe '#targeted?' do + pending + end + + describe '#threaded?' do + pending + end +end diff --git a/spec/models/stream_spec.rb b/spec/models/stream_spec.rb deleted file mode 100644 index 7fc775652..000000000 --- a/spec/models/stream_spec.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'rails_helper' - -RSpec.describe Stream, type: :model do - pending "add some examples to (or delete) #{__FILE__}" -end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 47a31bb43..64de06749 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -1,5 +1,5 @@ require 'rails_helper' RSpec.describe User, type: :model do - pending "add some examples to (or delete) #{__FILE__}" + end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb new file mode 100644 index 000000000..0a04d560c --- /dev/null +++ b/spec/rails_helper.rb @@ -0,0 +1,16 @@ +ENV['RAILS_ENV'] ||= 'test' +require File.expand_path('../../config/environment', __FILE__) + +abort("The Rails environment is running in production mode!") if Rails.env.production? + +require 'spec_helper' +require 'rspec/rails' + +ActiveRecord::Migration.maintain_test_schema! + +RSpec.configure do |config| + config.fixture_path = "#{::Rails.root}/spec/fixtures" + config.use_transactional_fixtures = true + config.infer_spec_type_from_file_location! + config.filter_rails_from_backtrace! +end diff --git a/spec/services/fetch_feed_service_spec.rb b/spec/services/fetch_feed_service_spec.rb new file mode 100644 index 000000000..c6a3d389b --- /dev/null +++ b/spec/services/fetch_feed_service_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe FetchFeedService do + pending +end diff --git a/spec/services/follow_remote_account_service_spec.rb b/spec/services/follow_remote_account_service_spec.rb new file mode 100644 index 000000000..fbe7e767a --- /dev/null +++ b/spec/services/follow_remote_account_service_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe FollowRemoteAccountService do + pending +end diff --git a/spec/services/follow_service_spec.rb b/spec/services/follow_service_spec.rb new file mode 100644 index 000000000..ba393f5ab --- /dev/null +++ b/spec/services/follow_service_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe FollowService do + pending +end diff --git a/spec/services/post_status_service_spec.rb b/spec/services/post_status_service_spec.rb new file mode 100644 index 000000000..43d58719d --- /dev/null +++ b/spec/services/post_status_service_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe PostStatusService do + pending +end diff --git a/spec/services/process_feed_service_spec.rb b/spec/services/process_feed_service_spec.rb new file mode 100644 index 000000000..087979ded --- /dev/null +++ b/spec/services/process_feed_service_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe ProcessFeedService do + pending +end diff --git a/spec/services/process_interaction_service_spec.rb b/spec/services/process_interaction_service_spec.rb new file mode 100644 index 000000000..8624d0b0c --- /dev/null +++ b/spec/services/process_interaction_service_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe ProcessInteractionService do + pending +end diff --git a/spec/services/process_mentions_service_spec.rb b/spec/services/process_mentions_service_spec.rb new file mode 100644 index 000000000..ae86d17dc --- /dev/null +++ b/spec/services/process_mentions_service_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe ProcessMentionsService do + pending +end diff --git a/spec/services/reblog_service_spec.rb b/spec/services/reblog_service_spec.rb new file mode 100644 index 000000000..4e94d5a70 --- /dev/null +++ b/spec/services/reblog_service_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe ReblogService do + pending +end diff --git a/spec/services/send_interaction_service_spec.rb b/spec/services/send_interaction_service_spec.rb new file mode 100644 index 000000000..ae4ab01c5 --- /dev/null +++ b/spec/services/send_interaction_service_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe SendInteractionService do + pending +end diff --git a/spec/services/setup_local_account_service_spec.rb b/spec/services/setup_local_account_service_spec.rb new file mode 100644 index 000000000..709f170b6 --- /dev/null +++ b/spec/services/setup_local_account_service_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe SetupLocalAccountService do + pending +end diff --git a/spec/services/unfollow_service_spec.rb b/spec/services/unfollow_service_spec.rb new file mode 100644 index 000000000..60121b675 --- /dev/null +++ b/spec/services/unfollow_service_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe UnfollowService do + pending +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 000000000..d6c1dc95b --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,15 @@ +require 'simplecov' + +SimpleCov.start 'rails' do + add_group "Services", "app/services" +end + +RSpec.configure do |config| + config.expect_with :rspec do |expectations| + expectations.include_chain_clauses_in_custom_matcher_descriptions = true + end + + config.mock_with :rspec do |mocks| + mocks.verify_partial_doubles = true + end +end diff --git a/spec/views/profile/show.html.haml_spec.rb b/spec/views/profile/show.html.haml_spec.rb deleted file mode 100644 index 778dcff32..000000000 --- a/spec/views/profile/show.html.haml_spec.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'rails_helper' - -RSpec.describe "profile/show.html.haml", type: :view do - pending "add some examples to (or delete) #{__FILE__}" -end