Git Product home page Git Product logo

chat_app's Introduction

README

A simple chat app that supports attachments and emojis. The app is a modular monolith that sends messages real time using turbo streams.

  • Ruby version 3.2.2
  • Rails version 7.1
  • Database postgresql
  • Message broker Redis
  • Background worker Sidekiq

Getting Started

The recommended way to get started is with docker.

docker-compose run --rm app rake db:create db:migrate
docker-compose run --rm app rake assets:precompile

# Create Users to sign in with devise
docker-compose run --rm app rails c
Authentication::Domain::User.create!(id: SecureRandom.uuid, email: "[email protected]", password: "test123", first_name: "Name1", last_name: "LastName1")
Authentication::Domain::User.create!(id: SecureRandom.uuid, email: "[email protected]", password: "test123", first_name: "Name2", last_name: "LastName2")
docker-compose up

Project Architecture

The project uses the dry.rb gems, initializing an App Container in config/initializers/container.rb. Each feature is defined in the root/feature_namefolder. Each feature folder contains the following structure:

feature_name
    lib
        feature_name
            app
            domain
            infra
            ui
    spec

App

The app folder contains all our services and response dtos. All our business logic goes here. The service methods call a Model method to modify the data, save, and publish all the events registered by the Aggregate Root. The models that we modify here need to be defined as an Aggregate Root. The Aggregate Root Models hold an array of domain events that are registered by the model methods. The pub/sub comes from the rails_event_store gem.

Domain

The domain folder holds all our models and events that are registered by the model methods. The models should implement methods that are related to data modifications. If the model inherits from the AggregateRoot class, it can hold an array of domain events, which on successful save, the services uses to publish all the events. The events are sent to Redis, and the background worker reads from there and maps them to a Listener. The mapping is defined in infra/system/provider_source.

Infra

This folder holds all the files related to the infrastructure, such as application configs, routing configs, database migrations, importmap javascript pins, and a provider_source file, which registers our models and services into the app container. This makes our feature a bootable component, which is automatically booted in the provider_source file on the line:

App::Container.register_provider(:chats, from: :chats)
App::Container.start(:chats)

This will give us access to all the registered dependencies in the lines above, and we can use dependency injection in the following way:

include Import[chat_service: 'chats.chat_service', chat_repository: 'chats.chat_repository']

NOTE

There is an issue with the dry-system gem and the dependency injection in the controllers, because of the change in change on the ruby 3+ initialize method. Because of that we have to define a custom strategy, located in lib/utils/injection/controller_resolve_strategy, and add the strategy to the auto injector. This is defined in config/initializers/dependency_injection. When using dependency injection in the controller, use the following syntax:

include Import.inject[chat_service: 'chats.chat_service', chat_repository: 'chats.chat_repository']

When using dependency injection in the Listeners, use the following syntax:

include Import.active_job[chat_service: 'chats.chat_service', chat_repository: 'chats.chat_repository]

Ui

The Ui folder holds everything related to the presentation layer. This includes validation classes, controllers, listeners, assets. It serves as an access point to our module, either through a controller, or an event listener.

Note

If you have custom javascript controllers in a feature module, you need to include it in 2 places in order for the controller to be registered and compiled from the asset pipeline.

# app/assets/config/manifest.js
//= link_tree ../../../chats/lib/chats/ui/javascript/controllers .js

# app/javascript/controllers/index.js
eagerLoadControllersFrom("chats", application)

chat_app's People

Contributors

jane-terziev avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.