less_interactions
A new way to think about your Ruby applications.
What is it?
Less::Interactions are a place to put all of your business logic. They’re intended to be used primarily inside a rails app but they don’t need rails to work.
What problem is it solving?
Rails is great, but if you build a rails app of any size you start running into problems:
-
ActiveRecord’s before & after filters are the devil.
-
The code paths in my rails app are a fucking mess.
-
Where do I put this bit of code?
-
Having a model call another model just to call the previous model is stupid and error prone.
-
Where is the entry point to my app? Sometimes you access the app from places other than the controller (cron, console, background jobs), how do you know a safe entry point.
-
What are all the side effects of calling this method?
What do I do?!
Less::Interactions are a place to put all of your business logic and still get all the rails goodness you love.
Example
Before:
class ExpensesController < ApplicationController
def create
@expense = current_business.expenses.create params[:expense]
respond_with @expense
end
end
class Expense < ActiveRecord::Base
# all sorts of before and after filters
# doing things like updating bank account balances, budgets
# creating other models like ExpenseItem or Transaction
end
After:
# You don't need a context class, but we really like using one.
class Context
def initialize *args
args[0].each do |name, value|
instance_variable_set "@#{name}", value
eval "def #{name}; instance_variable_get :@#{name}; end"
end
end
end
#Controller is basically the same
class ExpensesController < ApplicationController
def create
@expense = Expenses::Save.run Context.new( business:current_business, user: current_user, params: params), some_other_thing_the_interaction_needs: "boo"
respond_with @expense
end
end
# found in /app/interactions/expenses.save.rb
class Expenses::Save < Less::Interaction
# A simple way of both enforcing params get passed in and creates and i_var and a getter for each expects
# set an expectation for all the objects the context provides
expects :some_other_thing_the_interaction_needs, allow_nil: true
expects :business
expects :user
#only one of these is required
expects_any :need_this, :or, :this
# method chain in use case is easy to see.
def run
do_somthing_with some_other_thing_the_interaction_needs
build_or_find_an_expense
setup_expense_items
setup_transaction
return @expense unless valid?
save
update_budgets
update_bank_accounts
@expense
end
private
# implementation of other methods
# some of which call other interactions
end
Contributing to less_interactions
-
Check out the latest master to make sure the feature hasn’t been implemented or the bug hasn’t been fixed yet.
-
Check out the issue tracker to make sure someone already hasn’t requested it and/or contributed it.
-
Fork the project.
-
Start a feature/bugfix branch.
-
Commit and push until you are happy with your contribution.
-
Make sure to add tests for it. This is important so I don’t break it in a future version unintentionally.
-
Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
Copyright
Copyright © 2015 LessEverything See LICENSE.txt for further details.