Add Messages to Rooms
This commit is contained in:
parent
c583ee7f32
commit
a59ab6cf03
@ -15,6 +15,8 @@ Development Environment Setup
|
||||
TODO
|
||||
----
|
||||
|
||||
- Continue to Private Chat https://www.honeybadger.io/blog/chat-app-rails-actioncable-turbo/
|
||||
|
||||
- Implement video chat https://github.com/domchristie/webrtc-hotwire-rails
|
||||
|
||||
- Abandon previous video chat solution
|
||||
|
||||
@ -265,3 +265,4 @@ textarea
|
||||
@import tokens
|
||||
@import microposts
|
||||
@import projects
|
||||
@import rooms
|
||||
|
||||
14
app/assets/stylesheets/rooms.sass
Normal file
14
app/assets/stylesheets/rooms.sass
Normal file
@ -0,0 +1,14 @@
|
||||
#messages
|
||||
font-family: sans-serif
|
||||
width: 100%
|
||||
|
||||
.message
|
||||
background: #ffffff44
|
||||
padding: 0.2em
|
||||
margin: 0.2em 0
|
||||
h6
|
||||
margin: 0
|
||||
.from_name
|
||||
padding: 0.15em
|
||||
color: #aaa
|
||||
text-shadow: none
|
||||
@ -1,3 +0,0 @@
|
||||
// Place all the styles related to the Rooms controller here.
|
||||
// They will automatically be included in application.css.
|
||||
// You can use Sass (SCSS) here: https://sass-lang.com/
|
||||
13
app/controllers/messages_controller.rb
Normal file
13
app/controllers/messages_controller.rb
Normal file
@ -0,0 +1,13 @@
|
||||
class MessagesController < ApplicationController
|
||||
def create
|
||||
@message = current_user.messages.build(content: msg_params[:content], room_id: params[:room_id])
|
||||
authorize @message
|
||||
@message.save
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def msg_params
|
||||
params.require(:message).permit(:content)
|
||||
end
|
||||
end
|
||||
@ -14,6 +14,8 @@ class RoomsController < ApplicationController
|
||||
def show
|
||||
authorize @room
|
||||
@rooms = Room.public_rooms
|
||||
@message = Message.new
|
||||
@messages = @room.messages
|
||||
|
||||
render "index"
|
||||
end
|
||||
|
||||
5
app/models/message.rb
Normal file
5
app/models/message.rb
Normal file
@ -0,0 +1,5 @@
|
||||
class Message < ActiveRecord::Base
|
||||
belongs_to :user
|
||||
belongs_to :room
|
||||
after_create_commit { broadcast_append_to self.room }
|
||||
end
|
||||
@ -1,4 +1,5 @@
|
||||
class Room < ActiveRecord::Base
|
||||
has_many :messages
|
||||
validates_uniqueness_of :name
|
||||
scope :public_rooms, -> {where(is_private: false)}
|
||||
after_create_commit { broadcast_append_to "rooms" }
|
||||
|
||||
@ -15,6 +15,7 @@ class User < ActiveRecord::Base
|
||||
has_many :following_projects, through: :active_relationships, source: :followable, source_type: "Project"
|
||||
has_many :microposts, as: :micropostable
|
||||
has_many :bots
|
||||
has_many :messages
|
||||
|
||||
def icid
|
||||
stp = SoftTokenPrincipal.where(soft_token: self.soft_token).first_or_initialize
|
||||
|
||||
56
app/policies/message_policy.rb
Normal file
56
app/policies/message_policy.rb
Normal file
@ -0,0 +1,56 @@
|
||||
class MessagePolicy
|
||||
attr_reader :user, :model
|
||||
|
||||
def initialize(user, model)
|
||||
@user = user || User.new
|
||||
@message = model
|
||||
end
|
||||
|
||||
class Scope
|
||||
def initialize(user, scope)
|
||||
@user = user
|
||||
@scope = scope
|
||||
end
|
||||
|
||||
def resolve
|
||||
if user.admin?
|
||||
scope.all
|
||||
else
|
||||
#TODO: private chats
|
||||
scope.all
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :user, :scope
|
||||
end
|
||||
|
||||
def index?
|
||||
true
|
||||
end
|
||||
|
||||
def show?
|
||||
true
|
||||
end
|
||||
|
||||
def new?
|
||||
@user.admin?
|
||||
end
|
||||
|
||||
def create?
|
||||
@user.admin?
|
||||
end
|
||||
|
||||
def edit?
|
||||
@user.admin?
|
||||
end
|
||||
|
||||
def update?
|
||||
@user.admin?
|
||||
end
|
||||
|
||||
def destroy?
|
||||
@user.admin?
|
||||
end
|
||||
end
|
||||
3
app/views/layouts/_new_message_form.html.haml
Normal file
3
app/views/layouts/_new_message_form.html.haml
Normal file
@ -0,0 +1,3 @@
|
||||
= form_with(model: [@room, @message], remote: true) do |f|
|
||||
= f.text_field :content, id: 'chat-text', class: "form-control msg-content", autocomplete: 'off'
|
||||
= f.submit data: { disable_with: false }
|
||||
@ -13,6 +13,12 @@
|
||||
<%= javascript_importmap_tags %>
|
||||
<%= csrf_meta_tags %>
|
||||
<%= yield :head %>
|
||||
<style>
|
||||
<%= ".message.from-#{current_user&.id}" %> {
|
||||
text-align: right;
|
||||
background-color: #007bff44 !important;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="<%= body_css_class %>">
|
||||
|
||||
|
||||
6
app/views/messages/_message.html.haml
Normal file
6
app/views/messages/_message.html.haml
Normal file
@ -0,0 +1,6 @@
|
||||
.message{class: "from-#{message.user.id}"}
|
||||
- unless message.room.is_private
|
||||
%h6
|
||||
%span.from_name{style: "background: ##{(message.user.display_name.to_i(36) % 16777215).to_s(16)};" }
|
||||
= message.user.display_name
|
||||
= message.content
|
||||
@ -1,9 +1,16 @@
|
||||
- if @room
|
||||
%h4= @room.name
|
||||
|
||||
= turbo_stream_from @room
|
||||
.contain
|
||||
#messages
|
||||
= render @messages
|
||||
= render partial: 'layouts/new_message_form'
|
||||
|
||||
%h1 Rooms index
|
||||
|
||||
= render partial: "layouts/new_room_form"
|
||||
- if policy(Room).new?
|
||||
= render partial: "layouts/new_room_form"
|
||||
|
||||
= turbo_stream_from "rooms"
|
||||
#rooms
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
Rails.application.routes.draw do
|
||||
resources :rooms
|
||||
resources :rooms do
|
||||
resources :messages
|
||||
end
|
||||
resources :commands do
|
||||
member do
|
||||
get 'run'
|
||||
|
||||
11
db/migrate/20231204083004_create_messages.rb
Normal file
11
db/migrate/20231204083004_create_messages.rb
Normal file
@ -0,0 +1,11 @@
|
||||
class CreateMessages < ActiveRecord::Migration[7.1]
|
||||
def change
|
||||
create_table :messages do |t|
|
||||
t.references :user, null: false, foreign_key: true
|
||||
t.references :room, null: false, foreign_key: true
|
||||
t.text :content
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
||||
125
db/schema.rb
125
db/schema.rb
@ -10,8 +10,7 @@
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 2023_12_03_160243) do
|
||||
|
||||
ActiveRecord::Schema[7.1].define(version: 2023_12_04_083004) do
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
|
||||
@ -21,8 +20,8 @@ ActiveRecord::Schema.define(version: 2023_12_03_160243) do
|
||||
t.string "discord_api_token"
|
||||
t.bigint "user_id", null: false
|
||||
t.bigint "profile_id"
|
||||
t.datetime "created_at", precision: 6, null: false
|
||||
t.datetime "updated_at", precision: 6, null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.text "telegram_subscriber_ids"
|
||||
t.index ["profile_id"], name: "index_bots_on_profile_id"
|
||||
t.index ["user_id"], name: "index_bots_on_user_id"
|
||||
@ -37,8 +36,8 @@ ActiveRecord::Schema.define(version: 2023_12_03_160243) do
|
||||
t.string "icid"
|
||||
t.string "name"
|
||||
t.bigint "user_id"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.datetime "created_at", precision: nil, null: false
|
||||
t.datetime "updated_at", precision: nil, null: false
|
||||
t.index ["user_id"], name: "index_canisters_on_user_id"
|
||||
end
|
||||
|
||||
@ -46,8 +45,8 @@ ActiveRecord::Schema.define(version: 2023_12_03_160243) do
|
||||
t.string "name"
|
||||
t.string "trigger"
|
||||
t.text "body"
|
||||
t.datetime "created_at", precision: 6, null: false
|
||||
t.datetime "updated_at", precision: 6, null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "delayed_jobs", force: :cascade do |t|
|
||||
@ -55,13 +54,13 @@ ActiveRecord::Schema.define(version: 2023_12_03_160243) do
|
||||
t.integer "attempts", default: 0, null: false
|
||||
t.text "handler", null: false
|
||||
t.text "last_error"
|
||||
t.datetime "run_at"
|
||||
t.datetime "locked_at"
|
||||
t.datetime "failed_at"
|
||||
t.datetime "run_at", precision: nil
|
||||
t.datetime "locked_at", precision: nil
|
||||
t.datetime "failed_at", precision: nil
|
||||
t.string "locked_by"
|
||||
t.string "queue"
|
||||
t.datetime "created_at", precision: 6
|
||||
t.datetime "updated_at", precision: 6
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.index ["priority", "run_at"], name: "delayed_jobs_priority"
|
||||
end
|
||||
|
||||
@ -69,8 +68,8 @@ ActiveRecord::Schema.define(version: 2023_12_03_160243) do
|
||||
t.text "body"
|
||||
t.bigint "user_id"
|
||||
t.boolean "is_public"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.datetime "created_at", precision: nil, null: false
|
||||
t.datetime "updated_at", precision: nil, null: false
|
||||
t.boolean "is_global", default: false
|
||||
t.index ["user_id"], name: "index_doodads_on_user_id"
|
||||
end
|
||||
@ -80,7 +79,7 @@ ActiveRecord::Schema.define(version: 2023_12_03_160243) do
|
||||
t.integer "sluggable_id", null: false
|
||||
t.string "sluggable_type", limit: 50
|
||||
t.string "scope"
|
||||
t.datetime "created_at"
|
||||
t.datetime "created_at", precision: nil
|
||||
t.index ["slug", "sluggable_type", "scope"], name: "index_friendly_id_slugs_on_slug_and_sluggable_type_and_scope", unique: true
|
||||
t.index ["slug", "sluggable_type"], name: "index_friendly_id_slugs_on_slug_and_sluggable_type"
|
||||
t.index ["sluggable_type", "sluggable_id"], name: "index_friendly_id_slugs_on_sluggable_type_and_sluggable_id"
|
||||
@ -88,8 +87,8 @@ ActiveRecord::Schema.define(version: 2023_12_03_160243) do
|
||||
|
||||
create_table "games", force: :cascade do |t|
|
||||
t.string "title"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.datetime "created_at", precision: nil
|
||||
t.datetime "updated_at", precision: nil
|
||||
t.string "status"
|
||||
t.integer "controlling_player_id"
|
||||
t.integer "play_to_beat_id"
|
||||
@ -98,27 +97,37 @@ ActiveRecord::Schema.define(version: 2023_12_03_160243) do
|
||||
t.index ["play_to_beat_id"], name: "index_games_on_play_to_beat_id"
|
||||
end
|
||||
|
||||
create_table "messages", force: :cascade do |t|
|
||||
t.bigint "user_id", null: false
|
||||
t.bigint "room_id", null: false
|
||||
t.text "content"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.index ["room_id"], name: "index_messages_on_room_id"
|
||||
t.index ["user_id"], name: "index_messages_on_user_id"
|
||||
end
|
||||
|
||||
create_table "microposts", force: :cascade do |t|
|
||||
t.text "content"
|
||||
t.string "micropostable_type"
|
||||
t.bigint "micropostable_id"
|
||||
t.datetime "created_at", precision: 6, null: false
|
||||
t.datetime "updated_at", precision: 6, null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.index ["micropostable_type", "micropostable_id"], name: "index_microposts_on_micropostable"
|
||||
end
|
||||
|
||||
create_table "play_to_beats", force: :cascade do |t|
|
||||
t.integer "game_id"
|
||||
t.integer "play_id"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.datetime "created_at", precision: nil, null: false
|
||||
t.datetime "updated_at", precision: nil, null: false
|
||||
end
|
||||
|
||||
create_table "player_cards", force: :cascade do |t|
|
||||
t.integer "player_id"
|
||||
t.integer "card_id"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.datetime "created_at", precision: nil
|
||||
t.datetime "updated_at", precision: nil
|
||||
t.integer "value"
|
||||
t.string "rank"
|
||||
t.string "suit"
|
||||
@ -130,8 +139,8 @@ ActiveRecord::Schema.define(version: 2023_12_03_160243) do
|
||||
create_table "players", force: :cascade do |t|
|
||||
t.integer "game_id"
|
||||
t.integer "user_id"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.datetime "created_at", precision: nil
|
||||
t.datetime "updated_at", precision: nil
|
||||
t.string "soft_token"
|
||||
t.boolean "is_bot", default: false
|
||||
t.index ["game_id"], name: "index_players_on_game_id"
|
||||
@ -141,8 +150,8 @@ ActiveRecord::Schema.define(version: 2023_12_03_160243) do
|
||||
create_table "plays", force: :cascade do |t|
|
||||
t.integer "game_id"
|
||||
t.integer "player_id"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.datetime "created_at", precision: nil
|
||||
t.datetime "updated_at", precision: nil
|
||||
t.index ["game_id"], name: "index_plays_on_game_id"
|
||||
t.index ["player_id"], name: "index_plays_on_player_id"
|
||||
end
|
||||
@ -152,8 +161,8 @@ ActiveRecord::Schema.define(version: 2023_12_03_160243) do
|
||||
t.string "name"
|
||||
t.string "summary"
|
||||
t.text "about"
|
||||
t.datetime "created_at", precision: 6, null: false
|
||||
t.datetime "updated_at", precision: 6, null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.index ["user_id"], name: "index_profiles_on_user_id"
|
||||
end
|
||||
|
||||
@ -161,16 +170,16 @@ ActiveRecord::Schema.define(version: 2023_12_03_160243) do
|
||||
t.string "title"
|
||||
t.text "description"
|
||||
t.bigint "user_id", null: false
|
||||
t.datetime "created_at", precision: 6, null: false
|
||||
t.datetime "updated_at", precision: 6, null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.index ["user_id"], name: "index_projects_on_user_id"
|
||||
end
|
||||
|
||||
create_table "relationships", force: :cascade do |t|
|
||||
t.integer "follower_id"
|
||||
t.integer "followed_id"
|
||||
t.datetime "created_at", precision: 6, null: false
|
||||
t.datetime "updated_at", precision: 6, null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.string "followable_type"
|
||||
t.bigint "followable_id"
|
||||
t.index ["followable_type", "followable_id"], name: "index_relationships_on_followable"
|
||||
@ -182,15 +191,15 @@ ActiveRecord::Schema.define(version: 2023_12_03_160243) do
|
||||
create_table "rooms", force: :cascade do |t|
|
||||
t.string "name"
|
||||
t.boolean "is_private", default: false
|
||||
t.datetime "created_at", precision: 6, null: false
|
||||
t.datetime "updated_at", precision: 6, null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "seats", force: :cascade do |t|
|
||||
t.integer "table_id"
|
||||
t.integer "user_id"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.datetime "created_at", precision: nil
|
||||
t.datetime "updated_at", precision: nil
|
||||
t.integer "position"
|
||||
t.string "user_soft_token"
|
||||
t.integer "game_id"
|
||||
@ -202,8 +211,8 @@ ActiveRecord::Schema.define(version: 2023_12_03_160243) do
|
||||
create_table "social_links", force: :cascade do |t|
|
||||
t.bigint "profile_id", null: false
|
||||
t.string "url"
|
||||
t.datetime "created_at", precision: 6, null: false
|
||||
t.datetime "updated_at", precision: 6, null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.index ["profile_id"], name: "index_social_links_on_profile_id"
|
||||
end
|
||||
|
||||
@ -214,8 +223,8 @@ ActiveRecord::Schema.define(version: 2023_12_03_160243) do
|
||||
|
||||
create_table "tables", force: :cascade do |t|
|
||||
t.string "title"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.datetime "created_at", precision: nil
|
||||
t.datetime "updated_at", precision: nil
|
||||
t.integer "current_game_id"
|
||||
t.string "skyspace_url"
|
||||
t.string "slug"
|
||||
@ -226,8 +235,8 @@ ActiveRecord::Schema.define(version: 2023_12_03_160243) do
|
||||
t.string "telegram_id", null: false
|
||||
t.string "icp_id"
|
||||
t.string "icp_principal"
|
||||
t.datetime "created_at", precision: 6, null: false
|
||||
t.datetime "updated_at", precision: 6, null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "tokens", force: :cascade do |t|
|
||||
@ -238,8 +247,8 @@ ActiveRecord::Schema.define(version: 2023_12_03_160243) do
|
||||
t.bigint "total_supply"
|
||||
t.integer "decimals"
|
||||
t.bigint "transfer_fee"
|
||||
t.datetime "created_at", precision: 6, null: false
|
||||
t.datetime "updated_at", precision: 6, null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.string "logo_url"
|
||||
t.index ["canister_id"], name: "index_tokens_on_canister_id", unique: true
|
||||
end
|
||||
@ -248,25 +257,25 @@ ActiveRecord::Schema.define(version: 2023_12_03_160243) do
|
||||
t.string "email", default: "", null: false
|
||||
t.string "encrypted_password", default: ""
|
||||
t.string "reset_password_token"
|
||||
t.datetime "reset_password_sent_at"
|
||||
t.datetime "remember_created_at"
|
||||
t.datetime "reset_password_sent_at", precision: nil
|
||||
t.datetime "remember_created_at", precision: nil
|
||||
t.integer "sign_in_count", default: 0, null: false
|
||||
t.datetime "current_sign_in_at"
|
||||
t.datetime "last_sign_in_at"
|
||||
t.datetime "current_sign_in_at", precision: nil
|
||||
t.datetime "last_sign_in_at", precision: nil
|
||||
t.inet "current_sign_in_ip"
|
||||
t.inet "last_sign_in_ip"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.datetime "created_at", precision: nil
|
||||
t.datetime "updated_at", precision: nil
|
||||
t.string "name"
|
||||
t.string "confirmation_token"
|
||||
t.datetime "confirmed_at"
|
||||
t.datetime "confirmation_sent_at"
|
||||
t.datetime "confirmed_at", precision: nil
|
||||
t.datetime "confirmation_sent_at", precision: nil
|
||||
t.string "unconfirmed_email"
|
||||
t.integer "role"
|
||||
t.string "invitation_token"
|
||||
t.datetime "invitation_created_at"
|
||||
t.datetime "invitation_sent_at"
|
||||
t.datetime "invitation_accepted_at"
|
||||
t.datetime "invitation_created_at", precision: nil
|
||||
t.datetime "invitation_sent_at", precision: nil
|
||||
t.datetime "invitation_accepted_at", precision: nil
|
||||
t.integer "invitation_limit"
|
||||
t.integer "invited_by_id"
|
||||
t.string "invited_by_type"
|
||||
@ -284,6 +293,8 @@ ActiveRecord::Schema.define(version: 2023_12_03_160243) do
|
||||
add_foreign_key "bots", "users"
|
||||
add_foreign_key "canisters", "users"
|
||||
add_foreign_key "doodads", "users"
|
||||
add_foreign_key "messages", "rooms"
|
||||
add_foreign_key "messages", "users"
|
||||
add_foreign_key "profiles", "users"
|
||||
add_foreign_key "projects", "users"
|
||||
add_foreign_key "social_links", "profiles"
|
||||
|
||||
7
spec/factories/messages.rb
Normal file
7
spec/factories/messages.rb
Normal file
@ -0,0 +1,7 @@
|
||||
FactoryGirl.define do
|
||||
factory :message do
|
||||
user nil
|
||||
room nil
|
||||
content "MyText"
|
||||
end
|
||||
end
|
||||
5
spec/models/message_spec.rb
Normal file
5
spec/models/message_spec.rb
Normal file
@ -0,0 +1,5 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Message, type: :model do
|
||||
pending "add some examples to (or delete) #{__FILE__}"
|
||||
end
|
||||
Loading…
x
Reference in New Issue
Block a user