Giter VIP home page Giter VIP logo

coupons's Introduction

Coupons

Build Status Code Climate Test Coverage Gem Version Dependencies

Coupons is a Rails engine for creating discount coupons.

Installation

Add this line to your application's Gemfile:

gem 'coupons'

You also need one pagination library. You can choose between paginate or kaminari, so make sure one of these libs is added to your Gemfile as well.

gem 'paginate'
# or
gem 'kaminari'

And then execute:

$ bundle

Or install it yourself as:

$ gem install coupons

Usage

After installing Coupons, add the following line to your config/routes.rb file.

mount Coupons::Engine => '/', as: 'coupons_engine'

You can visit /coupons to access the dashboard.

Creating coupons

There are two types of coupons: percentage or amount.

  • percentage: applies the percentage discount to total amount.
  • amount: applies the amount discount to the total amount.

Defining the coupon code format

The coupon code is generated with Coupons.configuration.generator. By default, it creates a 6-chars long uppercased alpha-numeric code. You can use any object that implements the call method and returns a string. The following implementation generates coupon codes like AWESOME-B7CB.

Coupons.configure do |config|
  config.generator = proc do
    token = SecureRandom.hex[0, 4].upcase
    "AWESOME-#{token}"
  end
end

You can always override the generated coupon code through the dashboard or Ruby.

Working with coupons

Imagine that you created the coupon RAILSCONF15 as a $100 discount; you can apply it to any amount using the Coupons.apply method. Notice that this method won't redeem the coupon code and it's supposed to be used on the checkout page.

Coupons.apply('RAILSCONF15', amount: 600.00)
#=> {:amount => 600.0, :discount => 100.0, :total => 500.0}

When a coupon is invalid/non-redeemable, it returns the discount amount as 0.

Coupons.apply('invalid', amount: 100.00)
#=> {:amount => 100.0, :discount => 0, :total => 100.0}

To redeem the coupon you can use Coupon.redeem.

Coupons.redeem('RAILSCONF15', amount: 600.00)
#=> {:amount => 600.0, :discount => 100.0, :total => 500.0}

coupon = Coupons::Models::Coupon.last

coupon.redemptions_count
#=> 1

coupon.redemptions
#=> [#<Coupons::Models::CouponRedemption:0x0000010e388290>]

Defining the coupon finder strategy

By default, the first redeemable coupon is used. You can set any of the following strategies.

  • Coupons::Finders::FirstAvailable: returns the first redeemable coupon available.
  • Coupons::Finders::SmallerDiscount: returns the smaller redeemable discount available.
  • Coupons::Finders::LargerDiscount: returns the larger redeemable discount available.

To define a different strategy, set the Coupons.configurable.finder attribute.

Coupons.configure do |config|
  config.finder = Coupons::Finders::SmallerDiscount
end

A finder can be any object that receives the coupon code and the options (which must include the amount key). Here's how the smaller discount finder is implemented.

module Coupons
  module Finders
    SmallerDiscount = proc do |code, options = {}|
      coupons = Models::Coupon.where(code: code).all.select(&:redeemable?)

      coupons.min do |a, b|
        a = a.apply(options)
        b = b.apply(options)

        a[:discount] <=> b[:discount]
      end
    end
  end
end

Injecting helper methods

The whole coupon interaction can be made through some helpers methods. You can extend any object with Coupons::Helpers module. So do it in your initializer file or in your controller, whatever suits you best.

coupons = Object.new.extend(Coupons::Helpers)

Now you can do all the interactions through the coupons variable.

Authorizing access to the dashboard

Coupons has a flexible authorization system, meaning you can do whatever you want. All you have to do is defining the authorization strategy by setting Coupons.configuration.authorizer. By default, it disables access to the production environment, as you can see below.

Coupons.configure do |config|
  config.authorizer = proc do |controller|
    if Rails.env.production?
      controller.render(
        text: 'Coupons: not enabled in production environments',
        status: 403
      )
    end
  end
end

To define your own strategy, like doing basic authentication, you can do something like this:

Coupons.configure do |config|
  config.authorizer = proc do |controller|
    controller.authenticate_or_request_with_http_basic do |user, password|
      user == 'admin' && password == 'sekret'
    end
  end
end

Attaching coupons to given records

