Compony logo

Where to read what

About Compony

Compony is a Gem that allows you to write your Rails application in component-style fashion. It combines a controller action and route along with its view into a single Ruby class. This allows writing much DRYer code, using inheritance even in views and much easier refactoring for your Rails applications, helping you to keep the code clean as the application evolves.

Compony's key aspects:

  • A Compony component is a single class that exports route(s), controller action(s) and a view to Rails.
    • Refactor common logic into your own components and inherit from them to DRY up your code.
  • Compony's powerful model mixin allows you to define metadata in your models and react to them. Examples:
    • Compony fields capture attributes that should be made visible in your UI. They allow you to implement formatting behavior and parameter sanitization for various types, e.g. URLs, phone numbers, colors etc. ready to be used in your lists, detail panels, or forms.
    • Compony's feasibility framework allows you to prohibit actions based on conditions, along with an error message. This causes all buttons pointing to that action to be disabled with a meaningful error message.
  • Compony only structures your code, but provides no style whatsoever. It is like a bookshelf rather than a reader's library. You still implement your own layouts, CSS and Javascript to define the behavior of your front-end.
  • Using Compony, you can write your application as components, but it is still possible to have regular routes, controllers and views side-to-side to it. This way, you can migrate your applications to Compony little by little and enter and leave the Compony world as you please. It is also possible to render Compony components from regular views and vice versa.
  • Compony is built for Rails 7 and fully supports Stimulus and Turbo Drive. Turbo Frames and Streams are not yet targeted, so Compony is currently meant for websites where every click triggers a "full page load" (in quotes because they are not actually full page loads due to Turbo Drive).
  • Compony uses CanCanCan for authorization but does not provide an authentication mechanism. You can easily build your own by creating login/logout components that manage cookies, and configure Compony to enforce authentication using the Compony.authentication_before_action setter. I have also successfully tested Compony to work with Devise.

State of the project

I am actively using this framework in various applications and both performance and reliability are good. However, the project is experimental and lacking peer reviews and especially automatic testing, such as unit and integration tests. Also, expect there to be (documented) breaking changes in the future, as the API will likely be further refined, resulting in renamings and deprecation of various methods.

A project with a similar aim, but a different approach, is Phlex.

Guide / Documentation

The following topics should help you get started. Please note that the links will not work in yard doc - read this on Compony's GitHub repo.

  • Self-contained example for those who like to dive straight into code
  • Installation (start here)
  • Concepts and usage:
  • Pre-built components shipped with Compony
    • Introduction
    • Button: This component class gets instanciated whenever using Compony.button or compony_button.
    • Show: Compony's equivalent to Rail's show controller action
    • Index: Compony's equivalent to Rail's index controller action
    • List: Compony's equivalent to Rail's _list partial
    • Destroy: Compony's equivalent to Rail's destroy controller action
    • WithForm: A base class for components containing and submitting forms
    • Form: Compony's equivalent to Rail's _form partial
    • New: Compony's equivalent to Rail's new and create controller action
    • Edit: Compony's equivalent to Rail's edit and update controller action

Contributing

Compony is Free Software under the LGPLv3 and you are most welcome to contribute to it.

  • If you spotted a security vulnerability, do not open an issue but instead use the contact form at https://kalsan.ch/#contact instead (English is just fine, even if the website is in German).
  • If you'd like to contribute feedback or discuss something, please open an issue.
  • If you have an idea that is worth implementing, please fork the repo, implement your changes in your own fork, and open a pull request.

Caveats

  • The API is not yet as consistent as I'd like it. Examples:
    • Instead of skip_... methods, remove_... should be implemented. This allows yet another level of classes to re-add properties. Skipping should be kept for options given via the constructor.
    • Change resourceful hooks as follows:
    • Verb DSL hooks still take precedence over global hooks, but if given, they MUST provide a block.
    • If global hooks are present, they will be executed in every verb.
  • At this point, I haven't gotten into Turbo Streams and Turbo Frames. It would be interesting to extend Compony such it also makes writing applications using these features much easier.
  • Feasibility:
    • The feasibility framework does not yet enforce prevention, but only has effects on buttons. Actions should be structured more explicitly such that prevention becomes as tight as authorization.
    • Feasibility for links is not yet implemented.
  • Compony is not compatible with tailwindcss-rails. This is likely due to Tailwind automatically removing any CSS that is not used by the application and the usage detection not picking up Compony components, as their content is not provided in views.

Acknowledgements

A big thank you to Alex and Koni who have patiently listened to my weird ideas and helped me developing them further, resulting in a few of the key concepts of Compony, such as param_name, or the way forms are structured.

Further, it should be acknowledged that Compony would not be what it is if it weren't for the awesome Gems it can rely on, for instance Rails, CanCanCan, SimpleForm, or Schemacop.