messaged 0.1.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.
- checksums.yaml +7 -0
- data/README.md +85 -0
- data/Rakefile +8 -0
- data/app/assets/config/messaged_manifest.js +1 -0
- data/app/assets/stylesheets/messaged/application.css +15 -0
- data/app/controllers/messaged/application_controller.rb +54 -0
- data/app/controllers/messaged/messages_controller.rb +71 -0
- data/app/javascript/application.js +2 -0
- data/app/jobs/messaged/application_job.rb +4 -0
- data/app/models/messaged/application_record.rb +5 -0
- data/app/models/messaged/message.rb +36 -0
- data/app/models/messaged/null_tenant.rb +15 -0
- data/app/models/messaged/null_user.rb +23 -0
- data/app/models/messaged/room.rb +27 -0
- data/app/models/messaged/user_extender.rb +15 -0
- data/app/views/layouts/messaged/application.html.erb +16 -0
- data/config/importmap.rb +4 -0
- data/config/locales/en.yml +9 -0
- data/config/routes.rb +3 -0
- data/db/migrate/20221001034722_create_messaged.rb +33 -0
- data/lib/generators/messaged/install/USAGE.md +8 -0
- data/lib/generators/messaged/install/install_generator.rb +18 -0
- data/lib/generators/messaged/install/templates/initializer.rb +20 -0
- data/lib/generators/messaged/views/USAGE.md +8 -0
- data/lib/generators/messaged/views/templates/messages/_form.html.erb +8 -0
- data/lib/generators/messaged/views/templates/messages/_message.html.erb +12 -0
- data/lib/generators/messaged/views/templates/messages/create.turbostream.erb +2 -0
- data/lib/generators/messaged/views/templates/messages/edit.html.erb +3 -0
- data/lib/generators/messaged/views/templates/messages/index.html.erb +21 -0
- data/lib/generators/messaged/views/templates/messages/new.html.erb +3 -0
- data/lib/generators/messaged/views/templates/messages/show.html.erb +1 -0
- data/lib/generators/messaged/views/views_generator.rb +42 -0
- data/lib/messaged/base_migration.rb +17 -0
- data/lib/messaged/engine.rb +15 -0
- data/lib/messaged/version.rb +3 -0
- data/lib/messaged.rb +50 -0
- data/lib/tasks/messaged_tasks.rake +4 -0
- metadata +125 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 2607ebea948e9c5464a9fba7e3153def8d1e0093fccc7c72570b9aeced8b910f
|
4
|
+
data.tar.gz: 4ab6464c09f420b6f18e6761317e0638d60d6fa30f0263f9cb67d7e174a5753d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 68b45ab5fa04546608da02a3aaf1cd945b497be9ea599ac9518ab4c0c076b8bf2f0885cbf2bb478ae0eb30e9f473bc455e3f9aa856be688477976bf92b39e42f
|
7
|
+
data.tar.gz: bcdcdebc54df17cfe5107e4926f57947c445b7ea14e217ed8bb006ccc741fec622fd51983ed15b06e870a9cf502340d3ddefd5e64c43ca775793cc92d4b110df
|
data/README.md
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
# Messaged
|
2
|
+
A Rails Engine for Hotwire Turbo-powered instant messaging.
|
3
|
+
|
4
|
+
The author would personally recommend against using this Gem if your Rails application is not built for Turbo Rails.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem "messaged"
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
```bash
|
15
|
+
bundle
|
16
|
+
```
|
17
|
+
|
18
|
+
Or install it yourself as:
|
19
|
+
```bash
|
20
|
+
gem install messaged
|
21
|
+
```
|
22
|
+
|
23
|
+
Generate the needed migrations and initializer:
|
24
|
+
```bash
|
25
|
+
rails generate messaged:install
|
26
|
+
rails messaged:install:migrations
|
27
|
+
```
|
28
|
+
|
29
|
+
## Usage
|
30
|
+
Messages broadcast to the DOM element id `messages`
|
31
|
+
```html
|
32
|
+
<div id="messages"></div>
|
33
|
+
```
|
34
|
+
|
35
|
+
To get started with a basic HTML structure, run in your terminal: `rails generate messaged:views`
|
36
|
+
|
37
|
+
If you're using this engine or `turbo-rails` for the first time, it is recommended to generate the views to familiarize yourself with how turbo tags are used when turbo streaming.
|
38
|
+
|
39
|
+
### Users
|
40
|
+
Messaged assumes you have a user model. You may customize the user model name in the initializer. For example, if your user model is called Member:
|
41
|
+
```ruby
|
42
|
+
# config/initializers/messaged.rb
|
43
|
+
Messaged.user_class = 'Member'
|
44
|
+
Messaged.current_user_method = :current_member
|
45
|
+
```
|
46
|
+
|
47
|
+
### Tenants
|
48
|
+
Messaged does not assume the application is multi-tenant, but does support it. By default, `Messaged.tenant_class` is set to `nil`.
|
49
|
+
```ruby
|
50
|
+
# config/initializers/messaged.rb
|
51
|
+
Messaged.tenant_class = 'Account'
|
52
|
+
Messaged.current_tenant_method = :current_account
|
53
|
+
```
|
54
|
+
|
55
|
+
## Dependencies
|
56
|
+
It is recommended, particularly for development, to have a websockets compatible web server. This is true for production as well, but puma adds an easy way to support websockets without needing additional infrastructure from external services.
|
57
|
+
```ruby
|
58
|
+
gem "puma"
|
59
|
+
```
|
60
|
+
|
61
|
+
By default, Messaged is powered by:
|
62
|
+
```ruby
|
63
|
+
gem "rails", ">= 7.0.2.3"
|
64
|
+
gem "importmap-rails", "1.1.5"
|
65
|
+
gem "turbo-rails", "1.3.0"
|
66
|
+
```
|
67
|
+
If your application cannot support these gems, it is recommended that you do not use the Messaged engine. Alternatively, feel free to work this engine and add support for your desired setup. Pull requests are welcome, see: [CONTRIBUTING.md](https://github.com/ianrandmckenzie/messaged/blob/main/CONTRIBUTING.md)
|
68
|
+
|
69
|
+
## Contributing
|
70
|
+
See [CONTRIBUTING.md](https://github.com/ianrandmckenzie/messaged/blob/main/CONTRIBUTING.md)
|
71
|
+
|
72
|
+
## License
|
73
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
74
|
+
See also: [LICENSE.txt](https://github.com/ianrandmckenzie/messaged/blob/main/LICENSE.txt)
|
75
|
+
|
76
|
+
## Other Info
|
77
|
+
Messaged is intended to be named through the nomenclature used in [Noticed](https://github.com/excid3/noticed), in part because Collin and I met through the GoRails Discord server (owned by @excid3).
|
78
|
+
—Ian
|
79
|
+
|
80
|
+
## TODO
|
81
|
+
* Add dynamic configurations for message broadcasting to tenants (like an organization chat room), rooms (like a Discord channel), or users (like direct messages in most direct-messaging apps such as Signal)
|
82
|
+
* Figure out how to support permissioning/authorization (such as Pundit/Cancancan) without being opinionated
|
83
|
+
* Complete adding rich_text support
|
84
|
+
* Ensure I18n support for hard-coded English strings that are seen by the end-user
|
85
|
+
* Create and finish the test suite
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
//= link_directory ../stylesheets/messaged .css
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
|
10
|
+
* files in this directory. Styles in this file should be added after the last require_* statement.
|
11
|
+
* It is generally better to create a new file per style scope.
|
12
|
+
*
|
13
|
+
*= require_tree .
|
14
|
+
*= require_self
|
15
|
+
*/
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Messaged
|
2
|
+
class ApplicationController < ActionController::Base
|
3
|
+
helper Messaged::Engine.helpers
|
4
|
+
helper_method \
|
5
|
+
:messaged_current_user,
|
6
|
+
:messaged_current_tenant
|
7
|
+
|
8
|
+
protected
|
9
|
+
|
10
|
+
# The `current_user` and `signed_in?` methods are prefixed with `messaged_`
|
11
|
+
# to avoid conflicts with methods from the parent controller.
|
12
|
+
|
13
|
+
def messaged_current_user
|
14
|
+
send(Messaged.current_user_method) || NullUser.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def messaged_user_signed_in?
|
18
|
+
!messaged_current_user.messaged_anonymous?
|
19
|
+
end
|
20
|
+
|
21
|
+
# The `current_tenant` and `signed_in?` methods are prefixed with `messaged_`
|
22
|
+
# to avoid conflicts with methods from the parent controller.
|
23
|
+
|
24
|
+
def messaged_current_tenant
|
25
|
+
send(Messaged.current_tenant_method) || NullTenant.new
|
26
|
+
end
|
27
|
+
|
28
|
+
def messaged_tenant_signed_in?
|
29
|
+
!messaged_current_tenant.messaged_anonymous?
|
30
|
+
end
|
31
|
+
|
32
|
+
def messaged_current_room
|
33
|
+
@room = nil
|
34
|
+
return unless params && params[:room_id]
|
35
|
+
@room = Room.find(params[:room_id])
|
36
|
+
return @room
|
37
|
+
end
|
38
|
+
|
39
|
+
# Here we define an owner in the event that there is a current_tenant or
|
40
|
+
# current_user, but perhaps not necessarily both without assuming one or the other.
|
41
|
+
# Like in models/message.rb, we default to user and fallback to other models.
|
42
|
+
def messaged_current_owner
|
43
|
+
return messaged_current_user if messaged_current_user
|
44
|
+
return messaged_current_room if messaged_current_room
|
45
|
+
return messaged_current_tenant if messaged_current_tenant
|
46
|
+
return nil
|
47
|
+
end
|
48
|
+
|
49
|
+
def messaged_require_login!
|
50
|
+
fail Messaged::Errors::LoginRequired if messaged_current_user.messaged_anonymous?
|
51
|
+
fail Messaged::Errors::LoginRequired if messaged_current_tenant.messaged_anonymous?
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module Messaged
|
2
|
+
class MessagesController < ApplicationController
|
3
|
+
# TODO: How does the enginer user require authnetication without assuming Devise?
|
4
|
+
# before_action :authenticate_user!
|
5
|
+
before_action :set_message, only: [:destroy, :edit, :show, :update]
|
6
|
+
|
7
|
+
def index
|
8
|
+
# TODO: How does the enginer user require authnetication without assuming Devise / ActsAsTenant?
|
9
|
+
# @messages = Message.where(account: current_account)
|
10
|
+
@messages = Message.all
|
11
|
+
@new_message = Message.new
|
12
|
+
@new_message = messaged_current_owner.messages.build if messaged_current_owner
|
13
|
+
end
|
14
|
+
|
15
|
+
def show; end
|
16
|
+
|
17
|
+
def new
|
18
|
+
@message = Message.new
|
19
|
+
@message = messaged_current_owner.messages.build if messaged_current_owner
|
20
|
+
end
|
21
|
+
|
22
|
+
def create
|
23
|
+
# TODO: How does the enginer user require authnetication without assuming Devise / ActsAsTenant?
|
24
|
+
# @message = Message.new(message_params.merge(account: current_account, user: current_user))
|
25
|
+
@message = Message.new(message_params)
|
26
|
+
if @message.save
|
27
|
+
@new_message = messaged_current_owner.messages.build if messaged_current_owner
|
28
|
+
respond_to do |format|
|
29
|
+
format.turbo_stream do
|
30
|
+
render turbo_stream: turbo_stream.append(:messages, partial: "messaged/messages/message",
|
31
|
+
locals: { message: @message })
|
32
|
+
end
|
33
|
+
format.html { redirect_to messages_url }
|
34
|
+
end
|
35
|
+
else
|
36
|
+
render :new, status: :unprocessable_entity
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def edit; end
|
41
|
+
|
42
|
+
def update
|
43
|
+
# TODO: (Security risk) How to authenticate user agnostically?
|
44
|
+
if @message.update(message_params)
|
45
|
+
render @message
|
46
|
+
else
|
47
|
+
render :edit, status: :unprocessable_entity
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def destroy
|
52
|
+
# TODO: (Security risk) How to authenticate user agnostically?
|
53
|
+
@message.destroy
|
54
|
+
respond_to do |format|
|
55
|
+
format.turbo_stream { render turbo_stream: turbo_stream.remove(@message) }
|
56
|
+
format.html { redirect_to messages_url }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def set_message
|
63
|
+
# TODO: (Security risk) How to authenticate user agnostically before declaring?
|
64
|
+
@message = Message.find(params[:id])
|
65
|
+
end
|
66
|
+
|
67
|
+
def message_params
|
68
|
+
params.require(:message).permit(:content, :user_id, :tenant_id, :messaged_room_id)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Messaged
|
2
|
+
class Message < ApplicationRecord
|
3
|
+
include ActionView::RecordIdentifier
|
4
|
+
|
5
|
+
# User association
|
6
|
+
belongs_to :user,
|
7
|
+
class_name: Messaged.user_class_name,
|
8
|
+
inverse_of: :messages,
|
9
|
+
optional: true
|
10
|
+
# Multi-tenant option
|
11
|
+
if Messaged.tenant_class_name
|
12
|
+
belongs_to :tenant,
|
13
|
+
class_name: Messaged.tenant_class_name,
|
14
|
+
inverse_of: :messages,
|
15
|
+
optional: true
|
16
|
+
end
|
17
|
+
belongs_to :room, optional: true
|
18
|
+
|
19
|
+
has_rich_text :content
|
20
|
+
validates :content, presence: true
|
21
|
+
|
22
|
+
# TODO: This needs to be added to a generator
|
23
|
+
after_create_commit -> { broadcast_append_later_to ["messages"], target: "messages", partial: "messaged/messages/message" }
|
24
|
+
after_update_commit -> { broadcast_replace_later_to ["messages"], target: "#{dom_id(self)}", partial: "messaged/messages/message" }
|
25
|
+
after_destroy_commit -> { broadcast_remove_to ["messages"] }
|
26
|
+
|
27
|
+
# Messages should default to the person sending them, otherwise
|
28
|
+
# fallback to the chat room, and finally tenant if they exist.
|
29
|
+
def owner
|
30
|
+
return user if user
|
31
|
+
return room if room
|
32
|
+
return tenant if Messaged.tenant_class_name && tenant
|
33
|
+
return nil # replace with user, tenant, or room
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Messaged
|
2
|
+
class Room < ApplicationRecord
|
3
|
+
# User association
|
4
|
+
belongs_to :user,
|
5
|
+
class_name: Messaged.user_class_name,
|
6
|
+
inverse_of: :messages,
|
7
|
+
optional: true
|
8
|
+
# Multi-tenant option
|
9
|
+
if Messaged.tenant_class_name
|
10
|
+
belongs_to :tenant,
|
11
|
+
class_name: Messaged.tenant_class_name,
|
12
|
+
inverse_of: :messages,
|
13
|
+
optional: true
|
14
|
+
end
|
15
|
+
validates :title, presence: true
|
16
|
+
|
17
|
+
has_many :messages, dependent: :destroy
|
18
|
+
|
19
|
+
# Messages should default to the person sending them, otherwise
|
20
|
+
# fallback to the chat room, and finally tenant if they exist.
|
21
|
+
def owner
|
22
|
+
return user if user
|
23
|
+
return tenant if Messaged.tenant_class_name && tenant
|
24
|
+
return nil # replace with user, tenant, or room
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Messaged
|
2
|
+
module UserExtender
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
included do
|
5
|
+
with_options dependent: :nullify, foreign_key: 'user_id', inverse_of: :user do
|
6
|
+
has_many :messages, class_name: 'Messaged::Message', dependent: :destroy
|
7
|
+
has_many :rooms, class_name: 'Messaged::Room', dependent: :destroy
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def messaged_anonymous?
|
12
|
+
false
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>Messaged</title>
|
5
|
+
<%= csrf_meta_tags %>
|
6
|
+
<%= csp_meta_tag %>
|
7
|
+
|
8
|
+
<%= stylesheet_link_tag "messaged/application", media: "all" %>
|
9
|
+
<%= javascript_importmap_tags %>
|
10
|
+
</head>
|
11
|
+
<body>
|
12
|
+
|
13
|
+
<%= yield %>
|
14
|
+
|
15
|
+
</body>
|
16
|
+
</html>
|
data/config/importmap.rb
ADDED
data/config/routes.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'messaged/base_migration'
|
2
|
+
class CreateMessaged < Messaged::BaseMigration
|
3
|
+
def change
|
4
|
+
create_table :messaged_messages do |t|
|
5
|
+
t.references :tenant, type: user_id_type, index: false
|
6
|
+
t.index [:tenant_id], name: :index_messaged_messages_on_tenant_id
|
7
|
+
|
8
|
+
t.references :user, type: tenant_id_type, index: false
|
9
|
+
t.index [:user_id], name: :index_messaged_messages_on_user_id
|
10
|
+
|
11
|
+
t.references :messaged_room, foreign_key: true
|
12
|
+
|
13
|
+
t.text :content
|
14
|
+
|
15
|
+
# Choose an association: room, user, tenant
|
16
|
+
t.string :delivery_target
|
17
|
+
|
18
|
+
t.timestamps
|
19
|
+
end
|
20
|
+
|
21
|
+
create_table :messaged_rooms do |t|
|
22
|
+
t.references :tenant, type: user_id_type, index: false
|
23
|
+
t.index [:tenant_id], name: :index_messaged_rooms_on_tenant_id
|
24
|
+
|
25
|
+
t.references :user, type: tenant_id_type, index: false
|
26
|
+
t.index [:user_id], name: :index_messaged_rooms_on_user_id
|
27
|
+
|
28
|
+
t.string :title
|
29
|
+
|
30
|
+
t.timestamps
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Messaged
|
2
|
+
module Generators
|
3
|
+
class InstallGenerator < Rails::Generators::Base
|
4
|
+
def set_source_paths
|
5
|
+
@source_paths = [
|
6
|
+
File.expand_path('templates', __dir__),
|
7
|
+
File.expand_path('../../../..', __dir__),
|
8
|
+
]
|
9
|
+
end
|
10
|
+
|
11
|
+
def copy_initializer_file
|
12
|
+
copy_file \
|
13
|
+
'initializer.rb',
|
14
|
+
'config/initializers/messaged.rb'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# Messaged configuration
|
2
|
+
|
3
|
+
# ==> User Configuration
|
4
|
+
# The name of the class your app uses for your users.
|
5
|
+
# By default the engine will use 'User' but if you have another name
|
6
|
+
# for your user class - change it here.
|
7
|
+
Messaged.user_class = 'User'
|
8
|
+
|
9
|
+
# This method is used by Messaged controllers and views to fetch the currently signed-in user
|
10
|
+
Messaged.current_user_method = :"current_#{Messaged.user_class_name.demodulize.underscore}"
|
11
|
+
|
12
|
+
# ==> Multi-tenant Configuration
|
13
|
+
# The name of the class your app uses for your tenants.
|
14
|
+
# By default the engine will use nil (in other words, tenancy in the
|
15
|
+
# application is not assumed). If you have another name
|
16
|
+
# for your tenant class - change it here. Example: 'Account'
|
17
|
+
Messaged.tenant_class = nil
|
18
|
+
|
19
|
+
# This method is used by Messaged controllers and views to fetch the currently signed-in user
|
20
|
+
# Messaged.current_tenant_method = :"current_#{Messaged.tenant_class_name.demodulize.underscore}"
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<%= form_with model: message, class: 'messaged-form' do |f| %>
|
2
|
+
<%= f.label :content, t('messaged.send_a_message') %>
|
3
|
+
<%= f.hidden_field :user_id %>
|
4
|
+
<%= f.hidden_field :tenant_id %>
|
5
|
+
<%= f.hidden_field :messaged_room_id %>
|
6
|
+
<%= f.text_area :content %>
|
7
|
+
<%= f.submit nil, class: 'messaged-button' %>
|
8
|
+
<% end %>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<%= turbo_frame_tag dom_id(message) do %>
|
2
|
+
<div class="messaged-message-container">
|
3
|
+
<div>
|
4
|
+
<span class="messaged-timestamp"><%= time_ago_in_words(message.created_at) %> ago</span>
|
5
|
+
<p class="messaged-body"><%= message.content %></p>
|
6
|
+
<div class="messaged-options">
|
7
|
+
<span><%= link_to t('messaged.edit'), messaged.edit_message_path(message), class: "messaged-edit-link", "data-turbo-action": "replace" %></span>
|
8
|
+
<%= button_to t('messaged.delete'), messaged.message_path(message), method: :delete, form: { data: { turbo_confirm: t('messaged.confirm') } }, class: "messaged-delete-link", "data-turbo-action": "delete" %>
|
9
|
+
</div>
|
10
|
+
</div>
|
11
|
+
</div>
|
12
|
+
<% end %>
|
@@ -0,0 +1,21 @@
|
|
1
|
+
<div class="messaged-index-container">
|
2
|
+
<div class="messaged-outer-wrapper">
|
3
|
+
<div class="messaged-inner-wrapper">
|
4
|
+
<div class="messaged-index">
|
5
|
+
<% if t('messaged.header').present? %>
|
6
|
+
<h1 class="messaged-header"><%= t('messaged.header') %></h1>
|
7
|
+
<% end %>
|
8
|
+
<% # TODO: How do we make current_user model agnostic? %>
|
9
|
+
<%#= turbo_stream_from current_account, "messages" %>
|
10
|
+
<%= turbo_stream_from "messages" %>
|
11
|
+
<div class="messaged-messages" id="messages">
|
12
|
+
<%= render @messages %>
|
13
|
+
</div>
|
14
|
+
|
15
|
+
<%= turbo_frame_tag "new_message" do %>
|
16
|
+
<%= render "form", message: @new_message %>
|
17
|
+
<% end %>
|
18
|
+
</div>
|
19
|
+
</div>
|
20
|
+
</div>
|
21
|
+
</div>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= render @message %>
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Messaged
|
2
|
+
module Generators
|
3
|
+
class ViewsGenerator < Rails::Generators::Base
|
4
|
+
def set_source_paths
|
5
|
+
@source_paths = [
|
6
|
+
File.expand_path('templates', __dir__),
|
7
|
+
File.expand_path('../../../..', __dir__),
|
8
|
+
]
|
9
|
+
end
|
10
|
+
|
11
|
+
def copy_view_templates
|
12
|
+
copy_file \
|
13
|
+
'messages/_form.html.erb',
|
14
|
+
'app/views/messaged/messages/_form.html.erb'
|
15
|
+
|
16
|
+
copy_file \
|
17
|
+
'messages/_message.html.erb',
|
18
|
+
'app/views/messaged/messages/_message.html.erb'
|
19
|
+
|
20
|
+
copy_file \
|
21
|
+
'messages/create.turbostream.erb',
|
22
|
+
'app/views/messaged/messages/create.turbostream.erb'
|
23
|
+
|
24
|
+
copy_file \
|
25
|
+
'messages/edit.html.erb',
|
26
|
+
'app/views/messaged/messages/edit.html.erb'
|
27
|
+
|
28
|
+
copy_file \
|
29
|
+
'messages/index.html.erb',
|
30
|
+
'app/views/messaged/messages/index.html.erb'
|
31
|
+
|
32
|
+
copy_file \
|
33
|
+
'messages/new.html.erb',
|
34
|
+
'app/views/messaged/messages/new.html.erb'
|
35
|
+
|
36
|
+
copy_file \
|
37
|
+
'messages/show.html.erb',
|
38
|
+
'app/views/messaged/messages/show.html.erb'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Messaged
|
2
|
+
class BaseMigration < ActiveRecord::Migration[7.0]
|
3
|
+
protected
|
4
|
+
|
5
|
+
def user_id_type
|
6
|
+
Messaged.user_class.columns.find { |c| c.name == Messaged.user_class.primary_key }.sql_type
|
7
|
+
end
|
8
|
+
|
9
|
+
def tenant_id_type
|
10
|
+
if Messaged&.tenant_class
|
11
|
+
Messaged.tenant_class.columns.find { |c| c.name == Messaged.tenant_class.primary_key }.sql_type
|
12
|
+
else
|
13
|
+
Messaged.user_class.columns.find { |c| c.name == Messaged.user_class.primary_key }.sql_type
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Messaged
|
2
|
+
class Engine < ::Rails::Engine
|
3
|
+
require "importmap-rails"
|
4
|
+
require "turbo-rails"
|
5
|
+
isolate_namespace Messaged
|
6
|
+
|
7
|
+
config.to_prepare do
|
8
|
+
Messaged.user_class&.send(:include, Messaged::UserExtender)
|
9
|
+
end
|
10
|
+
|
11
|
+
# initializer "messaged.assets.precompile" do |app|
|
12
|
+
# app.config.assets.precompile += %w( messaged/application.css )
|
13
|
+
# end
|
14
|
+
end
|
15
|
+
end
|
data/lib/messaged.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require "messaged/version"
|
2
|
+
require "messaged/engine"
|
3
|
+
|
4
|
+
module Messaged
|
5
|
+
class << self
|
6
|
+
# @return [String] The name of the user class
|
7
|
+
attr_reader :user_class_name
|
8
|
+
|
9
|
+
# @return [String] The name of the tenant class
|
10
|
+
attr_reader :tenant_class_name
|
11
|
+
|
12
|
+
# @return [Symbol] The name of the method used by Messaged controllers and views to get the currently signed-in user
|
13
|
+
attr_accessor :current_user_method
|
14
|
+
|
15
|
+
# @return [Symbol] The name of the method used by Messaged controllers and views to get the currently signed-in tenant
|
16
|
+
attr_accessor :current_tenant_method
|
17
|
+
|
18
|
+
# @param user_class_name [String]
|
19
|
+
def user_class=(user_class_name)
|
20
|
+
return nil if user_class_name.nil?
|
21
|
+
unless user_class_name.is_a?(String)
|
22
|
+
fail "Messaged.user_class must be set to a String, got #{user_class_name.inspect}"
|
23
|
+
end
|
24
|
+
@user_class_name = user_class_name
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [Class<Messaged::UserExtender>] the user class from the host application.
|
28
|
+
def user_class
|
29
|
+
# This is nil before the initializer is installed.
|
30
|
+
return nil if @user_class_name.nil?
|
31
|
+
@user_class_name.constantize
|
32
|
+
end
|
33
|
+
|
34
|
+
# @param tenant_class_name [String]
|
35
|
+
def tenant_class=(tenant_class_name)
|
36
|
+
return nil if tenant_class_name.nil?
|
37
|
+
unless tenant_class_name.is_a?(String)
|
38
|
+
fail "Messaged.tenant_class must be set to a String, got #{tenant_class_name.inspect}"
|
39
|
+
end
|
40
|
+
@tenant_class_name = tenant_class_name
|
41
|
+
end
|
42
|
+
|
43
|
+
# @return [Class<Messaged::TenantExtender>] the tenant class from the host application.
|
44
|
+
def tenant_class
|
45
|
+
# This is nil before the initializer is installed.
|
46
|
+
return nil if @tenant_class_name.nil?
|
47
|
+
@tenant_class_name.constantize
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
metadata
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: messaged
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- cjilbert504, ianrandmckenzie
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-01-29 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 7.0.2.3
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 7.0.2.3
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: importmap-rails
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.1.5
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.1.5
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: turbo-rails
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 1.3.0
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.3.0
|
55
|
+
description: A quick and easy way to implement an instant-messaging module using Turbo
|
56
|
+
Rails.
|
57
|
+
email:
|
58
|
+
- admin@ianrandmckenzie.com
|
59
|
+
executables: []
|
60
|
+
extensions: []
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- README.md
|
64
|
+
- Rakefile
|
65
|
+
- app/assets/config/messaged_manifest.js
|
66
|
+
- app/assets/stylesheets/messaged/application.css
|
67
|
+
- app/controllers/messaged/application_controller.rb
|
68
|
+
- app/controllers/messaged/messages_controller.rb
|
69
|
+
- app/javascript/application.js
|
70
|
+
- app/jobs/messaged/application_job.rb
|
71
|
+
- app/models/messaged/application_record.rb
|
72
|
+
- app/models/messaged/message.rb
|
73
|
+
- app/models/messaged/null_tenant.rb
|
74
|
+
- app/models/messaged/null_user.rb
|
75
|
+
- app/models/messaged/room.rb
|
76
|
+
- app/models/messaged/user_extender.rb
|
77
|
+
- app/views/layouts/messaged/application.html.erb
|
78
|
+
- config/importmap.rb
|
79
|
+
- config/locales/en.yml
|
80
|
+
- config/routes.rb
|
81
|
+
- db/migrate/20221001034722_create_messaged.rb
|
82
|
+
- lib/generators/messaged/install/USAGE.md
|
83
|
+
- lib/generators/messaged/install/install_generator.rb
|
84
|
+
- lib/generators/messaged/install/templates/initializer.rb
|
85
|
+
- lib/generators/messaged/views/USAGE.md
|
86
|
+
- lib/generators/messaged/views/templates/messages/_form.html.erb
|
87
|
+
- lib/generators/messaged/views/templates/messages/_message.html.erb
|
88
|
+
- lib/generators/messaged/views/templates/messages/create.turbostream.erb
|
89
|
+
- lib/generators/messaged/views/templates/messages/edit.html.erb
|
90
|
+
- lib/generators/messaged/views/templates/messages/index.html.erb
|
91
|
+
- lib/generators/messaged/views/templates/messages/new.html.erb
|
92
|
+
- lib/generators/messaged/views/templates/messages/show.html.erb
|
93
|
+
- lib/generators/messaged/views/views_generator.rb
|
94
|
+
- lib/messaged.rb
|
95
|
+
- lib/messaged/base_migration.rb
|
96
|
+
- lib/messaged/engine.rb
|
97
|
+
- lib/messaged/version.rb
|
98
|
+
- lib/tasks/messaged_tasks.rake
|
99
|
+
homepage: https://github.com/ianrandmckenzie/messaged
|
100
|
+
licenses:
|
101
|
+
- MIT
|
102
|
+
metadata:
|
103
|
+
homepage_uri: https://github.com/ianrandmckenzie/messaged
|
104
|
+
source_code_uri: https://github.com/ianrandmckenzie/messaged
|
105
|
+
changelog_uri: https://github.com/ianrandmckenzie/messaged/blob/main/CHANGELOG.md
|
106
|
+
post_install_message:
|
107
|
+
rdoc_options: []
|
108
|
+
require_paths:
|
109
|
+
- lib
|
110
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
111
|
+
requirements:
|
112
|
+
- - ">="
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: '0'
|
115
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
116
|
+
requirements:
|
117
|
+
- - ">="
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '0'
|
120
|
+
requirements: []
|
121
|
+
rubygems_version: 3.3.7
|
122
|
+
signing_key:
|
123
|
+
specification_version: 4
|
124
|
+
summary: A Rails Engine for Hotwire Turbo-powered instant messaging.
|
125
|
+
test_files: []
|