soc_med 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +148 -0
  4. data/Rakefile +32 -0
  5. data/app/assets/config/soc_med_manifest.js +1 -0
  6. data/app/assets/stylesheets/soc_med/application.css +15 -0
  7. data/app/blueprints/base_blueprint.rb +6 -0
  8. data/app/blueprints/blocks/overview_blueprint.rb +7 -0
  9. data/app/blueprints/follows/overview_blueprint.rb +7 -0
  10. data/app/blueprints/likes/overview_blueprint.rb +7 -0
  11. data/app/blueprints/reports/overview_blueprint.rb +7 -0
  12. data/app/controllers/soc_med/application_controller.rb +24 -0
  13. data/app/controllers/soc_med/blocks_controller.rb +28 -0
  14. data/app/controllers/soc_med/follows_controller.rb +28 -0
  15. data/app/controllers/soc_med/likes_controller.rb +28 -0
  16. data/app/controllers/soc_med/reports_controller.rb +29 -0
  17. data/app/errors/soc_med/base.rb +4 -0
  18. data/app/errors/soc_med/blocks/already_exists_error.rb +7 -0
  19. data/app/errors/soc_med/follows/already_exists_error.rb +7 -0
  20. data/app/errors/soc_med/likes/already_exists_error.rb +7 -0
  21. data/app/helpers/soc_med/application_helper.rb +4 -0
  22. data/app/jobs/soc_med/application_job.rb +4 -0
  23. data/app/mailers/soc_med/application_mailer.rb +6 -0
  24. data/app/models/soc_med/application_record.rb +5 -0
  25. data/app/models/soc_med/block.rb +16 -0
  26. data/app/models/soc_med/concerns/soc_med_helper.rb +17 -0
  27. data/app/models/soc_med/follow.rb +35 -0
  28. data/app/models/soc_med/like.rb +38 -0
  29. data/app/models/soc_med/report.rb +16 -0
  30. data/app/views/layouts/soc_med/application.html.erb +15 -0
  31. data/config/routes.rb +6 -0
  32. data/db/migrate/20200605151411_create_soc_med_likes.rb +12 -0
  33. data/db/migrate/20200605151423_create_soc_med_follows.rb +12 -0
  34. data/db/migrate/20200605151437_create_soc_med_blocks.rb +12 -0
  35. data/db/migrate/20200605151450_create_soc_med_reports.rb +12 -0
  36. data/lib/soc_med.rb +21 -0
  37. data/lib/soc_med/concerns/blockable.rb +34 -0
  38. data/lib/soc_med/concerns/followable.rb +34 -0
  39. data/lib/soc_med/concerns/likeable.rb +34 -0
  40. data/lib/soc_med/concerns/reportable.rb +33 -0
  41. data/lib/soc_med/engine.rb +5 -0
  42. data/lib/soc_med/services/base_service.rb +37 -0
  43. data/lib/soc_med/services/blocks/block_base.rb +46 -0
  44. data/lib/soc_med/services/blocks/create.rb +27 -0
  45. data/lib/soc_med/services/blocks/destroy.rb +27 -0
  46. data/lib/soc_med/services/failure.rb +16 -0
  47. data/lib/soc_med/services/follows/create.rb +27 -0
  48. data/lib/soc_med/services/follows/destroy.rb +27 -0
  49. data/lib/soc_med/services/follows/follow_base.rb +46 -0
  50. data/lib/soc_med/services/likes/create.rb +25 -0
  51. data/lib/soc_med/services/likes/destroy.rb +26 -0
  52. data/lib/soc_med/services/likes/like_base.rb +46 -0
  53. data/lib/soc_med/services/no_trigger.rb +10 -0
  54. data/lib/soc_med/services/reports/base_report.rb +46 -0
  55. data/lib/soc_med/services/reports/create.rb +27 -0
  56. data/lib/soc_med/services/reports/destroy.rb +27 -0
  57. data/lib/soc_med/services/success.rb +16 -0
  58. data/lib/soc_med/version.rb +3 -0
  59. data/lib/tasks/soc_med_tasks.rake +4 -0
  60. metadata +180 -0
