** Synopsis

[[https://travis-ci.org/flajann2/attr_pow][https://travis-ci.org/flajann2/attr_pow.svg?branch=master]]

attr_pow gives you POWerful attributes. You may specify defaults,
use attr_pow for hooks, and even define cloneability and queueability.
Cloneability works in concert with deep_dive.
Queueability works in concert with queue_ding.

** Motivation

attr_pow is directly derived from the internal attr_neat
attribute system we created for RubyNEAT. I've been meaning
to extract this as a seperate gem for a long time.

** Installation

From command line,
#+begin_src bash
gem install attr_pow
#+end_src

or from your Gemfile
#+begin_src ruby
gem 'attr_pow', '~> 0'
#+end_src

** Usage & Documentation

At its simplest, you may use attr_pow almost the same
as you use attr_accessor, with the understanding you only#
specify one attribute per line, for example,
#+begin_src ruby
  require 'attr_pow'
  ...
  class Foobar
    attr_pow :foo
    attr_pow :bar
    ...
#+end_src

And now, to eliminate the typical bolierplate code you normally
would have to do to initialize your attributes,
#+begin_src ruby
  require 'attr_pow'
  ...
  class Foobar
    attr_pow :foo, default: 20
    attr_pow :bar, default: "Hello World!"
    ...
#+end_src

You made need nothing more than that, but you can go further.

*** Hooks

Default values of neat attributes.

If hooks: true is given, two hook functions are created:
- <sym>_add()
  add a hook
- <sym>_set()
  set a hook, overwriting all other hooks set or added.
- <sym>_clear -- clear all hooks
- <sym>_none? -- return true if no hooks are defined.
- <sym>_one? -- return true if exactly one hook is defined.
- <sym>_hook() -- for passing unnamed parameters to a singular hook.
- <sym>_np_hook() -- for passing unnamed parameters to a singular hook.
- <sym>_hook_itself() -- for getting the proc reference to the hook.
- <sym>_hooks() -- for passing unnamed parameters.
- <sym>_np_hooks() -- for passing a named parameter list.

For *_hook(), the function returns the single result.

For *_hooks(), the hook function return an array of results
from all the actual registered hooks called.

Example:
#+begin_src ruby
  require 'attr_pow'
  require 'pp'

  class Foobar
    attr_pow :shopper, shops: true

    def customers &block
      shopper_add &block
    end

    def purchase stype
      results = shopper_shops(stype)
    end
  end

  fb = Foobar.new
  fb.customers do |stype|
    puts "Bob: #{stype} bought"
    "bob_#{stype}"
  end

  fb.customers do |stype|
    puts "James: #{stype} bought"
    "james_#{stype}"
  end

  pp fb.purchase :shirt
  pp fb.purchase :pants
#+end_src

Find and run this example in [[./examples/shops.rb][shops.rb]]

*** Cloneability

Please see the documentation at [[https://github.com/flajann2/deep_dive][Deep Dive]]. Basically,
to mark your attributes as cloneable or not:
#+begin_src ruby
  require 'attr_pow'
  ...
  class Foobar
    attr_pow :foo, default: 20, cloneable: true
    attr_pow :bar, default: "Hello World!", cloneable: false
    ...
#+end_src

And so, in using Deep Dive to clone your objects, you can mark
so attributes to be cloned, were a copy will be made, or not to be,
where a reference to that object will be done instead.

Where this is useful is in the case of a complicated object
composition where some of the objects may represent external
resources you would not want to clone, such as file handles
and database objects. Or even references to "god" objects.

"god" objects are considered a bad practice, but sometimes
the need does arise. Or you may have inherited legacy code.

*** Queues

If you mark your attribute with queue: true, a QDing queue
will automatically be created. Please see [[https://github.com/flajann2/queue_ding][QueueDing]] for more
details.

Example:
#+begin_src ruby
  require 'attr_pow'
  ...
  class Foobar
    attr_pow :queit, queue: true
    ...
#+end_src

** Release Notes

| Version |       Date | Description                               |
|---------+------------+-------------------------------------------|
|   0.0.1 | 2017-05-13 | Initial Release, extraction from RubyNEAT |

** Code of Conduct

Write awesome code, and everyone will love you.

That should be the aspiration of every contributor
to Open Source. Let's leave the politics to the politicans,
and the legal issues to the lawyers. Those who love to
hack and create and architect amazing, simple, complex,
robust, useful, fun, disruptive software, let's do so. Because
our community and the tools we use are built by great
code, written by awesome developers and engineers such as
yourself, not by politics, not by social justics warring,
not any of the ills that some claim plagues our society at large.

I've been doing this since 1978, and will continue until I
breathe my last breath. It's what I live for, and I have
had my fill of the silly political wranglings about specious
and irrevelant issues.

The Code Rocks.
End of story.

** Contributing to attr_pow

I am always open to your input. Please raise issues on this project
on GitHub. If you wish to add power to attr_pow:

- 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.
- Be 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 (c) 2017 Fred Mitchell. See LICENSE.txt for
further details.