scope_composer 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ NTRkOTIwMzFmZWNjN2NjNTFkYzUwNzNkMDUyMDcxOGM5YzdhNmFjZQ==
5
+ data.tar.gz: !binary |-
6
+ OTU4NzQwZjJhZmYyM2JmNmJlMWJhYjlmMDgwMjBiMjNjODU1ODg5MA==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ ODU1YWQwMGI5YWFiODRmMTkwMWJjZjM0MWRjYWNlZmVhYjkwMmQ5YThiM2M3
10
+ ZWU1ZjQxYzI5MjkwMDIxYzk4NWQ5MzM2YWE5MDU3MDk0MzNlZWExZTQ1MGEz
11
+ MTExNjgwODZjNDIyM2NhZWFhZTUxZWIwNzUxYjEwZjI1MTg5NWU=
12
+ data.tar.gz: !binary |-
13
+ ODUwZmViZjkzNmM4NmFiZDEyZjZhOTY1NTJlNmEyYTIxNWJmN2UxYjliNjg0
14
+ YWU1NjUyYWQxYjAxMWU3MTdhMGFjZjIyMTBlNmUwZDgzMTlkZmRkNjI3MmZh
15
+ NmQ0YWZhNTkwYjczODg1NGIwZDViZTVkYzQ1OTBhMThiZTRhZWU=
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ /Gemfile.lock
2
+ /pkg
3
+ /tmp
4
+ *.gem
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour --format=Fivemat
data/.rvmrc ADDED
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # This is an RVM Project .rvmrc file, used to automatically load the ruby
4
+ # development environment upon cd'ing into the directory
5
+
6
+ # First we specify our desired <ruby>[@<gemset>], the @gemset name is optional,
7
+ # Only full ruby name is supported here, for short names use:
8
+ # echo "rvm use 1.9.3" > .rvmrc
9
+ environment_id="ruby-1.9.3-p392@scope_builder"
10
+
11
+ # Uncomment the following lines if you want to verify rvm version per project
12
+ # rvmrc_rvm_version="1.19.6 (stable)" # 1.10.1 seams as a safe start
13
+ # eval "$(echo ${rvm_version}.${rvmrc_rvm_version} | awk -F. '{print "[[ "$1*65536+$2*256+$3" -ge "$4*65536+$5*256+$6" ]]"}' )" || {
14
+ # echo "This .rvmrc file requires at least RVM ${rvmrc_rvm_version}, aborting loading."
15
+ # return 1
16
+ # }
17
+
18
+ # First we attempt to load the desired environment directly from the environment
19
+ # file. This is very fast and efficient compared to running through the entire
20
+ # CLI and selector. If you want feedback on which environment was used then
21
+ # insert the word 'use' after --create as this triggers verbose mode.
22
+ if [[ -d "${rvm_path:-$HOME/.rvm}/environments"
23
+ && -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
24
+ then
25
+ \. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
26
+ for __hook in "${rvm_path:-$HOME/.rvm}/hooks/after_use"*
27
+ do
28
+ if [[ -f "${__hook}" && -x "${__hook}" && -s "${__hook}" ]]
29
+ then \. "${__hook}" || true
30
+ fi
31
+ done
32
+ unset __hook
33
+ else
34
+ # If the environment file has not yet been created, use the RVM CLI to select.
35
+ rvm --create "$environment_id" || {
36
+ echo "Failed to create RVM environment '${environment_id}'."
37
+ return 1
38
+ }
39
+ fi
40
+
41
+ # If you use bundler, this might be useful to you:
42
+ # if [[ -s Gemfile ]] && {
43
+ # ! builtin command -v bundle >/dev/null ||
44
+ # builtin command -v bundle | GREP_OPTIONS= \grep $rvm_path/bin/bundle >/dev/null
45
+ # }
46
+ # then
47
+ # printf "%b" "The rubygem 'bundler' is not installed. Installing it now.\n"
48
+ # gem install bundler
49
+ # fi
50
+ # if [[ -s Gemfile ]] && builtin command -v bundle >/dev/null
51
+ # then
52
+ # bundle install | GREP_OPTIONS= \grep -vE '^Using|Your bundle is complete'
53
+ # fi
data/.travis.yml ADDED
@@ -0,0 +1,20 @@
1
+ language: ruby
2
+
3
+ rvm:
4
+ - 2.0.0
5
+ - 1.9.3
6
+ - 1.9.2
7
+ - 1.8.7
8
+
9
+ gemfile:
10
+ - Gemfile
11
+ - gemfiles/activemodel-4.0.gemfile
12
+
13
+ matrix:
14
+ exclude:
15
+ - rvm: 1.8.7
16
+ gemfile: gemfiles/activemodel-4.0.gemfile
17
+ - rvm: 1.9.2
18
+ gemfile: gemfiles/activemodel-4.0.gemfile
19
+
20
+ script: "echo 'COME ON!' && bundle exec rake spec"
data/.yardopts ADDED
@@ -0,0 +1,2 @@
1
+ --protected
2
+ --no-private
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source "https://rubygems.org"
2
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,7 @@
1
+ Copyright (c) 2012-2013 Blake Hilscher
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,42 @@
1
+ # ScopeComposer
2
+
3
+ ```ruby
4
+ class Example
5
+
6
+ include ScopeComposer::Model
7
+
8
+ scope_composer_for :search
9
+
10
+ search_helper :integer, ->(v){ v.to_s.to_i }
11
+
12
+ search_scope :limit
13
+ search_scope :offset, ->(i){ where(offset: integer(i) ) }
14
+
15
+ search_helper :find, ->(id){ Example.where(self.attributes).find(id) }
16
+
17
+ def self.where(attrs)
18
+ puts "where: #{attrs.to_param}"
19
+ self
20
+ end
21
+
22
+ def self.find(id)
23
+ puts "find by #{id}"
24
+ self.new
25
+ end
26
+
27
+ end
28
+
29
+ Example.limit(10).offset('50').find(10)
30
+ Example.limit(10).offset('50').to_param
31
+
32
+ scope = Example.limit(10)
33
+ scope.offset(20)
34
+ scope.find(2)
35
+
36
+ ```
37
+
38
+ ```
39
+ where: limit=10&offset=50
40
+ find by 10
41
+ Example:0x007ff8eb8ce920
42
+ ```
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require "bundler"
2
+ require "rake"
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ task :default => :spec
7
+
8
+ desc "Run all specs"
9
+ RSpec::Core::RakeTask.new(:spec) do |task|
10
+ task.pattern = "spec/**/*_spec.rb"
11
+ end
data/UPGRADE.md ADDED
@@ -0,0 +1,3 @@
1
+ ## 0.1
2
+
3
+ Initial
@@ -0,0 +1,25 @@
1
+ module ScopeComposer
2
+ module Model
3
+
4
+ extend ActiveSupport::Concern
5
+
6
+ module ClassMethods
7
+
8
+ def has_scope_composer
9
+ ScopeComposer::Scope.define_scope_composer( self, :scope )
10
+ # alias_method scope and scope_helper
11
+ self.define_singleton_method(:scope){|*args| scope_scope(*args) }
12
+ end
13
+
14
+ def scope_composer_for(*args)
15
+ # each scope_composer arg is a new type of scope
16
+ args.each do |scope_type|
17
+ # define a class method for adding scopes to the composer
18
+ ScopeComposer::Scope.define_scope_composer( self, scope_type )
19
+ end
20
+ end
21
+
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,164 @@
1
+ module ScopeComposer
2
+ class Scope
3
+
4
+ class << self
5
+
6
+ def define_scope_composer( parent_class, scope_type )
7
+ # define a class method for adding scopes to the composer
8
+ scope_subclass = define_scope_subclass( parent_class, scope_type )
9
+ # eg. dataset_scope :limit
10
+ parent_class.send(:define_singleton_method, "#{scope_type}_scope") do |*args|
11
+ # act as getter if args are nil
12
+ return scope_subclass if args.first.nil?
13
+ # delegate the scope definition to the sub-class
14
+ scope_subclass.define_scope(*args)
15
+ scope_subclass.define_scope_delegate(parent_class, scope_type, *args)
16
+ end
17
+ parent_class.send(:define_singleton_method, "#{scope_type}_helper") do |*args|
18
+ scope_subclass.define_helper(*args)
19
+ end
20
+ end
21
+
22
+ def define_scope(*args)
23
+ args[1].is_a?(Proc) ? define_proc_scope(*args) : define_simple_scopes(*args)
24
+ end
25
+
26
+ def define_helper(name, proc, *args)
27
+ # ensure symbol
28
+ name = name.to_sym
29
+ # define method
30
+ define_method(name) do |*args|
31
+ # otherwise set the value
32
+ instance_exec(*args, &proc)
33
+ end
34
+ # add to scope list
35
+ helpers[name] = proc
36
+ end
37
+
38
+ def define_scope_delegate(parent_class, scope_type, *args)
39
+ # options
40
+ options = args.extract_options!
41
+ scope_subclass = self
42
+ # for each scope name
43
+ args.each do |scope_name|
44
+ # skip non text scopes
45
+ next unless scope_name.is_a?(String) || scope_name.is_a?(Symbol)
46
+ # add prefix if required
47
+ method_name = scope_name
48
+ method_name = "#{method_name}_#{scope_type}" if options[:prefix] == true
49
+ # define method
50
+ parent_class.send(:define_singleton_method, method_name) do |*args|
51
+ # delegate the scope to an instance of this scope
52
+ scope_subclass.new.send( scope_name, *args )
53
+ end
54
+ end
55
+ end
56
+
57
+ def scope_names
58
+ @scope_names ||= scopes.keys
59
+ end
60
+
61
+ def helper_names
62
+ @helper_names ||= helpers.keys
63
+ end
64
+
65
+ def scopes
66
+ @scopes ||= {}
67
+ end
68
+
69
+ def helpers
70
+ @helpers ||= {}
71
+ end
72
+
73
+ protected
74
+
75
+ def define_scope_subclass(parent_class, scope_type)
76
+ # the class name
77
+ class_name = "#{scope_type.to_s.camelize}Scope"
78
+ # define the class if it doesn't exist
79
+ unless parent_class.const_defined?(class_name)
80
+ # the new scope class inherits from Scope
81
+ scope_class = Class.new(ScopeComposer::Scope)
82
+ # the class is attached the parent class
83
+ parent_class.const_set class_name, scope_class
84
+ end
85
+ # return the scope class
86
+ "#{parent_class.name}::#{class_name}".constantize
87
+ end
88
+
89
+ def define_proc_scope(name, proc, *args)
90
+ # ensure symbol
91
+ name = name.to_sym
92
+ # define method
93
+ define_method(name) do |*args|
94
+ # if no value is given, act as a getter and retrieve the value
95
+ return attributes[name] if args.first.nil?
96
+ # otherwise set the value
97
+ instance_exec(*args, &proc)
98
+ # and return self for chaining
99
+ self
100
+ end
101
+ define_method("#{name}=") do |value|
102
+ self.send( name, value )
103
+ end
104
+ # add to scope list
105
+ scopes[name] = proc
106
+ end
107
+
108
+ def define_simple_scopes(*args)
109
+ options = args.extract_options!
110
+ args.each { |name| define_simple_scope(name, options) }
111
+ end
112
+
113
+ def define_simple_scope(name, options)
114
+ # ensure symbol
115
+ name = name.to_sym
116
+ # define method
117
+ define_method(name) do |*args|
118
+ # init
119
+ value = args.first
120
+ # if no value is given, act as a getter
121
+ return attributes[name] if value.nil?
122
+ # otherwise set the value
123
+ where( name => value )
124
+ # and return self for chaining
125
+ return self
126
+ end
127
+ define_method("#{name}=") do |*args|
128
+ self.send( name, *args )
129
+ end
130
+ # add to scoping list
131
+ scopes[name] = nil
132
+ end
133
+
134
+ end
135
+
136
+ delegate :to_param, to: :attributes
137
+
138
+ def assign_attributes(*attrs)
139
+ attrs = attrs.extract_options!
140
+ attrs.each do |key, value|
141
+ self.send("#{key}=", value) if self.respond_to?("#{key}=")
142
+ end
143
+ end
144
+
145
+ def attributes
146
+ self.class.scopes.keys.inject({}){|m,k| m.merge( k => attributes[k] ) }
147
+ end
148
+
149
+ def where(*args)
150
+ attrs = args.extract_options!
151
+ attrs.symbolize_keys!
152
+ self.attributes = attrs
153
+ end
154
+
155
+ def attributes
156
+ @attributes ||= {}
157
+ end
158
+
159
+ def attributes=(attrs)
160
+ @attributes = self.attributes.merge(attrs)
161
+ end
162
+
163
+ end
164
+ end
@@ -0,0 +1,3 @@
1
+ module ScopeComposer
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,12 @@
1
+ require "scope_composer/version"
2
+
3
+ require "active_support"
4
+ require "active_support/inflector"
5
+ require "active_support/core_ext/hash"
6
+ require "active_support/core_ext/object"
7
+
8
+ require "scope_composer/scope"
9
+ require "scope_composer/model"
10
+
11
+ module ScopeComposer
12
+ end
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "scope_composer/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "scope_composer"
7
+ s.version = ScopeComposer::VERSION
8
+ s.authors = ["Blake Hilscher"]
9
+ s.email = ["blake@hilscher.ca"]
10
+ s.homepage = "http://blake.hilscher.ca/"
11
+ s.license = "MIT"
12
+ s.summary = "For building scopes"
13
+ s.description = "Scopes will be built"
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ["lib"]
19
+
20
+ s.add_development_dependency "rake", "~> 10.0"
21
+ s.add_development_dependency "rspec", "~> 2.13"
22
+ s.add_development_dependency "fivemat", "~> 1.2"
23
+ s.add_development_dependency "pry"
24
+
25
+ s.add_runtime_dependency "activesupport", ">= 3.0.0"
26
+ end
@@ -0,0 +1,38 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe ScopeComposer::Model do
5
+ subject do
6
+ class TestClass
7
+ include ScopeComposer::Model
8
+
9
+ has_scope_composer
10
+ scope :say_hi, ->(t){ 'hi' }
11
+ scope_helper :helper_method, ->(t){ 'hi' }
12
+
13
+ scope_composer_for :search
14
+
15
+ search_scope :limit
16
+ search_scope :offset, prefix: true
17
+ search_helper :tester, ->(t){ t.to_i }
18
+
19
+ end
20
+ TestClass
21
+ end
22
+
23
+ it { should respond_to :scope_composer_for }
24
+ it { should respond_to :scope_scope }
25
+ it { should respond_to :scope }
26
+ it { should respond_to :say_hi }
27
+
28
+ it { should respond_to :search_scope }
29
+ it { should respond_to :search_helper }
30
+ it { should respond_to :limit }
31
+ it { should respond_to :offset_search }
32
+ it { should_not respond_to :tester }
33
+
34
+ it "should define a scope helper" do
35
+ TestClass.say_hi('hi').should respond_to :helper_method
36
+ end
37
+
38
+ end
@@ -0,0 +1,4 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
2
+
3
+ require "rspec"
4
+ require "scope_composer"
metadata ADDED
@@ -0,0 +1,133 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: scope_composer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Blake Hilscher
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-07-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ~>
17
+ - !ruby/object:Gem::Version
18
+ version: '10.0'
19
+ type: :development
20
+ prerelease: false
21
+ name: rake
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '10.0'
27
+ - !ruby/object:Gem::Dependency
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: '2.13'
33
+ type: :development
34
+ prerelease: false
35
+ name: rspec
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '2.13'
41
+ - !ruby/object:Gem::Dependency
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ~>
45
+ - !ruby/object:Gem::Version
46
+ version: '1.2'
47
+ type: :development
48
+ prerelease: false
49
+ name: fivemat
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '1.2'
55
+ - !ruby/object:Gem::Dependency
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ! '>='
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ type: :development
62
+ prerelease: false
63
+ name: pry
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ! '>='
73
+ - !ruby/object:Gem::Version
74
+ version: 3.0.0
75
+ type: :runtime
76
+ prerelease: false
77
+ name: activesupport
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: 3.0.0
83
+ description: Scopes will be built
84
+ email:
85
+ - blake@hilscher.ca
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - .gitignore
91
+ - .rspec
92
+ - .rvmrc
93
+ - .travis.yml
94
+ - .yardopts
95
+ - Gemfile
96
+ - LICENSE
97
+ - README.md
98
+ - Rakefile
99
+ - UPGRADE.md
100
+ - lib/scope_composer.rb
101
+ - lib/scope_composer/model.rb
102
+ - lib/scope_composer/scope.rb
103
+ - lib/scope_composer/version.rb
104
+ - scope_composer.gemspec
105
+ - spec/scope_composer/model_spec.rb
106
+ - spec/spec_helper.rb
107
+ homepage: http://blake.hilscher.ca/
108
+ licenses:
109
+ - MIT
110
+ metadata: {}
111
+ post_install_message:
112
+ rdoc_options: []
113
+ require_paths:
114
+ - lib
115
+ required_ruby_version: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ! '>='
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ required_rubygems_version: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ! '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ requirements: []
126
+ rubyforge_project:
127
+ rubygems_version: 2.0.5
128
+ signing_key:
129
+ specification_version: 4
130
+ summary: For building scopes
131
+ test_files:
132
+ - spec/scope_composer/model_spec.rb
133
+ - spec/spec_helper.rb