Skip to content

RichOrElse/wrapper-based

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

48 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

WrapperBased

Gem Version Build Status

Wrapper Based DCI framework for OOP done right.

Installation

Add this line to your application's Gemfile:

gem 'wrapper_based'

And then execute:

$ bundle

DCI::Roles

Includes role components into classes. For each role it defines private accessor methods.

Usage

It accepts Classes that can be initialized with an argument, like so:

class SignsUser < Struct.new(:signed)
  def in!(user)
    signed[:user_id] = user.id
  end

  def out!
    signed.delete(:user_id)
    @user = nil
  end

  def out?
    signed[:user_id].nil? || in?
  end

  def in?
    !user.nil?
  end

  def user
    @user ||= by(id: signed[:user_id])
  end

  def by(**identification)
    User.find_by identification
  end

  def with(**credentials)
    User.new credentials
  end

  def up!(user)
    user.save && user if User.validate_registering(user)
  end
end

Assign values using role binding methods prefixed by 'with_' and ended by an exclamation mark '!'.

class ApplicationController
  include DCI::Roles(:current_user, logged: SignsUser)

  before_action -> { with_logged! session }
  helper_method :current_user, :logged
  
  private

  def authenticate_user!
    if logged.out?
      flash[:error] = "You must be logged in to access this section"
      redirect_to login_url
    else
      with_current_user! logged.user
    end
  end
end

class LogoutController < ApplicationController
  include DCI::Roles(signing: SignsUser)

  before_action -> { with_signing! session }

  def destroy
    signing.out!
    redirect_to root_url
  end
end

It also accept Modules but no procedural code allowed, meaning only call the role player object methods and avoid calling the other methods defined in the Module.

module UserParams
  def registration
    permit(:username, :email)
  end

  def login
    permit(:username, :email)
  end

  def security
    permit(:password, :password_confirmation, :code)
  end

  def password
    fetch(:password, '')
  end
end

Mass assign values to multiple components using 'with!' method.

class LoginController < ApplicationController
  include DCI::Roles(signing: SignsUser, user_params: UserParams, login: HasEncryptedPassword)

  before_action -> { with! signing: session, user_params: params.require(:user) }
  before_action -> { with! login: signing.by(user_params.login) }

  def new; end

  def create
    if login.authenticate(user_params.password)
      signing.in! login
      redirect_to login, notice: 'Welcome, you are now logged in.'
    else
      flash[:danger] = 'Invalid credentials.'
      render :new, status: :unauthorized
    end
  end
end

A role's instance variable holds plain value (without the new behavior).

DCI::Context

Usage

class GiftToy < DCI::Context(:toy, gifter: Buyer, giftee: Recipient)
  def call(toy = @toy)
    gift = gifter.buy 
    giftee.receive gift 
  end
end

Context#to_proc

Returns call method as a Proc.

['Card Wars', 'Ice Ninja Manual', 'Bacon'].map &GiftToy[gifter: 'Jake', giftee: 'Finn']

Context::call

A shortcut for instantiating the context by passing the collaborators and then executing the context call method.

Funds::TransferMoney.(from: @account1, to: @account2, amount: 50)

Which is equivalent to:

Funds::TransferMoney.new(from: @account1, to: @account2, amount: 50).call

Context Examples

Money Transfer | Djikstra | Toy Shop | Acapella | Background Job | Facade | HTTP API Client | all examples

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake test to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/RichOrElse/wrapper-based.

License

The gem is available as open source under the terms of the MIT License.