• Stars
    star
    174
  • Rank 219,104 (Top 5 %)
  • Language
    Ruby
  • License
    MIT License
  • Created almost 15 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Traits and partial classes for Ruby

Tests

Modularity - Traits and partial classes for Ruby

Modularity enhances Ruby's Module so it can be used traits and partial classes. This allows very simple definition of meta-programming macros like the has_many that you know from Rails.

Modularity also lets you organize large models into multiple source files in a way that is less awkward than using modules.

Installation

Add the following to your Gemfile:

gem 'modularity'

Now run bundle install.

Example 1: Easy meta-programming macros

Ruby allows you to construct classes using meta-programming macros like acts_as_tree or has_many :items. These macros will add methods, callbacks, etc. to the calling class. However, right now Ruby (and Rails) makes it awkward to define such macros in your project as part of your application domain.

Modularity allows you to extract common behaviour into reusable macros by defining traits with parameters. Your macros can live in your application, allowing you to express your application domain in both classes and macros.

Here is an example of a strip_field macro, which created setter methods that remove leading and trailing whitespace from newly assigned values:

# app/models/article.rb
class Article < ActiveRecord::Base
  include DoesStripFields[:name, :brand]
end

# app/models/shared/does_strip_fields.rb
module DoesStripFields
  as_trait do |*fields|
    fields.each do |field|
      define_method("#{field}=") do |value|
        self[field] = value.strip
      end
    end
  end
end

Notice the as_trait block.

We like to add app/models/shared and app/controllers/shared to the load paths of our Rails projects. These are great places to store macros that are re-used from multiple classes.

Example 2: Mixins with class methods

Using a module to add both instance methods and class methods is very awkward. Modularity does away with the clutter and lets you say this:

# app/models/model.rb
class Model
  include Mixin
end

# app/models/mixin.rb
module Mixin
  as_trait do
    def instance_method
      # ...
    end
    def self.class_method
      # ..
    end
  end
end

private and protected will also work as expected when defining a trait.

Example 3: Splitting a model into multiple source files

Models are often concerned with multiple themes like "authentication", "contact info" or "permissions", each requiring a couple of validations and callbacks here, and some method there. Modularity lets you organize your model into multiple partial classes, so each file can deal with a single aspect of your model:

# app/models/user.rb
class User < ActiveRecord::Base
  include DoesAuthentication
  include DoesPermissions
end

# app/models/user/does_authentication.rb
module User::DoesAuthentication
  as_trait do
    # methods, validations, etc. regarding usernames and passwords go here
  end
end

# app/models/user/does_permissions.rb
module User::DoesPermissions
  as_trait do
    # methods, validations, etc. regarding contact information go here
  end
end

Some criticism has been raised for splitting large models into files like this. Essentially, even though have an easier time navigating your code, you will still have one giant model with many side effects.

There are many better ways to decompose a huge Ruby class.

Development

  • Install Bundler 2 gem install bundler:2.2.22 and run bundle install to have a working development setup.
  • Running tests for the current Ruby version: bundle exec rake
  • Running tests for all supported Ruby version: Push the changes to Github in a feature branch, open a merge request and have a look at the test matrix in Github actions

Credits

Henning Koch from makandra.com

More Repositories

1

active_type

Make any Ruby object quack like ActiveRecord
Ruby
1,036
star
2

consul

Scope-based authorization for Ruby on Rails.
Ruby
313
star
3

query_diet

A Rails database query counter that stays out of your way
Ruby
244
star
4

aegis

Complete authorization solution for Rails that supports roles and a RESTish, resource-style declaration of permission rules.
Ruby
191
star
5

spreewald

Our collection of useful cucumber steps.
Ruby
137
star
6

assignable_values

Restrict the values assignable to ActiveRecord attributes or associations.
Ruby
120
star
7

cucumber_factory

Create records from Cucumber features without writing step definitions.
Ruby
116
star
8

geordi

Collection of command line tools used in our daily work with Ruby, Rails and Linux.
Ruby
105
star
9

edge_rider

Power tools for Active Record relations (scopes)
Ruby
85
star
10

rspec_candy

RSpec helpers and matchers
Ruby
68
star
11

capybara-lockstep

