acts-as-messageable 0.4.11 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/.dockerignore +1 -0
  3. data/.rubocop.yml +19 -0
  4. data/.rubocop_todo.yml +33 -0
  5. data/.travis.yml +40 -4
  6. data/Appraisals +24 -11
  7. data/Dockerfile +13 -0
  8. data/Gemfile +11 -4
  9. data/Gemfile.lock +94 -63
  10. data/README.md +30 -12
  11. data/Rakefile +4 -0
  12. data/VERSION +1 -1
  13. data/acts-as-messageable.gemspec +62 -49
  14. data/docker-compose.yml +73 -0
  15. data/gemfiles/rails_3.2.gemfile +17 -10
  16. data/gemfiles/rails_4.2.gemfile +24 -0
  17. data/gemfiles/rails_5.2.gemfile +17 -10
  18. data/gemfiles/rails_6.0.gemfile +17 -10
  19. data/gemfiles/rails_master.gemfile +23 -0
  20. data/lib/acts-as-messageable.rb +2 -17
  21. data/lib/acts_as_messageable.rb +23 -0
  22. data/lib/{acts-as-messageable → acts_as_messageable}/message.rb +25 -8
  23. data/lib/{acts-as-messageable → acts_as_messageable}/model.rb +27 -30
  24. data/lib/{acts-as-messageable → acts_as_messageable}/rails3.rb +7 -5
  25. data/lib/{acts-as-messageable → acts_as_messageable}/rails4.rb +8 -4
  26. data/lib/acts_as_messageable/rails6.rb +31 -0
  27. data/lib/acts_as_messageable/railtie.rb +11 -0
  28. data/lib/{acts-as-messageable → acts_as_messageable}/relation.rb +4 -2
  29. data/lib/{acts-as-messageable → acts_as_messageable}/scopes.rb +16 -12
  30. data/lib/generators/{acts-as-messageable → acts_as_messageable}/migration/migration_generator.rb +16 -2
  31. data/lib/generators/{acts-as-messageable → acts_as_messageable}/migration/templates/migration.rb +3 -3
  32. data/lib/generators/acts_as_messageable/migration/templates/migration_indexes.rb +11 -0
  33. data/lib/generators/acts_as_messageable/migration/templates/migration_opened_as_datetime.rb +15 -0
  34. data/lib/generators/{acts-as-messageable → acts_as_messageable}/migration/templates/migration_permanent.rb +1 -1
  35. data/spec/{acts-as-messageable_spec.rb → acts_as_messageable_spec.rb} +77 -5
  36. data/spec/{custom-class_spec.rb → custom_class_spec.rb} +14 -5
  37. data/spec/{custom-required_spec.rb → custom_required_spec.rb} +3 -1
  38. data/spec/{group-messages_spec.rb → group_messages_spec.rb} +4 -2
  39. data/spec/migrations_spec.rb +75 -0
  40. data/spec/spec_helper.rb +30 -37
  41. data/spec/support/admin.rb +2 -0
  42. data/spec/support/custom_message.rb +5 -0
  43. data/spec/support/custom_message_uuid.rb +5 -0
  44. data/spec/support/custom_search_user.rb +5 -0
  45. data/spec/support/men.rb +6 -0
  46. data/spec/support/send_message.rb +2 -0
  47. data/spec/support/table_schema.rb +35 -0
  48. data/spec/support/user.rb +2 -3
  49. data/spec/support/uuid_user.rb +6 -0
  50. metadata +113 -31
  51. data/gemfiles/rails_3.2.gemfile.lock +0 -153
  52. data/gemfiles/rails_4.2.11.gemfile +0 -16
  53. data/gemfiles/rails_4.2.11.gemfile.lock +0 -157
  54. data/gemfiles/rails_5.2.gemfile.lock +0 -155
  55. data/gemfiles/rails_6.0.gemfile.lock +0 -155
  56. data/lib/acts-as-messageable/railtie.rb +0 -13
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This file was generated by Appraisal
4
+
5
+ source 'http://rubygems.org'
6
+
7
+ gem 'activerecord', git: 'https://github.com/rails/rails.git'
8
+ gem 'activesupport', git: 'https://github.com/rails/rails.git'
9
+ gem 'ancestry'
10
+ gem 'railties', git: 'https://github.com/rails/rails.git'
11
+
12
+ group :development do
13
+ gem 'appraisal'
14
+ gem 'coveralls', require: false
15
+ gem 'jeweler'
16
+ gem 'pg'
17
+ gem 'pry'
18
+ gem 'rspec'
19
+ gem 'rubocop', require: false
20
+ gem 'sqlite3'
21
+ gem 'timecop'
22
+ gem 'yard'
23
+ end
@@ -1,18 +1,3 @@
1
- module ActsAsMessageable
2
- autoload :Model, 'acts-as-messageable/model'
3
- autoload :Scopes, 'acts-as-messageable/scopes'
4
- autoload :Message, 'acts-as-messageable/message'
5
- autoload :Relation, 'acts-as-messageable/relation'
6
- autoload :Rails3, 'acts-as-messageable/rails3'
7
- autoload :Rails4, 'acts-as-messageable/rails4'
1
+ # frozen_string_literal: true
8
2
 
