Where to read what
- Get to know what Compony is and which concepts it uses in the README on GitHub.
- When using pre-built Components, it is useful to refer to their setup code.
- There is also a RubyDoc page for Compony available.
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_actionsetter. 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.
Related projects
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:
- A basic component: Basic concepts relevant for all components
- Standalone: Routing to components
- Inheritance: DRY up your code by providing base components
- Nesting: How to instanciate components inside other components
- Resourceful components: How to create components that deal with Rails-style resources
- Compony helpers, links and buttons: Important tools for concise Compony programming
- Root actions: How to provide context-sensitive buttons to your application
- Feasibility: Disabiling buttons based on context (contains
prevent) - Ownership: Informing Compony that a resource is conceptually part of another resource
- Model fields: Allowing Compony to auto-generate UI elements by telling it about the structure of your model
- Rails generators: Creating components quickly
- Internal datastructures: Noteworthy datastructures provided by Compony
- Virtual models: Unleashing non-persistent interactions through Compony's
ActiveTypeintegration
- Pre-built components shipped with Compony
- Introduction
- Button: This component class gets instanciated whenever using
Compony.buttonorcompony_button. - Show: Compony's equivalent to Rail's
showcontroller action - Index: Compony's equivalent to Rail's
indexcontroller action - List: Compony's equivalent to Rail's
_listpartial - Destroy: Compony's equivalent to Rail's
destroycontroller action - WithForm: A base class for components containing and submitting forms
- Form: Compony's equivalent to Rail's
_formpartial - New: Compony's equivalent to Rail's
newandcreatecontroller action - Edit: Compony's equivalent to Rail's
editandupdatecontroller 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.
- Instead of
- 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.