To be written.

Creating complex discount rules

To be written.

JSON endpoint

You may want to apply discounts using AJAX, so you can give instant feedback. In this case, you'll find the /coupons/apply endpoint useful.

var response = $.get('/coupons/apply', {amount: 600.0, coupon: 'RAILSCONF15'});
response.done(function(options)) {
  console.log(options);
  //=> {amount: 600.0, discount: 100.0, total: 500.0}
});

If you provide invalid amount/coupon, then it'll return zero values, like {amount: 0, discount: 0, total: 0}.

I18n support

Coupons uses I18n. It has support for en and pt-BR. You can contribute with your language by translating the file config/en.yml.

Screenshots

Viewing existing coupons

Creating coupon

Contributing

  1. Before implementing anything, create an issue to discuss your idea. This only applies to big changes and new features.
  2. Fork it ( https://github.com/fnando/coupons/fork )
  3. Create your feature branch (git checkout -b my-new-feature)
  4. Commit your changes (git commit -am 'Add some feature')
  5. Push to the branch (git push origin my-new-feature)
  6. Create a new Pull Request

coupons's People

Contributors

cabgfx avatar fnando avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

coupons's Issues

Coupon redemption limit = 0 doesn't work

  1. I create a coupon with Redemption Limit = 0 (so the number of time usage should be ∞)
  2. Then I use this coupon by this code:
    Coupons.redeem(coupon, amount: total_amount_dollars)
  3. From now, if I check coupon with:
    Coupons.apply(coupon, amount: total_amount_dollars)

Real result: The discount amount will be returned 0 in step 3
Expectation: it shouldn't be 0, because Redemption Limit = 0

Could you guys help on this? Thanks so much

Query with has_available_redemptions?

Hi there, more of a query than an issue, I have found looking through your code really really helpful and have learnt alot from it, so thank you very much for that!

I noticed one method though and I don't see how it works and was hoping you might be able to shed light on it.

https://github.com/fnando/coupons/blob/master/lib/coupons/models/coupon.rb#L65
The method named has_available_redemptions?, I assume should return true if there is no limit set(0) but from this code it will return false?

Therefore would that not make redeemable? false as well

ActiveRecord::DuplicateMigrationNameError

I'm getting an ActiveRecord::DuplicateMigrationNameError during rake db:migrate

My steps are:

  • Add to Gemfile:
gem 'kaminari' # required by coupons
gem 'coupons', :git => 'https://github.com/fnando/coupons.git'
  • bundle install
  • rake coupons:install:migrations
  • rake db:migrate which generates the following error:
rake aborted!
ActiveRecord::DuplicateMigrationNameError: 

Multiple migrations have the name SetupCoupons

I only have new 1 migration file in db/migrate and none of my existing migrations have the name SetupCoupons.

Rails 4.2.6
Ruby 2.3.1p112
Bundler 1.12.5

ERROR: relation "coupons_models_coupons" does not exist

Followed installation instructions as best as I could. I imagine there might be an generate coupons:install step that I am missing? Nothing in the readme about it. Anyone else getting this?

PG::UndefinedTable: ERROR: relation "coupons_models_coupons" does not exist LINE 5: WHERE a.attrelid = '"coupons_models_coupons"'... ^ : SELECT a.attname, format_type(a.atttypid, a.atttypmod), pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod FROM pg_attribute a LEFT JOIN pg_attrdef d ON a.attrelid = d.adrelid AND a.attnum = d.adnum WHERE a.attrelid = '"coupons_models_coupons"'::regclass AND a.attnum > 0 AND NOT a.attisdropped ORDER BY a.attnum

Doesn't seem to work with Kaminari

If I use Kaminari as my pagination library, as per b66d261, I get a:

undefined method 'paginate' for #<ActiveRecord::Relation []>

I just specified gem 'kaminari' in my Gemfile, haven't done anything else. Is there something I'm missing?

Full trace here

Features

  • Coupons with date limit
  • Coupons with usage limit
  • Coupons with amount discount
  • Coupons with percentage discount
  • Coupons tied to a given class#id (so you can define a discount that can be used with a specific product)
  • Web interface for managing coupons (with authorization)
  • Configurable coupon tokens (default with 6 alpha-numeric)
  • Web interface for viewing redeemed coupons
  • Attachments support through web interface
  • Add coupon search on dashboard (search on code and description)
  • Add coupon filtering on dashboard (expired, redeemed, redeemable)
  • Add table column to compute redeemable coupons (once a coupon is not redeemable, flag it)
  • Add pagination
  • Import coupons CSV (may also have attachments, probably through user's email)

CONTRIBUTION - Recurrent coupons

Hello @fnando , I have an idea for a contribution to your coupons gem and it is about recurrent coupons, for instance:
one coupon with code HAPPY-HOUR will be redeemable from August 24th to September 28th but it only can be redeemed on Monday, Wednesday and Friday and from 1:00PM to 2:00PM and we can make follow the other restrictions like only 100 global redeems and 3 redeems per user, etc.
We can choose if we want recurrent coupons or normal ones, if the admin doesn't select specific days by default all days are redeemable. (we can choose to be valid during those dates but only in some specific hours, like "all December from 1:00PM to 2:00PM is happy hour")
What do you think about it? We are two guys who want to contribute to open source, we'll be very happy for helping.
Greetings

redeemable? returns false when limit is set to 0.

This is pretty simple - I fixed it by changing the has_available_redemptions method to :
def has_available_redemptions? redemptions_count.zero? || redemptions_count < redemption_limit || redemption_limit == 0 end

HTTP BASIC AUTHENTICATION SECURITY CONCERN

Hi. I've started using this gem to generate coupons and its so easy and works like a charm. Saved me a hell lot of time.

The only Issue is I have is using basic authentication to authorize the person who creates the coupons.

I've read in the following links that http basic authentication is not that safe.

http://security.stackexchange.com/questions/988/is-basic-auth-secure-if-done-over-https

http://stackoverflow.com/questions/3323245/is-basic-access-authentication-secure

I was thinking is there a way where I can use my devise authentication to give access to admin(person who creates the coupons) so that it would become much secure.

I'm not even sure if that works or is a viable option. Its just a thought I have.

If we can use devise authentication and serves the purpose of security then how do we do it?

Thanks.

Request/suggestion: Unique codes

What do you think of having the Coupon model enforce uniqueness for the coupon code?

As it is today, I can create multiple coupons with the same name. I suspect this is why the larger/smaller discount finders exist?

But could they be eliminated altogether, by having Coupons::Models::Coupon use validates_uniqueness_of :name ?

Missing code in rubygems.org

After i run thebundle install, i find out this gem is incompleted. Would you mind to update this gem to rubygems.org? Thanks!

Support Rails 5.1

Hello,

I was using that gem and just upgraded to rails 5.1 where it is not supported anymore.

When I try to access to /coupons I have the following error :

undefined method "empty?" for #<Encoding:UTF-8>

Any idea how I could fix this ?

Thanks,
Gauthier

PG::NotNullViolation: ERROR: null value in column "attachments" violates not-null constraint

Hi @fnando , Great work on the gem. I was looking for exactly something like this and this surely is of great use.

So, I was trying to include this gem in my application and came across above titled error. I followed all the instructions in my local machine where I'm using MySQL and it works like a charm.

I have uploaded the code to heroku (Postgre Sql) just by pushing the master and it throws me an Internal Server Error.

Here is the trace of the error:

 Started GET "/coupons" for 183.83.215.45 at 2015-12-10 19:26:45 +0000
2015-12-10T19:26:45.073575+00:00 app[web.1]:   Rendered vendor/bundle/ruby/2.2.0/bundler/gems/coupons-0bed9cfad48a/app/views/coupons/coupons/_no_coupons.html.erb (1.5ms)
2015-12-10T19:26:45.073658+00:00 app[web.1]:   Rendered vendor/bundle/ruby/2.2.0/bundler/gems/coupons-0bed9cfad48a/app/views/coupons/coupons/index.html.erb within layouts/coupons/application (45.7ms)
2015-12-10T19:26:45.080975+00:00 app[web.1]:   Rendered vendor/bundle/ruby/2.2.0/bundler/gems/coupons-0bed9cfad48a/app/views/coupons/application/_header.html.erb (0.9ms)
2015-12-10T19:26:45.086024+00:00 app[web.1]: Completed 200 OK in 79ms (Views: 60.1ms | ActiveRecord: 6.9ms)
2015-12-10T19:26:45.007191+00:00 app[web.1]: Processing by Coupons::CouponsController#index as HTML
2015-12-10T19:26:45.084923+00:00 app[web.1]:   Rendered vendor/bundle/ruby/2.2.0/bundler/gems/coupons-0bed9cfad48a/app/views/coupons/application/_flash_messages.html.erb (0.8ms)
2015-12-10T19:26:45.094477+00:00 heroku[router]: at=info method=GET path="/coupons" host=migreratest.herokuapp.com request_id=9dc1a74f-128c-4251-94f5-83b1d07aefe0 fwd="183.83.215.45" dyno=web.1 connect=1ms service=88ms status=304 bytes=555
2015-12-10T19:26:47.722715+00:00 app[web.1]: Started GET "/coupons/new" for 183.83.215.45 at 2015-12-10 19:26:47 +0000
2015-12-10T19:26:47.730271+00:00 app[web.1]:   Rendered vendor/bundle/ruby/2.2.0/bundler/gems/coupons-0bed9cfad48a/app/views/coupons/application/_form_errors.html.erb (0.1ms)
2015-12-10T19:26:47.749549+00:00 heroku[router]: at=info method=GET path="/coupons/new" host=migreratest.herokuapp.com request_id=3a45c6e6-7fdf-4ebf-b100-1bfaf4631866 fwd="183.83.215.45" dyno=web.1 connect=1ms service=26ms status=200 bytes=8323
2015-12-10T19:26:47.738517+00:00 app[web.1]:   Rendered vendor/bundle/ruby/2.2.0/bundler/gems/coupons-0bed9cfad48a/app/views/coupons/coupons/_form.html.erb (8.9ms)
2015-12-10T19:26:47.725380+00:00 app[web.1]: Processing by Coupons::CouponsController#new as HTML
2015-12-10T19:26:47.738580+00:00 app[web.1]:   Rendered vendor/bundle/ruby/2.2.0/bundler/gems/coupons-0bed9cfad48a/app/views/coupons/coupons/new.html.erb within layouts/coupons/application (9.9ms)
2015-12-10T19:26:47.740022+00:00 app[web.1]:   Rendered vendor/bundle/ruby/2.2.0/bundler/gems/coupons-0bed9cfad48a/app/views/coupons/application/_header.html.erb (0.1ms)
2015-12-10T19:26:47.740197+00:00 app[web.1]:   Rendered vendor/bundle/ruby/2.2.0/bundler/gems/coupons-0bed9cfad48a/app/views/coupons/application/_flash_messages.html.erb (0.1ms)
2015-12-10T19:26:47.740651+00:00 app[web.1]: Completed 200 OK in 15ms (Views: 12.7ms | ActiveRecord: 0.0ms)
2015-12-10T19:27:18.995574+00:00 app[web.1]: Processing by Coupons::CouponsController#create as HTML
2015-12-10T19:27:18.995618+00:00 app[web.1]:   Parameters: {"utf8"=>"✓", "coupon"=>{"code"=>"MIGRERA100", "description"=>"Checking", "redemption_limit"=>"1", "type"=>"amount", "amount"=>"100", "valid_from(1i)"=>"2015", "valid_from(2i)"=>"12", "valid_from(3i)"=>"11", "valid_until(1i)"=>"2016", "valid_until(2i)"=>"1", "valid_until(3i)"=>"10"}, "commit"=>"Create Coupon"}
2015-12-10T19:27:19.013028+00:00 app[web.1]: PG::NotNullViolation: ERROR:  null value in column "attachments" violates not-null constraint
2015-12-10T19:27:19.013035+00:00 app[web.1]: DETAIL:  Failing row contains (2, MIGRERA100, Checking, 2015-12-11, 2016-01-10, 1, 0, 100, amount, 2015-12-10 19:27:19.003908, 2015-12-10 19:27:19.003908, null).
2015-12-10T19:27:19.013038+00:00 app[web.1]: : INSERT INTO "coupons" ("attachments", "code", "description", "amount", "type", "valid_from", "valid_until", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING "id"
2015-12-10T19:27:19.019329+00:00 app[web.1]: Completed 500 Internal Server Error in 24ms
2015-12-10T19:27:18.987570+00:00 app[web.1]: Started POST "/coupons" for 183.83.215.45 at 2015-12-10 19:27:18 +0000
2015-12-10T19:27:19.023813+00:00 app[web.1]: DETAIL:  Failing row contains (2, MIGRERA100, Checking, 2015-12-11, 2016-01-10, 1, 0, 100, amount, 2015-12-10 19:27:19.003908, 2015-12-10 19:27:19.003908, null).
2015-12-10T19:27:19.023810+00:00 app[web.1]: ActiveRecord::StatementInvalid (PG::NotNullViolation: ERROR:  null value in column "attachments" violates not-null constraint
2015-12-10T19:27:19.023816+00:00 app[web.1]:   vendor/bundle/ruby/2.2.0/gems/activerecord-4.2.0/lib/active_record/connection_adapters/postgresql_adapter.rb:602:in `exec_prepared'
2015-12-10T19:27:19.023817+00:00 app[web.1]:   vendor/bundle/ruby/2.2.0/gems/activerecord-4.2.0/lib/active_record/connection_adapters/abstract_adapter.rb:466:in `block in log'
2015-12-10T19:27:19.023818+00:00 app[web.1]:   vendor/bundle/ruby/2.2.0/gems/activesupport-4.2.0/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
2015-12-10T19:27:19.023814+00:00 app[web.1]: : INSERT INTO "coupons" ("attachments", "code", "description", "amount", "type", "valid_from", "valid_until", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING "id"):
2015-12-10T19:27:19.023819+00:00 app[web.1]:   vendor/bundle/ruby/2.2.0/gems/activerecord-4.2.0/lib/active_record/connection_adapters/abstract_adapter.rb:460:in `log'
2015-12-10T19:27:19.023817+00:00 app[web.1]:   vendor/bundle/ruby/2.2.0/gems/activerecord-4.2.0/lib/active_record/connection_adapters/postgresql_adapter.rb:602:in `block in exec_cache'
2015-12-10T19:27:19.023805+00:00 app[web.1]: 

Question: Finders

First off, thank you for such an awesome piece of work!
This gem has helped us tremendously in the past week 👍 ❤️

I was a bit confused about the finders that come with the engine by default.
Specifically, the larger/smaller discount finders. I'm not entirely sure of how/when these would be applicable.

Did you have a specific use case in mind for these two finders?

Bad installation?

I added to the config/routes.rb and when I try to start the application, I get this error:

Exiting
/Users/cooper/dev/flatzon/config/routes.rb:61:in `block in <top (required)>': uninitialized constant Coupons::Engine (NameError)
    from /Users/cooper/.rvm/gems/ruby-2.2.0@global/gems/actionpack-4.2.0/lib/action_dispatch/routing/route_set.rb:423:in `instance_exec'
    from /Users/cooper/.rvm/gems/ruby-2.2.0@global/gems/actionpack-4.2.0/lib/action_dispatch/routing/route_set.rb:423:in `eval_block'
    from /Users/cooper/.rvm/gems/ruby-2.2.0@global/gems/actionpack-4.2.0/lib/action_dispatch/routing/route_set.rb:401:in `draw'
    from /Users/cooper/dev/flatzon/config/routes.rb:1:in `<top (required)>'
    from /Users/cooper/.rvm/gems/ruby-2.2.0@global/gems/railties-4.2.0/lib/rails/application/routes_reloader.rb:40:in `block in load_paths'
    from /Users/cooper/.rvm/gems/ruby-2.2.0@global/gems/railties-4.2.0/lib/rails/application/routes_reloader.rb:40:in `each'
    from /Users/cooper/.rvm/gems/ruby-2.2.0@global/gems/railties-4.2.0/lib/rails/application/routes_reloader.rb:40:in `load_paths'
    from /Users/cooper/.rvm/gems/ruby-2.2.0@global/gems/railties-4.2.0/lib/rails/application/routes_reloader.rb:16:in `reload!'
    from /Users/cooper/.rvm/gems/ruby-2.2.0@global/gems/railties-4.2.0/lib/rails/application/routes_reloader.rb:26:in `block in updater'
    from /Users/cooper/.rvm/gems/ruby-2.2.0@global/gems/activesupport-4.2.0/lib/active_support/file_update_checker.rb:75:in `call'
    from /Users/cooper/.rvm/gems/ruby-2.2.0@global/gems/activesupport-4.2.0/lib/active_support/file_update_checker.rb:75:in `execute'
    from /Users/cooper/.rvm/gems/ruby-2.2.0@global/gems/railties-4.2.0/lib/rails/application/routes_reloader.rb:27:in `updater'
    from /Users/cooper/.rvm/gems/ruby-2.2.0@global/gems/railties-4.2.0/lib/rails/application/routes_reloader.rb:7:in `execute_if_updated'
    from /Users/cooper/.rvm/gems/ruby-2.2.0@global/gems/railties-4.2.0/lib/rails/application/finisher.rb:69:in `block in <module:Finisher>'
    from /Users/cooper/.rvm/gems/ruby-2.2.0@global/gems/railties-4.2.0/lib/rails/initializable.rb:30:in `instance_exec'
    from /Users/cooper/.rvm/gems/ruby-2.2.0@global/gems/railties-4.2.0/lib/rails/initializable.rb:30:in `run'
    from /Users/cooper/.rvm/gems/ruby-2.2.0@global/gems/railties-4.2.0/lib/rails/initializable.rb:55:in `block in run_initializers'
    from /Users/cooper/.rvm/rubies/ruby-2.2.0/lib/ruby/2.2.0/tsort.rb:226:in `block in tsort_each'
    from /Users/cooper/.rvm/rubies/ruby-2.2.0/lib/ruby/2.2.0/tsort.rb:348:in `block (2 levels) in each_strongly_connected_component'
    from /Users/cooper/.rvm/rubies/ruby-2.2.0/lib/ruby/2.2.0/tsort.rb:429:in `each_strongly_connected_component_from'
    from /Users/cooper/.rvm/rubies/ruby-2.2.0/lib/ruby/2.2.0/tsort.rb:347:in `block in each_strongly_connected_component'
    from /Users/cooper/.rvm/rubies/ruby-2.2.0/lib/ruby/2.2.0/tsort.rb:345:in `each'
    from /Users/cooper/.rvm/rubies/ruby-2.2.0/lib/ruby/2.2.0/tsort.rb:345:in `call'
    from /Users/cooper/.rvm/rubies/ruby-2.2.0/lib/ruby/2.2.0/tsort.rb:345:in `each_strongly_connected_component'
    from /Users/cooper/.rvm/rubies/ruby-2.2.0/lib/ruby/2.2.0/tsort.rb:224:in `tsort_each'
    from /Users/cooper/.rvm/rubies/ruby-2.2.0/lib/ruby/2.2.0/tsort.rb:203:in `tsort_each'
    from /Users/cooper/.rvm/gems/ruby-2.2.0@global/gems/railties-4.2.0/lib/rails/initializable.rb:54:in `run_initializers'
    from /Users/cooper/.rvm/gems/ruby-2.2.0@global/gems/railties-4.2.0/lib/rails/application.rb:352:in `initialize!'
    from /Users/cooper/dev/flatzon/config/environment.rb:5:in `<top (required)>'
    from /Users/cooper/dev/flatzon/config.ru:3:in `block in <main>'
    from /Users/cooper/.rvm/gems/ruby-2.2.0@global/gems/rack-1.6.0/lib/rack/builder.rb:55:in `instance_eval'
    from /Users/cooper/.rvm/gems/ruby-2.2.0@global/gems/rack-1.6.0/lib/rack/builder.rb:55:in `initialize'
    from /Users/cooper/dev/flatzon/config.ru:in `new'
    from /Users/cooper/dev/flatzon/config.ru:in `<main>'
    from /Users/cooper/.rvm/gems/ruby-2.2.0@global/gems/rack-1.6.0/lib/rack/builder.rb:49:in `eval'
    from /Users/cooper/.rvm/gems/ruby-2.2.0@global/gems/rack-1.6.0/lib/rack/builder.rb:49:in `new_from_string'
    from /Users/cooper/.rvm/gems/ruby-2.2.0@global/gems/rack-1.6.0/lib/rack/builder.rb:40:in `parse_file'
    from /Users/cooper/.rvm/gems/ruby-2.2.0@global/gems/rack-1.6.0/lib/rack/server.rb:299:in `build_app_and_options_from_config'
    from /Users/cooper/.rvm/gems/ruby-2.2.0@global/gems/rack-1.6.0/lib/rack/server.rb:208:in `app'
    from /Users/cooper/.rvm/gems/ruby-2.2.0@global/gems/railties-4.2.0/lib/rails/commands/server.rb:61:in `app'
    from /Users/cooper/.rvm/gems/ruby-2.2.0@global/gems/rack-1.6.0/lib/rack/server.rb:336:in `wrapped_app'
    from /Users/cooper/.rvm/gems/ruby-2.2.0@global/gems/railties-4.2.0/lib/rails/commands/server.rb:139:in `log_to_stdout'
    from /Users/cooper/.rvm/gems/ruby-2.2.0@global/gems/railties-4.2.0/lib/rails/commands/server.rb:78:in `start'
    from /Users/cooper/.rvm/gems/ruby-2.2.0@global/gems/railties-4.2.0/lib/rails/commands/commands_tasks.rb:80:in `block in server'
    from /Users/cooper/.rvm/gems/ruby-2.2.0@global/gems/railties-4.2.0/lib/rails/commands/commands_tasks.rb:75:in `tap'
    from /Users/cooper/.rvm/gems/ruby-2.2.0@global/gems/railties-4.2.0/lib/rails/commands/commands_tasks.rb:75:in `server'
    from /Users/cooper/.rvm/gems/ruby-2.2.0@global/gems/railties-4.2.0/lib/rails/commands/commands_tasks.rb:39:in `run_command!'
    from /Users/cooper/.rvm/gems/ruby-2.2.0@global/gems/railties-4.2.0/lib/rails/commands.rb:17:in `<top (required)>'
    from /Users/cooper/dev/flatzon/bin/rails:8:in `require'
    from /Users/cooper/dev/flatzon/bin/rails:8:in `<top (required)>'
    from /Users/cooper/.rvm/gems/ruby-2.2.0@flatzon/gems/spring-1.3.3/lib/spring/client/rails.rb:27:in `load'
    from /Users/cooper/.rvm/gems/ruby-2.2.0@flatzon/gems/spring-1.3.3/lib/spring/client/rails.rb:27:in `call'
    from /Users/cooper/.rvm/gems/ruby-2.2.0@flatzon/gems/spring-1.3.3/lib/spring/client/command.rb:7:in `call'
    from /Users/cooper/.rvm/gems/ruby-2.2.0@flatzon/gems/spring-1.3.3/lib/spring/client.rb:26:in `run'
    from /Users/cooper/.rvm/gems/ruby-2.2.0@flatzon/gems/spring-1.3.3/bin/spring:48:in `<top (required)>'
    from /Users/cooper/.rvm/gems/ruby-2.2.0@flatzon/gems/spring-1.3.3/lib/spring/binstub.rb:11:in `load'
    from /Users/cooper/.rvm/gems/ruby-2.2.0@flatzon/gems/spring-1.3.3/lib/spring/binstub.rb:11:in `<top (required)>'
    from /Users/cooper/.rvm/rubies/ruby-2.2.0/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require'
    from /Users/cooper/.rvm/rubies/ruby-2.2.0/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require'
    from /Users/cooper/dev/flatzon/bin/spring:13:in `<top (required)>'
    from bin/rails:3:in `load'
    from bin/rails:3:in `<main>'

Basically broken

This gem appears to be mostly broken.

I am using rails 4.2.5.1

Hit issues when I already use will_paginate.

Followed instructions and got nowhere due to odd issues with the gem picking up will_paginate instead of kaminari, I couldnt use paginate as it clashed with will_paginate.

Then once I had it installed, it didn't work due to this:

undefined method `per' for #Coupons::Models::Coupon::ActiveRecord_Relation:0x007fa26c1611b8

Then I tried running rake coupons:install:migrations and then did rake db:migrate which failed with :Multiple migrations have the name SetupCoupons -- so - uninstalling this. Big disappointment.

Rails 5 support

Hi @fnando,

Great library! I have been using it for months without any problems. Rails 5 has just been released. It would be awesome to support it as well. There are very little breaking changes.

Karens

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.