Skip to content

Commit

Permalink
copy over from Forbidium
Browse files Browse the repository at this point in the history
  • Loading branch information
msimonborg committed Aug 3, 2017
1 parent 7d41f2f commit f5fc0e8
Show file tree
Hide file tree
Showing 74 changed files with 1,415 additions and 39 deletions.
1 change: 1 addition & 0 deletions .rspec
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--require spec_helper
19 changes: 19 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
AllCops:
TargetRubyVersion: 2.4

Metrics/BlockLength:
Exclude:
- 'allowable.gemspec'
- 'spec/**/*'
- 'Rakefile'

Metrics/LineLength:
Max: 80
Exclude:
- 'spec/**/*'
- 'allowable.gemspec'

Style/PercentLiteralDelimiters:
PreferredDelimiters:
'%i': '[]'
'%w': '[]'
38 changes: 38 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
language: ruby

rvm:
- 2.2.2
- 2.3.0
- 2.3.4
- 2.4.1
- jruby-9.1.6.0
- jruby-head
- rbx-3.74
- ruby-head

sudo: false

cache: bundler

bundler_args: --without development --retry=3 --jobs=3

before_install:
- gem update --system
- gem install bundler
- gem update bundler

env:
global:
- JRUBY_OPTS="$JRUBY_OPTS --debug"

matrix:
allow_failures:
- rvm: jruby-head
- rvm: ruby-head
- rvm: rbx-3.74
fast_finish: true

notifications:
email:
on_success: never
on_failure: always
Empty file added CHANGELOG.md
Empty file.
14 changes: 13 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
# frozen_string_literal: true

source 'https://rubygems.org'

# Specify your gem's dependencies in allowable.gemspec
# Specify your gem's dependencies in forbidium.gemspec
gemspec