9
- def self.rails_api
10
- if Rails::VERSION::MAJOR >= 4
11
- Rails4
12
- else
13
- Rails3
14
- end
15
- end
16
- end
17
-
18
- require 'acts-as-messageable/railtie'
3
+ require 'acts_as_messageable'
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActsAsMessageable
4
+ autoload :Model, 'acts_as_messageable/model'
5
+ autoload :Scopes, 'acts_as_messageable/scopes'
6
+ autoload :Message, 'acts_as_messageable/message'
7
+ autoload :Relation, 'acts_as_messageable/relation'
8
+ autoload :Rails3, 'acts_as_messageable/rails3'
9
+ autoload :Rails4, 'acts_as_messageable/rails4'
10
+ autoload :Rails6, 'acts_as_messageable/rails6'
11
+
12
+ def self.rails_api
13
+ if Rails::VERSION::MAJOR >= 6
14
+ Rails6
15
+ elsif Rails::VERSION::MAJOR >= 4
16
+ Rails4
17
+ else
18
+ Rails3
19
+ end
20
+ end
21
+ end
22
+
23
+ require 'acts_as_messageable/railtie'
@@ -1,35 +1,52 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'ancestry'
2
4
 
3
5
  module ActsAsMessageable
4
6
  class Message < ::ActiveRecord::Base
5
7
  include ActsAsMessageable::Scopes
6
8
 
9
+ has_ancestry
10
+
7
11
  belongs_to :received_messageable, polymorphic: true
8
- belongs_to :sent_messageable, polymorphic: true
12
+ belongs_to :sent_messageable, polymorphic: true
9
13
 
10
- attr_accessor :removed, :restored
11
- cattr_accessor :required
14
+ attr_accessor :removed, :restored
12
15
 
16
+ cattr_accessor :required
17
+
18
+ ActsAsMessageable.rails_api.new(self).attr_accessible(
19
+ :topic, :body, :opened, :opened_at, :recipient_permanent_delete,
20
+ :recipient_delete, :sender_permanent_delete, :sender_delete
21
+ )
13
22
  ActsAsMessageable.rails_api.new(self).default_scope('created_at desc')
14
23
 
15
24
  def open?
16
25
  opened?
17
26
  end
18
27
 
28
+ def opened?
29
+ opened_at.present? || super
30
+ end
31
+
19
32
  def open
20
- update_attributes!(opened: true)
33
+ ActsAsMessageable.rails_api.new(self).update_attributes!(opened_at: DateTime.now)
34
+ ActsAsMessageable.rails_api.new(self).update_attributes!(opened: true)
21
35
  end
36
+
22
37
  alias mark_as_read open
23
- alias read open
38
+ alias read open
24
39
 
25
40
  def close
26
- update_attributes!(opened: false)
41
+ ActsAsMessageable.rails_api.new(self).update_attributes!(opened_at: nil)
42
+ ActsAsMessageable.rails_api.new(self).update_attributes!(opened: false)
27
43
  end
