acts-as-messageable 0.4.11 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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