@@ -0,0 +1,4 @@
1
+ module SocMed
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module SocMed
2
+ class ApplicationJob < ActiveJob::Base
3
+ end
4
+ end
@@ -0,0 +1,6 @@
1
+ module SocMed
2
+ class ApplicationMailer < ActionMailer::Base
3
+ default from: 'from@example.com'
4
+ layout 'mailer'
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ module SocMed
2
+ class ApplicationRecord < ActiveRecord::Base
3
+ self.abstract_class = true
4
+ end
5
+ end
@@ -0,0 +1,16 @@
1
+ module SocMed
2
+ class Block < ApplicationRecord
3
+ belongs_to :target, polymorphic: true
4
+ belongs_to :owner, polymorphic: true
5
+
6
+ before_validation :raise_already_liked_error_if_required, on: :create
7
+
8
+ validates :target_id, uniqueness: {scope: %i[target_type owner_id owner_type], message: "has already been blocked."}
9
+
10
+ private
11
+
12
+ def raise_already_followd_error_if_required
13
+ raise SocMed::Follows::AlreadyExistsError.new("#{owner_type} has already blocked that #{target_type}") if owner.blockable_objects.exists?(target: target)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,17 @@
1
+ module SocMed
2
+ module Concerns
3
+ module SocMedHelper
4
+
5
+ def raise_not_implemented_error
6
+ raise NotImplementedError unless target.respond_to?("number_of_#{self.class.to_s.underscore.split('/')[-1].pluralize}")
7
+ end
8
+
9
+ def update_count(attribute, operator)
10
+ count = target.send(attribute).send(operator, 1)
11
+
12
+ target.update("#{attribute}" => count)
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,35 @@
1
+ module SocMed
2
+ class Follow < ApplicationRecord
3
+ include SocMed::SocMedHelper
4
+
5
+ belongs_to :target, polymorphic: true
6
+ belongs_to :owner, polymorphic: true
7
+
8
+
9
+ before_validation :raise_already_liked_error_if_required, on: :create
10
+ before_validation :raise_not_implemented_error, on: :create
11
+ before_commit :increment_number_of_follows, on: :create
12
+ before_destroy :decrement_number_of_follows
13
+
14
+ validates :target_id, uniqueness: {scope: %i[target_type owner_id owner_type], message: "has already been followed."}
15
+
16
+
17
+ private
18
+
19
+ def increment_number_of_follows
20
+ raise_not_implemented_error
21
+
22
+ update_count(:number_of_follows, :+)
23
+ end
24
+
25
+ def decrement_number_of_follows
26
+ raise_not_implemented_error
27
+
28
+ update_count(:number_of_follows, :-)
29
+ end
30
+
31
+ def raise_already_followd_error_if_required
32
+ raise SocMed::Follows::AlreadyExistsError.new("#{owner_type} has already followed that #{target_type}") if owner.followable_objects.exists?(target: target)
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,38 @@
1
+ require_relative './concerns/soc_med_helper'
2
+
3
+ module SocMed
4
+ class Like < ::ApplicationRecord
5
+ include Concerns::SocMedHelper
6
+
7
+ belongs_to :target, polymorphic: true
8
+ belongs_to :owner, polymorphic: true
9
+
10
+ before_validation :raise_already_liked_error_if_required, on: :create
11
+ before_validation :raise_not_implemented_error, on: :create
12
+ before_commit :increment_number_of_likes, on: :create
13
+ before_destroy :decrement_number_of_likes
14
+
15
+ validates :target_id, uniqueness: {scope: %i[target_type owner_id owner_type], message: "has already been liked."}
16
+
17
+
18
+ private
19
+
20
+ def increment_number_of_likes
21
+ raise_not_implemented_error
22
+
23
+ update_count(:number_of_likes, :+)
24
+ end
25
+
26
+ def decrement_number_of_likes
27
+ raise_not_implemented_error
28
+
29
+ update_count(:number_of_likes, :-)
30
+ end
31
+
32
+ private
33
+
34
+ def raise_already_liked_error_if_required
35
+ raise SocMed::Likes::AlreadyExistsError.new("#{owner_type} has already liked that #{target_type}") if owner.likeable_objects.exists?(target: target)
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,16 @@
1
+ module SocMed
2
+ class Report < ApplicationRecord
3
+ belongs_to :target, polymorphic: true
4
+ belongs_to :owner, polymorphic: true
5
+
6
+ before_validation :raise_already_liked_error_if_required, on: :create
7
+
8
+ validates :target_id, uniqueness: {scope: %i[target_type owner_id owner_type], message: "has already been reported."}
9
+
10
+ private
11
+
12
+ def raise_already_followd_error_if_required
13
+ raise SocMed::Reports::AlreadyExistsError.new("#{owner_type} has already reported that #{target_type}") if owner.reportable_objects.exists?(target: target)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,15 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Soc med</title>
5
+ <%= csrf_meta_tags %>
6
+ <%= csp_meta_tag %>
7
+
8
+ <%= stylesheet_link_tag "soc_med/application", media: "all" %>
9
+ </head>
10
+ <body>
11
+
12
+ <%= yield %>
13
+
14
+ </body>
15
+ </html>
@@ -0,0 +1,6 @@
1
+ SocMed::Engine.routes.draw do
2
+ resource :likes, only: %i[create destroy]
3
+ resources :follows, only: %i[create destroy]
4
+ resources :blocks, only: %i[create destroy]
5
+ resources :reports, only: %i[create destroy]
6
+ end
@@ -0,0 +1,12 @@
1
+ class CreateSocMedLikes < ActiveRecord::Migration[6.0]
2
+ def change
3
+ create_table :soc_med_likes do |t|
4
+ t.references :target, null: false, polymorphic: true
5
+ t.references :owner, null: false, polymorphic: true
6
+
7
+ t.timestamps
8
+ end
9
+
10
+ add_index :soc_med_likes, %i[target_id target_type owner_id owner_type], unique: true, name: :idx_soc_med_likes_on_target_and_owner
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ class CreateSocMedFollows < ActiveRecord::Migration[6.0]
2
+ def change
3
+ create_table :soc_med_follows do |t|
4
+ t.references :target, null: false, polymorphic: true
5
+ t.references :owner, null: false, polymorphic: true
6
+
7
+ t.timestamps
8
+ end
9
+
10
+ add_index :soc_med_follows, %i[target_id target_type owner_id owner_type], unique: true, name: :idx_soc_med_follows_on_target_and_owner
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ class CreateSocMedBlocks < ActiveRecord::Migration[6.0]
2
+ def change
3
+ create_table :soc_med_blocks do |t|
4
+ t.references :target, null: false, polymorphic: true
5
+ t.references :owner, null: false, polymorphic: true
6
+
7
+ t.timestamps
8
+ end
9
+
10
+ add_index :soc_med_blocks, %i[target_id target_type owner_id owner_type], unique: true, name: :idx_soc_med_blocks_on_target_and_owner
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ class CreateSocMedReports < ActiveRecord::Migration[6.0]
2
+ def change
3
+ create_table :soc_med_reports do |t|
4
+ t.references :target, null: false, polymorphic: true
5
+ t.references :owner, null: false, polymorphic: true
6
+
7
+ t.timestamps
8
+ end
9
+
10
+ add_index :soc_med_reports, %i[target_id target_type owner_id owner_type], unique: true, name: :idx_soc_med_reports_on_target_and_owner
11
+ end
12
+ end
@@ -0,0 +1,21 @@
1
+ require "soc_med/engine"
2
+ require 'soc_med/concerns/likeable'
3
+ require 'soc_med/concerns/followable'
4
+ require 'soc_med/concerns/blockable'
5
+ require 'soc_med/concerns/reportable'
6
+ require 'soc_med/services/likes/create'
7
+ require 'soc_med/services/likes/destroy'
8
+ require 'soc_med/services/follows/create'
9
+ require 'soc_med/services/follows/destroy'
10
+ require 'soc_med/services/reports/create'
11
+ require 'soc_med/services/reports/destroy'
12
+ require 'soc_med/services/blocks/create'
13
+ require 'soc_med/services/blocks/destroy'
14
+
15
+ module SocMed
16
+ mattr_accessor :owner_class
17
+
18
+ def self.owner_class
19
+ @@owner_class.to_s.classify.constantize
20
+ end
21
+ end
@@ -0,0 +1,34 @@
1
+ module SocMed
2
+ module Concerns
3
+ module Blockable
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ has_many :blocks, class_name: 'SocMed::Block', as: :target, dependent: :destroy
8
+ has_many :blockable_objects, class_name: 'SocMed::Block', as: :owner, dependent: :destroy
9
+ end
10
+
11
+ class_methods do
12
+ def blockable(*attributes)
13
+ attributes = [attributes] unless attributes.is_a?(Array)
14
+
15
+ attributes.each do |attribute|
16
+ class_eval "has_many :by_blocking_#{attribute}, -> { order(created_at: :desc) }, class_name: 'SocMed::Block', source: :owner, source_type: '#{attribute.to_s.classify}', foreign_key: :owner_id, dependent: :destroy"
17
+ class_eval "has_many :blocked_#{attribute}, through: :by_blocking_#{attribute}, source: :target, source_type: '#{attribute.to_s.classify}'"
18
+ end
19
+ end
20
+
21
+ def blocker(*attributes)
22
+ attributes = [attributes] unless attributes.is_a?(Array)
23
+
24
+ attributes.each do |attribute|
25
+ class_eval "has_many :by_blocked_#{attribute}, -> { order(created_at: :desc) }, class_name: 'SocMed::Block', source: :target, source_type: '#{attribute.to_s.classify}', foreign_key: :target_id, dependent: :destroy"
26
+ class_eval "has_many :blocked_by_#{attribute}, through: :by_blocked_#{attribute}, source: :owner, source_type: '#{attribute.to_s.classify}'"
27
+ end
28
+ end
29
+
30
+ end
31
+
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,34 @@
1
+ module SocMed
2
+ module Concerns
3
+ module Followable
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ has_many :follows, class_name: 'SocMed::Follow', as: :target, dependent: :destroy
8
+ has_many :followable_objects, class_name: 'SocMed::Follow', as: :owner, dependent: :destroy
9
+ end
10
+
11
+ class_methods do
12
+ def followable(*attributes)
13
+ attributes = [attributes] unless attributes.is_a?(Array)
14
+
15
+ attributes.each do |attribute|
16
+ class_eval "has_many :by_following_#{attribute}, -> { order(created_at: :desc) }, class_name: 'SocMed::Follow', source: :owner, source_type: '#{attribute.to_s.classify}', foreign_key: :owner_id, dependent: :destroy"
17
+ class_eval "has_many :followed_#{attribute}, through: :by_following_#{attribute}, source: :target, source_type: '#{attribute.to_s.classify}'"
18
+ end
19
+ end
20
+
21
+ def follower(*attributes)
22
+ attributes = [attributes] unless attributes.is_a?(Array)
23
+
24
+ attributes.each do |attribute|
25
+ class_eval "has_many :by_followed_#{attribute}, -> { order(created_at: :desc) }, class_name: 'SocMed::Follow', source: :target, source_type: '#{attribute.to_s.classify}', foreign_key: :target_id, dependent: :destroy"
26
+ class_eval "has_many :followed_by_#{attribute}, through: :by_followed_#{attribute}, source: :owner, source_type: '#{attribute.to_s.classify}'"
27
+ end
28
+ end
29
+
30
+ end
31
+
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,34 @@
1
+ module SocMed
2
+ module Concerns
3
+ module Likeable
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ has_many :likes, class_name: 'SocMed::Like', as: :target, dependent: :destroy
8
+ has_many :likeable_objects, class_name: 'SocMed::Like', as: :owner, dependent: :destroy
9
+ end
10
+
11
+ class_methods do
12
+ def likeable(*attributes)
13
+ attributes = [attributes] unless attributes.is_a?(Array)
14
+
15
+ attributes.each do |attribute|
16
+ class_eval "has_many :by_liking_#{attribute}, -> { order(created_at: :desc) }, class_name: 'SocMed::Like', source: :owner, source_type: '#{attribute.to_s.classify}', foreign_key: :owner_id, dependent: :destroy"
17
+ class_eval "has_many :liked_#{attribute}, through: :by_liking_#{attribute}, source: :target, source_type: '#{attribute.to_s.classify}'"
18
+ end
19
+ end
20
+
21
+ def liker(*attributes)
22
+ attributes = [attributes] unless attributes.is_a?(Array)
23
+
24
+ attributes.each do |attribute|
25
+ class_eval "has_many :by_liked_#{attribute}, -> { order(created_at: :desc) }, class_name: 'SocMed::Like', source: :target, source_type: '#{attribute.to_s.classify}', foreign_key: :target_id, dependent: :destroy"
26
+ class_eval "has_many :liked_by_#{attribute}, through: :by_liked_#{attribute}, source: :owner, source_type: '#{attribute.to_s.classify}'"
27
+ end
28
+ end
29
+
30
+ end
31
+
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,33 @@
1
+ module SocMed
2
+ module Concerns
3
+ module Reportable
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ has_many :reports, class_name: 'SocMed::Report', as: :target, dependent: :destroy
8
+ has_many :reportable_objects, class_name: 'SocMed::Report', as: :owner, dependent: :destroy
9
+ end
10
+
11
+ class_methods do
12
+ def reportable(*attributes)
13
+ attributes = [attributes] unless attributes.is_a?(Array)
14
+
15
+ attributes.each do |attribute|
16
+ class_eval "has_many :by_reporting_#{attribute}, -> { order(created_at: :desc) }, class_name: 'SocMed::Report', source: :owner, source_type: '#{attribute.to_s.classify}', foreign_key: :owner_id, dependent: :destroy"
17
+ class_eval "has_many :reported_#{attribute}, through: :by_reporting_#{attribute}, source: :target, source_type: '#{attribute.to_s.classify}'"
18
+ end
19
+ end
20
+
21
+ def reporter(*attributes)
22
+ attributes = [attributes] unless attributes.is_a?(Array)
23
+
24
+ attributes.each do |attribute|
25
+ class_eval "has_many :by_reported_#{attribute}, -> { order(created_at: :desc) }, class_name: 'SocMed::Report', source: :target, source_type: '#{attribute.to_s.classify}', foreign_key: :target_id, dependent: :destroy"
26
+ class_eval "has_many :reported_by_#{attribute}, through: :by_reported_#{attribute}, source: :owner, source_type: '#{attribute.to_s.classify}'"
27
+ end
28
+ end
29
+ end
30
+
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,5 @@
1
+ module SocMed
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace SocMed
4
+ end
5
+ end
@@ -0,0 +1,37 @@
1
+ require 'active_record'
2
+ require 'soc_med/services/no_trigger'
3
+ require 'soc_med/services/success'
4
+ require 'soc_med/services/failure'
5
+
6
+ module SocMed
7
+ module Services
8
+ class BaseService
9
+ attr_reader :params
10
+
11
+ def self.call(params, &block)
12
+ new( params).call(&block)
13
+ end
14
+
15
+ def initialize(params)
16
+ @params = params
17
+ end
18
+
19
+ private_class_method :new
20
+
21
+ def call(&block)
22
+ raise NotImplementedError
23
+ end
24
+
25
+ private
26
+
27
+ def target
28
+ raise NotImplementedError
29
+ end
30
+
31
+ def owner
32
+ raise NotImplementedError
33
+ end
34
+
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,46 @@
1
+ require_relative '../base_service'
2
+
3
+ module SocMed
4
+ module Services
5
+ module Blocks
6
+ class BlockBase < BaseService
7
+
8
+ private
9
+
10
+ def block
11
+ block = owner.blockable_objects.find_by(target: target)
12
+ raise ActiveRecord::RecordNotFound unless block
13
+
14
+ block
15
+ end
16
+
17
+ def target
18
+ target_type, target_id = target_info
19
+ target = target_type.classify.constantize.find_by(id: target_id)
20
+ raise ActiveRecord::RecordNotFound unless target
21
+
22
+ target
23
+ end
24
+
25
+ def target_info
26
+ return params[:block][:target_type], params[:block][:target_id] unless params[:block].nil?
27
+ return params[:target_type], params[:target_id]
28
+ end
29
+
30
+ def owner
31
+ owner_type, owner_id = owner_info
32
+ owner = SocMed.owner_class.find_by(id: owner_id)
33
+ raise ActiveRecord::RecordNotFound unless owner
34
+
35
+ owner
36
+ end
37
+
38
+ def owner_info
39
+ return params[:block][:owner_type], params[:block][:owner_id] unless params[:block].nil?
40
+ return params[:owner_type], params[:owner_id]
41
+ end
42
+
43
+ end
44
+ end
45
+ end
46
+ end