Customs Icon # Customs **Customs** uses the power of [cancancan](https://github.com/CanCanCommunity/cancancan) (formerly known as [cancan](http://github.com/ryanb/cancan/)) to control the flow of your controllers. It adds some magic in your rails controllers, through the cancan magic formula : ```load_and_authorize_resource```, and let you customize the flow. **Customs** provides you: * default cruds methods * full control on controllers methods, steps by steps * methods for HTTP statuses * common errors rescue ``` class DrogsController < ApplicationController control_and_rescue_traffic respond_to :html, :json load_and_authorize_resource :drog end ``` In the given examples, we do not endorse in any way the traffic of illegal products. Customs is watching you! ## Requirements: * Ruby 1.9.3 * Rails 3.2.18 and higher * Cancancan ## Installation Add this line to your application's Gemfile: gem 'customs' Or install it yourself as: $ gem install customs Then, take a beer. ## Usage Two methods available: * ``control_traffic`` * ``rescue_traffic`` Or only one to bind them: * ``control_and_rescue_traffic`` #### Example ``` class DrogsController < ApplicationController load_and_authorize_resource :drog control_and_rescue_traffic respond_to :html, :json end ``` #### Control traffic `control_traffic` provides you default methods to list, create, update & delete resources, depending on the cancan `load_resource` arguments. It uses exception to control the flow of data, such as: * ActiveRecord::RecordNotFound or Mongoid::Errors::DocumentNotFound * ActiveRecord::RecordInvalid or Mongoid::Errors::Validations * CanCan::AccessDenied #### Rescue traffic `rescue_traffic` provides methods for specific HTTP statuses & routes the flow exceptions to the most appropriate one. * 401 - `unauthorized` * 403 - `forbidden` * 404 - `not_found` * 422 - `unprocessable` #### Callbacks Callbacks are working like rails filters : * `before_save :make_something` * `before_save :make_something_else, only: :create` * `before_destroy :make_nothing` ``` class BaggagesController < ApplicationController load_and_authorize_resource :baggage before_save :add_illegal_content after_save :report_to_autorithies after_destroy :analyse_scraps end ``` Maybe you prefer to pass a block to `create`, `update` or `destroy` ? In this case, the block is called after the `save!` method. ``` class BaggagesController < ApplicationController load_and_authorize_resource :baggage def create super do control_content && report_to_autorithies end end end ``` #### Flow customization You can customize the controller flow by overriding any following methods: * `resource_params` - parameters attributes, which will be used to create/update resources * `success_response` - what happened after successfull action * `resource_location` - where redirect on a success response (depending on the `action_name`) For a better understanding, you have to keep in mind that `control_traffic` apply these methods with the following schema: ``` class DrogsController < ApplicationController def create resource.assign_attributes resource_params resource.save! success_response end def update resource.assign_attributes resource_params resource.save! success_response end def destroy resource.destroy success_response end protected def resource_params params[resource_name] end def success_response respond_with resource, :location => resource_location end def resource_location case action_name when 'create' then resource when 'update' then resource when 'destroy' then resource_name.to_s.pluralize.to_sym end end end ``` ##### Mass assignment I highly recommend overriding the `resource_params` method with [Strong Parameters](http://github.com/rails/strong_parameters): ``` class SmugglersController < ApplicationController load_and_authorize_resource :smuggler protected def resource_params params.require(:smuggler).permit(:name, :skills) end end ``` #### Trace errors With `rescue_traffic`, rescued errors will output something like that in you logs: ``` [Customs] Rescuing from ActionView::MissingTemplate with :not_found ``` If you need to trace the error, you just have to override the `rescue_exception_with` method: ``` def rescue_exception_with exception, method logger.error "Rescuing from #{ exception.class } with :#{ method }" exception.backtrace[0..10].each {|line| logger.error line } send method end ``` ## Contributing 1. Fork it 2. Create your feature branch (`git checkout -b my-new-feature`) 3. Commit your changes (`git commit -am 'Added some feature'`) 4. Push to the branch (`git push origin my-new-feature`) 5. Create new Pull Request #### Credits - The gem has been cutted over [cancan](https://github.com/ryanb/cancan). - The icon has been stolen to [wikimedia.org](http://wikimedia.org).