# RefCode A ruby gem for converting arbitrary Ruby objects into encrypted, URL-safe strings. The strings can be easily decrypted later for use in your application. RefCode was conceived as a way to attach referral data to tracking links. Encryption makes it unlikely that the links will be tampered with. Still, it is not recommended for sensitive data! ## Why would you want this? Lets say your app needs to track activity around certain pages that are shared among your users. Using RefCode, you can generate URLs pointing to these pages that are meant to be shared across various channels (email, facebook, etc). These links can carry a small amount of encoded data as part of the URL that will guarantee that any events you track due to visits to these links can make use of this extra encoded data. The data might include, for example, which user originally shared the link and on which channel she did so. A secondary feature offered by the `Refcode::Encodable` mixin is the ability to guarantee that a given code works only for one (or more) specific page. For example, by using a unique value for the `salt` option that is tied to a single record, the generated code cannot be used with any other record. See the usage example below for a demonstration of this. ## Implementation - **Encryption** using the AES-256-CBC algorithm with https://github.com/attr-encrypted/encryptor which wraps the Ruby OpenSSL library. - **Base64 encoding** is handled by https://github.com/nojima/base64url which implements a slight tweak to the standard Base64 algorithm to create URL-safe strings. - **Serialization** with YAML. ## Installation Add this line to your application's Gemfile: gem 'refcode' And then execute: $ bundle Or install it yourself as: $ gem install refcode ## Usage RefCode can be used in two ways. Most simply, you can use the `Refcode::Encoder` class directly. ```ruby encoder = Refcode::Encoder.new do |e| e.secret = "a long crunchy secret" e.salt = "some salt" end something = OpenStruct.new(channel: 'facebook', action: 'message', user_id: 43765) encoded_param = encoder.encode something # in some future request: something = encoder.decode params[:encoded_param] puts something.channel #=> 'facebook' ``` For added convenience when using Refcode with an ORM such as ActiveRecord, a module called `Refcode::Encodable` is also provided. ```ruby class Job < ActiveRecord::Base include Refcode::Encodable has_refcode secret: 'a long crunchy secret', salt: :id end # the salt option of the has_refcode method can accept a proc/lambda, string # or a symbol representing an existing method on the class (id in this case) # in some controller code: @job = Job.find params[:id] referral_code = @job.generate_refcode channel: 'facebook', action: 'message', user_id: 43765 # and in another action: @job = Job.find params[:id] referral_data = @job.parse_refcode params[:encoded_param] ``` ## Features for 1.0 - ~~Encodable mixin~~ - ~~Better exception handling~~ - More complete tests against encoding non-core ruby class values ## Contributing 1. Fork it 2. Create your feature branch (`git checkout -b my-new-feature`) 3. Commit your changes (`git commit -am 'Add some feature'`) 4. Push to the branch (`git push origin my-new-feature`) 5. Create new Pull Request