group :test, :development do
gem 'coveralls', '>= 0.8.0', require: false
gem 'pry', '>= 0.10.0'
gem 'rake', '>= 10.0'
gem 'rspec-rails', '>= 3.6.0'
gem 'rubocop', '>= 0.49.0'
gem 'simplecov', '>= 0.14.0', require: false
gem 'yardstick', '>= 0.9.0'
end
74 changes: 68 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# Allowable
[![Gem Version](https://badge.fury.io/rb/allowable.svg)](https://badge.fury.io/rb/allowable)
[![Code Climate](https://codeclimate.com/github/msimonborg/allowable/badges/gpa.svg)](https://codeclimate.com/github/msimonborg/allowable)
[![Build Status](https://travis-ci.org/msimonborg/allowable.svg?branch=master)](https://travis-ci.org/msimonborg/allowable)
[![Coverage Status](https://coveralls.io/repos/github/msimonborg/allowable/badge.svg?branch=master)](https://coveralls.io/github/msimonborg/allowable?branch=master)

Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/allowable`. To experiment with that code, run `bin/console` for an interactive prompt.

TODO: Delete this and the text above, and describe your gem
Filter hashes by setting allowed or forbidden values for specific keys.

## Installation

Expand All @@ -21,8 +23,69 @@ Or install it yourself as:
$ gem install allowable

## Usage
The gem will add four methods to `Hash`: `#allow`, `#allow!`, `#forbid`, and `#forbid!`

```ruby
hash = { one: 'one', two: 'two' }

hash.forbid(one: 'one') # => { two: 'two' }

hash.allow(one: 'two') # => { two: 'two' }

hash.allow(one: ['one', 'two']) # => { one: 'one', two: 'two' }

hash.forbid(one: ['one', 'two']) # => { two: 'two' }

hash.allow!(one: 'two') # => { two: 'two' }

TODO: Write usage instructions here
hash.forbid!(two: 'two') # => {}

hash # => {}
```

#### Type sensitive for `Hash`

```ruby
hash = { 'one' => 'one', 'two' => 'two' }

hash.forbid(one: 'one') # => { "one" => "one", "two" => "two" }

hash.forbid('one' => 'one') # => { "two" => "two" }
```

## With Rails and strong parameters

When added to the `Gemfile` in a Rails project, `ActionController::Parameters` will automatically receive these methods so you can use them with your `strong_parameters`:

```ruby
def user_params
params.require(:user).permit(:email, :password, :role).forbid(role: ['sys_admin', 'owner'])
end
```

#### Type insensitive for `HashWithIndifferentAccess`
```ruby
params = ActionController::Parameters.new('one' => 'one', 'two' => 'two').permit(:one, :two)

params.forbid(one: 'one').to_h # => { "two" => "two" }

params.forbid('one' => 'one').to_h # => { "two" => "two" }
```

If your custom `Hash`-like class implements `#delete` and the `#[]` finder, you can `include Allowable` to mix in the methods.

## Platform support

This gem should work with Ruby >= 2.0.0, however at the moment it is only tested for Ruby >= 2.2.2

Tested against:
* MRI 2.2.2
* MRI 2.3.0
* MRI 2.3.4
* MRI 2.4.1
* JRuby 9.1.6.0
* JRuby HEAD
* MRI HEAD

## Development

Expand All @@ -32,10 +95,9 @@ To install this gem onto your local machine, run `bundle exec rake install`. To

## Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/allowable.
Bug reports and pull requests are welcome on GitHub at https://github.com/msimonborg/allowable.


## License

The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).

24 changes: 22 additions & 2 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -1,2 +1,22 @@
require "bundler/gem_tasks"
task :default => :spec
# frozen_string_literal: true

require 'bundler/gem_tasks'
require 'rubocop/rake_task'
require 'rspec/core/rake_task'
require 'yardstick/rake/verify'
require 'yardstick/rake/measurement'

RuboCop::RakeTask.new

RSpec::Core::RakeTask.new(:spec)

Yardstick::Rake::Measurement.new(:yardstick_measure) do |measurement|
measurement.output = 'measurement/report.txt'
end

Yardstick::Rake::Verify.new do |verify|
verify.threshold = 50
verify.require_exact_threshold = false
end

task default: %i[spec rubocop verify_measurements]
38 changes: 16 additions & 22 deletions allowable.gemspec
Original file line number Diff line number Diff line change
@@ -1,35 +1,29 @@
# coding: utf-8
# frozen_string_literal: true

lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'allowable/version'

Gem::Specification.new do |spec|
spec.name = "allowable"
spec.name = 'allowable'
spec.version = Allowable::VERSION
spec.authors = ["M. Simon Borg"]
spec.email = ["msimonborg@gmail.com"]
spec.authors = ['M. Simon Borg']
spec.email = ['msimonborg@gmail.com']

spec.summary = %q{TODO: Write a short summary, because Rubygems requires one.}
spec.description = %q{TODO: Write a longer description or delete this line.}
spec.homepage = "TODO: Put your gem's website or public repo URL here."
spec.license = "MIT"
spec.summary = 'Filter hash keys based on allowed and forbidden values.'
spec.description = 'Filter hash keys based on allowed and forbidden values.'
spec.homepage = 'https://github.com/msimonborg/allowable'
spec.license = 'MIT'

# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
# to allow pushing to a single host or delete this section to allow pushing to any host.
if spec.respond_to?(:metadata)
spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
else
raise "RubyGems 2.0 or newer is required to protect against " \
"public gem pushes."
end
spec.files = `git ls-files -z lib LICENSE.txt README.md CHANGELOG.md`.split("\0")

spec.files = `git ls-files -z`.split("\x0").reject do |f|
f.match(%r{^(test|spec|features)/})
end
spec.bindir = "exe"
spec.bindir = 'exe'
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
spec.require_paths = ['lib']

spec.required_ruby_version = '>= 2.0.0'

spec.add_development_dependency "bundler", "~> 1.14"
spec.add_development_dependency "rake", "~> 10.0"
spec.add_development_dependency 'bundler', '~> 1.14'
spec.add_development_dependency 'rake', '~> 10.0'
end
31 changes: 31 additions & 0 deletions benchmarks/allowable.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# frozen_string_literal: true

require 'benchmark'
require 'bundler/setup'
require 'allowable'
require 'action_controller'

ActionController::Parameters.class_eval do
include Allowable
end

hash = {}

1_000_000.times do |n|
hash[n] = n
end

params = ActionController::Parameters.new(hash)

Benchmark.bmbm do |bm|
bm.report('Hash#allow') { hash.allow(hash) }
bm.report('Hash#forbid') { hash.forbid(hash) }

bm.report('ActionController::Parameters#allow') do
params.allow(hash)
end

bm.report('ActionController::Parameters#forbid') do
params.forbid(hash)
end
end
7 changes: 4 additions & 3 deletions bin/console
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
#!/usr/bin/env ruby
# frozen_string_literal: true

require "bundler/setup"
require "allowable"
require 'bundler/setup'
require 'allowable'

# You can add fixtures and/or initialization code here to make experimenting
# with your gem easier. You can also use a different console, if you like.
Expand All @@ -10,5 +11,5 @@ require "allowable"
# require "pry"
# Pry.start

require "irb"
require 'irb'
IRB.start(__FILE__)
9 changes: 5 additions & 4 deletions lib/allowable.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
require "allowable/version"
# frozen_string_literal: true

module Allowable
# Your code goes here...
end
require 'allowable/version'
require 'allowable/allowable'
require 'allowable/core_ext/hash'
require 'allowable/railtie' if defined? Rails
17 changes: 17 additions & 0 deletions lib/allowable/allow.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# frozen_string_literal: true

module Allowable
# Adds the #allow and #allow! methods
module Allow
def allow(filters = {})
dup.allow!(filters)
end

def allow!(filters = {})
filters.each do |key, val|
delete(key) unless Array(val).include?(self[key])
end
self
end
end
end
26 changes: 26 additions & 0 deletions lib/allowable/allowable.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# frozen_string_literal: true

require 'allowable/allow'
require 'allowable/forbid'

# Filter hashes by setting allowed or forbidden values for specific keys.
#
# hash = { one: 'one', two: 'two' }
#
# hash.forbid(one: 'one') # => { two: 'two' }
#
# hash.allow(one: 'two') # => { two: 'two' }
#
# hash.allow(one: ['one', 'two']) # => { one: 'one', two: 'two' }
#
# hash.forbid(one: ['one', 'two']) # => { two: 'two' }
#
# hash.allow!(one: 'two') # => { two: 'two' }
#
# hash.forbid!(two: 'two') # => {}
#
# hash # => {}
module Allowable
include Forbid
include Allow
end
6 changes: 6 additions & 0 deletions lib/allowable/core_ext/hash.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# frozen_string_literal: true

# Add #allow, #allow!, #forbid, and #forbid! to Hash
class Hash
include Allowable
end
17 changes: 17 additions & 0 deletions lib/allowable/forbid.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# frozen_string_literal: true

module Allowable
# Adds the #forbid and #forbid! methods
module Forbid
def forbid(filters = {})
dup.forbid!(filters)
end

def forbid!(filters = {})
filters.each do |key, val|
delete(key) if Array(val).include?(self[key])
end
self
end
end
end
14 changes: 14 additions & 0 deletions lib/allowable/railtie.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# frozen_string_literal: true

require 'rails/railtie'

module Allowable
# Railtie initializer that adds Allowable methods to controller params
class Railtie < ::Rails::Railtie
initializer :allowable do
ActiveSupport.on_load :action_controller do
ActionController::Parameters.send :include, Allowable
end
end
end
end
Loading

0 comments on commit f5fc0e8

Please sign in to comment.