sinatra-has_scope 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source :gemcutter
2
+
3
+ # Specify your gem's dependencies in sinatra-has_scope.gemspec
4
+ gemspec
data/README.mdown ADDED
@@ -0,0 +1,71 @@
1
+ ## Sinatra HasScope
2
+
3
+ Sinatra HasScope is a Sinatra adaptation of the very useful [HasScope Rails library](https://github.com/plataformatec/has_scope).
4
+
5
+ Sinatra HasScope allows you to easily create filters based on your resources named scopes.
6
+ Imagine the following model called Graduation:
7
+
8
+ class Graduation < ActiveRecord::Base
9
+ scope :featured, where('featured = ?', true)
10
+ scope :by_degree, lambda { |degree| { where('degree = ?', degree) } }
11
+ end
12
+
13
+ You can use those named scopes as filters by declaring them on your routes:
14
+
15
+ class MyApp < Sinatra::Base
16
+ has_scope :gradutation, :featured, :type => :boolean
17
+ has_scope :gradutation, :by_degree
18
+ has_scope :gradutation, :by_period, :using => [:started_at, :ended_at]
19
+ end
20
+
21
+ Now, if you want to apply them to an specific resource, you just need to call `apply_scopes`:
22
+
23
+ get '/graduations' do
24
+ @graduations = apply_scopes(:graduation, Graduation, params).all
25
+ end
26
+
27
+ Then for each request:
28
+
29
+ /graduations
30
+ #=> acts like a normal request
31
+
32
+ /graduations?featured=true
33
+ #=> calls the named scope and bring featured graduations
34
+
35
+ /graduations?featured=true&by_degree=phd
36
+ #=> brings featured graduations with phd degree
37
+
38
+ /graduations?params[by_period][started_at]=20100701&params[by_period][ended_at]=20101013
39
+ #=> brings graduations in the given period
40
+
41
+ ## Installation
42
+
43
+ Sinatra HasScope is available as gem on Gemcutter, so just run the following:
44
+
45
+ sudo gem install sinatra-has_scope
46
+
47
+ To install it with bundler, use:
48
+
49
+ gem 'sinatra-has_scope', :require => 'sinatra/has_scope'
50
+
51
+ ## Options
52
+
53
+ HasScope supports several options:
54
+
55
+ * `:type` - Checks the type of the parameter sent. If set to :boolean it just calls the named scope, without any argument. By default, it does not allow hashes or arrays to be given, except if type :hash or :array are set.
56
+
57
+ * `:as` - The key in the params hash expected to find the scope. Defaults to the scope name.
58
+
59
+ * `:using` - The subkeys to be used as args when type is a hash.
60
+
61
+ * `:if` - Specifies a method, proc or string to call to determine if the scope should apply.
62
+
63
+ * `:unless` - Specifies a method, proc or string to call to determine if the scope should NOT apply.
64
+
65
+ * `:default` - Default value for the scope. Whenever supplied the scope is always called.
66
+
67
+ * `:allow_blank` - Blank values are not sent to scopes by default. Set to true to overwrite.
68
+
69
+ ## Bugs and Feedback
70
+
71
+ If you discover any bugs or want to drop a line, feel free to create an [issue on GitHub](http://github.com/simonc/sinatra-has_scope/issues).
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,5 @@
1
+ module Sinatra
2
+ module HasScope
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,141 @@
1
+ require 'sinatra/base'
2
+
3
+ module Sinatra
4
+ module HasScope
5
+ TRUE_VALUES = ["true", true, "1", 1]
6
+
7
+ ALLOWED_TYPES = {
8
+ :array => [ Array ],
9
+ :hash => [ Hash ],
10
+ :boolean => [ Object ],
11
+ :default => [ String, Numeric ]
12
+ }
13
+
14
+ attr_accessor :scopes_configuration
15
+
16
+ # Detects params from url and apply as scopes to your classes.
17
+ #
18
+ # == Options
19
+ #
20
+ # * <tt>:type</tt> - Checks the type of the parameter sent. If set to :boolean
21
+ # it just calls the named scope, without any argument. By default,
22
+ # it does not allow hashes or arrays to be given, except if type
23
+ # :hash or :array are set.
24
+ #
25
+ # * <tt>:as</tt> - The key in the params hash expected to find the scope.
26
+ # Defaults to the scope name.
27
+ #
28
+ # * <tt>:using</tt> - If type is a hash, you can provide :using to convert the hash to
29
+ # a named scope call with several arguments.
30
+ #
31
+ # * <tt>:if</tt> - Specifies a method, proc or string to call to determine
32
+ # if the scope should apply
33
+ #
34
+ # * <tt>:unless</tt> - Specifies a method, proc or string to call to determine
35
+ # if the scope should NOT apply.
36
+ #
37
+ # * <tt>:default</tt> - Default value for the scope. Whenever supplied the scope
38
+ # is always called.
39
+ #
40
+ # * <tt>:allow_blank</tt> - Blank values are not sent to scopes by default. Set to true to overwrite.
41
+ #
42
+ def has_scope(scope_group, *scopes)
43
+ options = scopes.extract_options!
44
+ options.symbolize_keys!
45
+ options.assert_valid_keys(:type, :if, :unless, :default, :as, :using, :allow_blank)
46
+
47
+ if options.key?(:using)
48
+ if options.key?(:type) && options[:type] != :hash
49
+ raise "You cannot use :using with another :type different than :hash"
50
+ else
51
+ options[:type] = :hash
52
+ end
53
+
54
+ options[:using] = [*options[:using]]
55
+ end
56
+
57
+ self.scopes_configuration ||= {}
58
+ self.scopes_configuration[scope_group] ||= {}
59
+
60
+ scopes.each do |scope|
61
+ self.scopes_configuration[scope_group][scope] ||= {
62
+ :as => scope,
63
+ :type => :default
64
+ }
65
+ self.scopes_configuration[scope_group][scope].merge!(options)
66
+ end
67
+ end
68
+
69
+ # Receives an object where scopes will be applied to.
70
+ #
71
+ # has_scope :graduation, :featured, :type => true
72
+ # has_scope :graduation, :by_degree
73
+ #
74
+ # get '/graduations' do
75
+ # @graduations = apply_scopes(:graduation, Graduation, params).all
76
+ # end
77
+ #
78
+ def apply_scopes(scope_group, target, hash)
79
+ return target unless scopes_configuration
80
+
81
+ self.scopes_configuration[scope_group].each do |scope, options|
82
+ key = options[:as].to_s
83
+
84
+ if hash.key?(key)
85
+ value, call_scope = hash[key], true
86
+ elsif options.key?(:default)
87
+ value, call_scope = options[:default], true
88
+ value = value.call(self) if value.is_a?(Proc)
89
+ end
90
+
91
+ value = parse_value(options[:type], key, value)
92
+
93
+ if call_scope && (value.present? || options[:allow_blank])
94
+ target = call_scope_by_type(options[:type], scope, target, value, options)
95
+ end
96
+ end
97
+
98
+ target
99
+ end
100
+
101
+ # Set the real value for the current scope if type check.
102
+ def parse_value(type, key, value) #:nodoc:
103
+ if type == :boolean
104
+ TRUE_VALUES.include?(value)
105
+ elsif value && ALLOWED_TYPES[type].none?{ |klass| value.is_a?(klass) }
106
+ raise "Expected type :#{type} in params[:#{key}], got #{value.class}"
107
+ else
108
+ value
109
+ end
110
+ end
111
+
112
+ # Call the scope taking into account its type.
113
+ def call_scope_by_type(type, scope, target, value, options) #:nodoc:
114
+ if type == :boolean
115
+ target.send(scope)
116
+ elsif value && options.key?(:using)
117
+ value = value.values_at(*options[:using])
118
+ target.send(scope, *value)
119
+ else
120
+ target.send(scope, value)
121
+ end
122
+ end
123
+
124
+ # Evaluates the scope options :if or :unless. Returns true if the proc
125
+ # method, or string evals to the expected value.
126
+ def applicable?(string_proc_or_symbol, expected) #:nodoc:
127
+ case string_proc_or_symbol
128
+ when String
129
+ eval(string_proc_or_symbol) == expected
130
+ when Proc
131
+ string_proc_or_symbol.call(self) == expected
132
+ when Symbol
133
+ send(string_proc_or_symbol) == expected
134
+ else
135
+ true
136
+ end
137
+ end
138
+ end
139
+
140
+ register HasScope
141
+ end
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path("../lib/sinatra/has_scope/version", __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "sinatra-has_scope"
6
+ s.version = Sinatra::HasScope::VERSION
7
+ s.platform = Gem::Platform::RUBY
8
+ s.authors = ['Simon COURTOIS']
9
+ s.email = ['scourtois@cubyx.fr']
10
+ s.homepage = "http://rubygems.org/gems/sinatra-has_scope"
11
+ s.summary = "HasScope equivalent for Sinatra"
12
+ s.description = "HasScope readaptation for the Sinatra micro-framework"
13
+
14
+ s.required_rubygems_version = ">= 1.3.6"
15
+ s.rubyforge_project = "sinatra-has_scope"
16
+
17
+ s.add_development_dependency "bundler", ">= 1.0.0"
18
+
19
+ s.files = `git ls-files`.split("\n")
20
+ s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
21
+ s.require_path = 'lib'
22
+ end
metadata ADDED
@@ -0,0 +1,91 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sinatra-has_scope
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Simon COURTOIS
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-12-06 00:00:00 +01:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: bundler
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 23
30
+ segments:
31
+ - 1
32
+ - 0
33
+ - 0
34
+ version: 1.0.0
35
+ type: :development
36
+ version_requirements: *id001
37
+ description: HasScope readaptation for the Sinatra micro-framework
38
+ email:
39
+ - scourtois@cubyx.fr
40
+ executables: []
41
+
42
+ extensions: []
43
+
44
+ extra_rdoc_files: []
45
+
46
+ files:
47
+ - .gitignore
48
+ - Gemfile
49
+ - README.mdown
50
+ - Rakefile
51
+ - lib/sinatra/has_scope.rb
52
+ - lib/sinatra/has_scope/version.rb
53
+ - sinatra-has_scope.gemspec
54
+ has_rdoc: true
55
+ homepage: http://rubygems.org/gems/sinatra-has_scope
56
+ licenses: []
57
+
58
+ post_install_message:
59
+ rdoc_options: []
60
+
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ hash: 3
69
+ segments:
70
+ - 0
71
+ version: "0"
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ hash: 23
78
+ segments:
79
+ - 1
80
+ - 3
81
+ - 6
82
+ version: 1.3.6
83
+ requirements: []
84
+
85
+ rubyforge_project: sinatra-has_scope
86
+ rubygems_version: 1.3.7
87
+ signing_key:
88
+ specification_version: 3
89
+ summary: HasScope equivalent for Sinatra
90
+ test_files: []
91
+