Skip to content

jaynetics/conscious_concern

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

18 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ConsciousConcern

Gem Version Build Status Dependency Status Code Climate Test Coverage

ConsciousConcern is a decorator for ActiveSupport::Concern that adds several metaprogramming features, willfully ignoring MVC constraints.

It is useful if you have concerns that are used by a large number of models, or concerns that regulary get added to new models. It consolidates the usage of such concerns by centralizing routing, application of related concerns, migrations, and more.

The examples below are just some possible use cases.

Installation

Add it to your gemfile or run

gem install conscious_concern

Usage

If you are using Rails, add this to your application.rb / engine.rb:

config.to_prepare { ConsciousConcern.load_classes }

This will let ConsciousConcern know about your models and controllers.

Now you can extend ConsciousConcern instead of ActiveSupport::Concern in your modules.

Automatic controller integration

Let's assume you have a Likable concern for your models and a corresponding Liking concern for your controllers. Instead of including Liking manually in your controllers and keeping the controllers up to date when something new becomes Likable or something old is no longer Likable, just add a line to the model concern:

module Likable
  extend ConsciousConcern
  let_controllers(include: Liking)
  # ...
end

Now, if you add Likable to, say, your Comment model, your CommentsController will automatically include Liking. You can also use prepend: or any other methods and arguments.

Shared routes

Draw extra routes for all models that use a concern in one go.

Likable.resources do
  member do
    post 'like'
  end
  collection do
    get 'most_liked'
  end
end

# => like_comment_path(comment)
# => like_event_path(event)
# => like_post_path(post)
# ...
# => most_liked_comments_path
# => most_liked_events_path
# => most_liked_posts_path
# ...

By default, this won't draw the standard RESTful routes, because you've probably done that already.

However, you can pass the usual restriction arguments to draw some or all of them.

Likable.resources(except: [:index]) # block is optional

# => comment_path
# => edit_comment_path
# => new_comment_path
# ...

Shared migrations

Set up database fields for all models that use a concern in one go. This is probably only useful if your data model is pretty much set in stone.

Likable.tables.each do |likable_table|
  change_table likable_table do |t|
    t.integer :like_count, null: false, default: 0
  end
end

Special directory structures, Engines, and no Rails

ConsciousConcern needs to know about your models and controllers. By default, ::load_classes assumes they'll be in the standard Rails paths.

If you have models or controllers in special paths, pass these paths to ::load_classes.

ConsciousConcern.load_classes(my_special_model_dir,
                              my_other_model_dir,
                              my_controller_dir)

If you are using an Engine with the classes in the usual places, just pass it to ::load_classes.

ConsciousConcern.load_classes(engine: MyModule::MyEngine)

If you are using ActiveRecord without Rails, call ::load_classes with rails: false and pass the appropriate directories before using any of the features.

ConsciousConcern.load_classes(my_model_dir, rails: false)

In every case, subdirectories are searched automatically.

Contributions

Feel free to send suggestions, point out issues, or submit pull requests.