44
+
28
45
  alias mark_as_unread close
29
- alias unread close
46
+ alias unread close
30
47
 
31
48
  alias from sent_messageable
32
- alias to received_messageable
49
+ alias to received_messageable
33
50
 
34
51
  def real_receiver(user)
35
52
  user == from ? to : from
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActsAsMessageable
2
4
  module Model
3
5
  def self.included(base)
@@ -5,49 +7,46 @@ module ActsAsMessageable
5
7
  end
6
8
 
7
9
  module ClassMethods
8
- mattr_accessor :messages_class_name, :group_messages
9
-
10
10
  # Method make ActiveRecord::Base object messageable
11
11
  # @param [Symbol] :table_name - table name for messages
12
12
  # @param [String] :class_name - message class name
13
13
  # @param [Array, Symbol] :required - required fields in message
14
14
  # @param [Symbol] :dependent - dependent option from ActiveRecord has_many method
15
+ # @param [Symbol] :search_scope - name of a scope for a full text search
15
16
  def acts_as_messageable(options = {})
16
17
  default_options = {
17
18
  table_name: 'messages',
18
19
  class_name: 'ActsAsMessageable::Message',
19
20
  required: %i[topic body],
20
21
  dependent: :nullify,
21
- group_messages: false
22
+ group_messages: false,
23
+ search_scope: :search
22
24
  }
23
25
  options = default_options.merge(options)
24
26
 
25
- has_many :received_messages_relation,
26
- as: :received_messageable,
27
- class_name: options[:class_name],
28
- dependent: options[:dependent]
29
- has_many :sent_messages_relation,
30
- as: :sent_messageable,
31
- class_name: options[:class_name],
32
- dependent: options[:dependent]
27
+ mattr_accessor(:messages_class_name, :group_messages)
28
+
29
+ has_many :received_messages_relation,
30
+ as: :received_messageable,
31
+ class_name: options[:class_name],
32
+ dependent: options[:dependent]
33
+ has_many :sent_messages_relation,
34
+ as: :sent_messageable,
35
+ class_name: options[:class_name],
36
+ dependent: options[:dependent]
33
37
 
34
38
  self.messages_class_name = options[:class_name].constantize
35
39
  messages_class_name.has_ancestry
36
40
 
37
- if messages_class_name.respond_to?(:table_name=)
38
- messages_class_name.table_name = options[:table_name]
39
- messages_class_name.initialize_scopes
40
- else
41
- messages_class_name.set_table_name(options[:table_name])
42
- ActiveSupport::Deprecation.warn("Calling set_table_name is deprecated. Please use `self.table_name = 'the_name'` instead.")
43
- end
41
+ messages_class_name.table_name = options[:table_name]
42
+ messages_class_name.initialize_scopes(options[:search_scope])
44
43
 
45
44
  messages_class_name.required = Array.wrap(options[:required])
46
45
  messages_class_name.validates_presence_of messages_class_name.required
47
46
  self.group_messages = options[:group_messages]
48
47
 
49
48
  include ActsAsMessageable::Model::InstanceMethods
50
- end
49
+ end
51
50
 
52
51
  # Method recognize real object class
53
52
  # @return [ActiveRecord::Base] class or relation object
@@ -122,9 +121,7 @@ module ActsAsMessageable
122
121
  #
123
122
  # @return [ActsAsMessageable::Message] the message object
124
123
  def send_message!(to, *args)
125
- send_message(to, *args).tap do |message|
126
- message.save!
127
- end
124
+ send_message(to, *args).tap(&:save!)
128
125
  end
129
126
 
130
127
  # Reply to given message
@@ -136,13 +133,13 @@ module ActsAsMessageable
136
133
  def reply_to(message, *args)
137
134
  current_user = self
138
135
 
139
- if message.participant?(current_user)
140
- reply_message = send_message(message.real_receiver(current_user), *args)
141
- reply_message.parent = message
142
- reply_message.save
136
+ return unless message.participant?(current_user)
143
137
 