Synchronize Capybara commands with application JavaScript and AJAX requests
Ruby
65
star
12

dusen

Comprehensive search solution for ActiveRecord and MySQL.
Ruby
61
star
13

gemika

Test a Ruby gem against multiple versions of everything
Ruby
61
star
14

minidusen

Low-tech search for ActiveRecord with MySQL or PostgreSQL
Ruby
32
star
15

superclamp

Cross-browser ellipsis on multi-line texts. Optimized for performance, and supports tags inside clamped element. Even looks better than -webkit-clamp. Supports all real browsers and IE11+.
HTML
29
star
16

apify

Apify lets you bolt a JSON-API onto your Rails application. UNMAINTAINED.
Ruby
27
star
17

katapult

Kickstart Rails development!
Ruby
22
star
18

rails_state_machine

Rails State Machine is an ActiveRecord-bound state machine.
Ruby
19
star
19

cucumber_spinner

Progress bar formatter for cucumber. Shows failing scenarios immediately and can automatically show the error page in the browser.
Ruby
16
star
20

mail_magnet

Mail Magnet allows you to override e-mail recipients in ActionMailer so all mails go to a given address. This library is UNMAINTAINED. Use the official ActionMailer::Base.register_interceptor API instead: https://makandracards.com/makandra/46094-rails-how-to-write-custom-email-interceptors
Ruby
15
star
21

safe_cookies

Have cookies as secure as possible
Ruby
11
star
22

validate-hls

Smoke test for HLS stream integrity
Ruby
9
star
23

upjs

Progressive enhancement, reloaded
8
star
24

machinist_callbacks

Callback hooks for machinist blueprints. UNMAINTAINED.
Ruby
7
star
25

pollyanna

Very simple search for your ActiveRecord models. UNMAINTAINED.
Ruby
7
star
26

makandra-rubocop

makandra's default Rubocop configuration
Ruby
6
star
27

rack-steady_etag

Rack Middleware that produces the same ETag for responses that only differ in CSRF tokens or CSP nonces.
Ruby
6
star
28

capistrano-opscomplete

Capistrano tasks for easy deployment to a makandra opscomplete environment.
Ruby
6
star
29

precompiled_assets

Serve assets without Rails doing any processing. Just requires a manifest file to resolve filenames.
Ruby
6
star
30

navy

Comprehensive solution for multi-level horizontal navigation bars. UNMAINTAINED.
Ruby
5
star
31

angular_xss

Patches rails_xss and Haml so AngularJS interpolations are auto-escaped in unsafe strings.
Ruby
5
star
32

memoized

Memoize your methods.
Ruby
5
star
33

ie-css-test

Tests Internet Explorer CSS breakage
HTML
4
star
34

cucumber_priority

Overridable step definitions for Cucumber
Ruby
4
star
35

makandra_sidekiq

Support code for sidekiq.
Ruby
3
star
36

rascal

Spin up CI environments locally
Ruby
3
star
37

esbuild-manifest-plugin

esbuild plugin to generate a manifest file for all digested files
JavaScript
2
star
38

angular-coffee-style-guide

Styleguide for Angular 1 using CoffeeScript
2
star
39

cloud_test

Ruby
2
star
40

akamai_tools

Akamai Tools provide some helpful tools, to deal with CCP and Net Storage.
Ruby
1
star
41

terraform-aws-modules

Collection of some standard modules for deployment in AWS accounts.
HCL
1
star
42

github-actions

1
star
43

webdev101

Examples for lecture "Grundlagen der Webentwicklung" at University of Augsburg
JavaScript
1
star
44

serum-rails

Scans a Rails application for metrics relevant to security audits. UNMAINTAINED.
Ruby
1
star
45

secret_service

Better secrets for Rails. UNMAINTAINED.
Ruby
1
star
46

micro_exiftool

Minimal ruby wrapper around exiftool
Ruby
1
star
47

cards_mvc

Sample project to evaluate JavaScript frameworks in the spirit of TodoMVC
JavaScript
1
star
48

check-config-rule-s3-lifecycle

This lambda function evaluates if an AWS Config rule is compliant. It's written to check if AWS::S3::Bucket resources with versioning enabled have a lifecycle policy. It does not check what is configured in the lifecycle policy.
Python
1
star