144
- reply_message
145
- end
138
+ reply_message = send_message(message.real_receiver(current_user), *args)
139
+ reply_message.parent = message
140
+ reply_message.save
141
+
142
+ reply_message
146
143
  end
147
144
 
148
145
  # Mark message as deleted
@@ -158,7 +155,7 @@ module ActsAsMessageable
158
155
  raise "#{current_user} can't delete this message"
159
156
  end
160
157
 
161
- message.update_attributes!(attribute => true)
158
+ ActsAsMessageable.rails_api.new(message).update_attributes!(attribute => true)
162
159
  end
163
160
 
164
161
  # Mark message as restored
@@ -174,7 +171,7 @@ module ActsAsMessageable
174
171
  raise "#{current_user} can't restore this message"
175
172
  end
176
173
 
177
- message.update_attributes!(attribute => false)
174
+ ActsAsMessageable.rails_api.new(message).update_attributes!(attribute => false)
178
175
  end
179
176
  end
180
177
  end
@@ -1,19 +1,21 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActsAsMessageable
2
4
  class Rails3
3
5
  def initialize(subject)
4
6
  @subject = subject
5
7
  end
6
8
 
7
- def attr_accessible(*args)
8
- @subject.attr_accessible(*args)
9
- end
10
-
11
9
  def default_scope(order_by)
12
10
  @subject.send(:default_scope, order(order_by))
13
11
  end
14
12
 
15
13
  def method_missing(name, *args)
16
- @subject.send(name, *args)
14
+ @subject.send(name, *args) || super
15
+ end
16
+
17
+ def respond_to_missing?(method_name, include_private = false)
18
+ method_name.to_s == 'default_scope' || super
17
19
  end
18
20
  end
19
21
  end
@@ -1,12 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActsAsMessageable
2
4
  class Rails4
3
5
  def initialize(subject)
4
6
  @subject = subject
5
7
  end
6
8
 
7
- def attr_accessible(*args)
8
- @subject.attr_accessible(*args) if defined?(ProtectedAttributes)
9
- end
9
+ def attr_accessible(*); end
10
10
 
11
11
  def default_scope(order_by)
12
12
  @subject.send(:default_scope) { order(order_by) }
@@ -17,7 +17,11 @@ module ActsAsMessageable
17
17
  end
18
18
 
19
19
  def method_missing(name, *args)
20
- @subject.send(name, *args)
20
+ @subject.send(name, *args) || super
21
+ end
22
+
23
+ def respond_to_missing?(method_name, include_private = false)
24
+ %w[default_scope scoped attr_accessible].include?(method_name) || super
21
25
  end
22
26
  end
23
27
  end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActsAsMessageable
4
+ class Rails6
5
+ def initialize(subject)
6
+ @subject = subject
7
+ end
8
+
9
+ def attr_accessible(*); end
10
+
11
+ def default_scope(order_by)
12
+ @subject.send(:default_scope) { order(order_by) }
13
+ end
14
+
15
+ def scoped
16
+ @subject.scope
17
+ end
18
+
19
+ def update_attributes!(*args)
20
+ @subject.update!(*args)
21
+ end
22
+
23
+ def method_missing(name, *args)
24
+ @subject.send(name, *args) || super
25
+ end
26
+
27
+ def respond_to_missing?(method_name, include_private = false)
28
+ %w[attr_accessible default_scope scoped update_attributes!].include?(method_name) || super
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_record/railtie'
4
+
5
+ module ActsAsMessageable
6
+ class Railtie < Rails::Railtie
7
+ ActiveRecord::Base.include ActsAsMessageable::Model if defined?(ActiveRecord::Base)
8
+
9
+ ActiveRecord::Relation.include ActsAsMessageable::Relation if defined?(ActiveRecord::Relation)
10
+ end
11
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActsAsMessageable
2
4
  module Relation
3
5
  attr_accessor :relation_context
@@ -5,8 +7,8 @@ module ActsAsMessageable
5
7
  def process(context = relation_context)
6
8
  each do |message|
7
9
  yield(message) if block_given?
8
- context.delete_message(message) if message.removed
9
- context.restore_message(message) if message.restored
10
+ context.delete_message(message) if message.removed
11
+ context.restore_message(message) if message.restored
10
12
  end
11
13
  end
12
14
 
@@ -1,19 +1,23 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'active_support/concern'
2
4
 
3
5
  module ActsAsMessageable
4
6
  module Scopes
5
7
  extend ActiveSupport::Concern
6
8
 
7
- included do
8
- initialize_scopes
9
- end
10
-
11
9
  module ClassMethods
12
- def initialize_scopes
13
- scope :are_from, ->(*args) { where(sent_messageable_id: args.first, sent_messageable_type: args.first.class.name) }
14
- scope :are_to, ->(*args) { where(received_messageable_id: args.first, received_messageable_type: args.first.class.name) }
15
- scope :search, ->(*args) { where('body like :search_txt or topic like :search_txt', search_txt: "%#{args.first}%") }
16
- scope :connected_with, lambda { |*args|
10
+ def initialize_scopes(search_scope)
11
+ scope :are_from, lambda { |*args|
12
+ where(sent_messageable_id: args.first, sent_messageable_type: args.first.class.name)
13
+ }
14
+ scope :are_to, lambda { |*args|
15
+ where(received_messageable_id: args.first, received_messageable_type: args.first.class.name)
16
+ }
17
+ scope search_scope, lambda { |*args|
18
+ where('body like :search_txt or topic like :search_txt', search_txt: "%#{args.first}%")
19
+ }
20
+ scope :connected_with, lambda { |*args|
17
21
  where("(sent_messageable_type = :sent_type and
18
22
  sent_messageable_id = :sent_id and
19
23
  sender_delete = :s_delete and sender_permanent_delete = :s_perm_delete) or
@@ -29,9 +33,9 @@ module ActsAsMessageable
29
33
  r_perm_delete: false,
30
34
  s_perm_delete: false)
31
35
  }
32
- scope :readed, -> { where(opened: true) }
33
- scope :unreaded, -> { where(opened: false) }
34
- scope :deleted, -> { where(recipient_delete: true, sender_delete: true) }
36
+ scope :readed, -> { where('opened_at is not null OR opened = ?', true) }
37
+ scope :unreaded, -> { where('opened_at is null OR opened = ?', false) }
38
+ scope :deleted, -> { where(recipient_delete: true, sender_delete: true) }
35
39
  end
36
40
  end
37
41
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rails/generators/migration'
2
4
  require 'rails/generators/active_record'
3
5
 
@@ -5,10 +7,11 @@ module ActsAsMessageable
5
7
  class MigrationGenerator < Rails::Generators::Base
6
8
  include Rails::Generators::Migration
7
9
 
8
- namespace 'acts-as-messageable:migration'
10
+ namespace 'acts_as_messageable:migration'
9
11
 
10
12
  source_root File.join(File.dirname(__FILE__), 'templates')
11
13
  argument :table_name, type: :string, default: 'messages'
14
+ class_option :uuid, type: :boolean, default: false
12
15
 
13
16
  def self.next_migration_number(dirname)
14
17
  ActiveRecord::Generators::Base.next_migration_number(dirname)
@@ -21,7 +24,18 @@ module ActsAsMessageable
21
24
  nil
22
25
  end
23
26
  begin
24
- migration_template 'migration_permanent.rb', 'db/migrate/add_recipient_permanent_delete_and_sender_permanent_delete_to_messages.rb'
27
+ migration_template 'migration_permanent.rb',
28
+ 'db/migrate/add_recipient_permanent_delete_and_sender_permanent_delete_to_messages.rb'
29
+ rescue StandardError
30
+ nil
31
+ end
32
+ begin
33
+ migration_template 'migration_opened_as_datetime.rb', 'db/migrate/add_opened_at_to_messages.rb'
34
+ rescue StandardError
35
+ nil
36
+ end
37
+ begin
38
+ migration_template 'migration_indexes.rb', 'db/migrate/add_indexes_to_messages.rb'
25
39
  rescue StandardError
26
40
  nil
27
41
  end