sakuramochi 0.5.5 → 0.5.6

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,4 +1,18 @@
1
1
  *.gem
2
+ *.rbc
2
3
  .bundle
4
+ .config
5
+ .yardoc
3
6
  Gemfile.lock
4
- pkg/*
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ vendor
data/.travis.yml CHANGED
@@ -1,3 +1,6 @@
1
+ language: ruby
1
2
  rvm:
2
3
  - 1.9.2
3
4
  - 1.9.3
5
+ notifications:
6
+ irc: "irc.freenode.org#mashiro-dev"
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Sakuramochi
2
-
3
2
  [![Build Status](https://secure.travis-ci.org/mashiro/sakuramochi.png)](http://travis-ci.org/mashiro/sakuramochi)
3
+ [![Dependency Status](https://gemnasium.com/mashiro/sakuramochi.png)](https://gemnasium.com/mashiro/sakuramochi)
4
4
 
5
5
  Sakuramochi is a minimal extensions for Active Record 3.
6
6
 
@@ -84,4 +84,3 @@ User.where(:name_surrounds_with => ["ama", "umu"])
84
84
  ## Copyright
85
85
 
86
86
  Copyright (c) 2011 mashiro
87
-
data/lib/sakuramochi.rb CHANGED
@@ -1,14 +1,53 @@
1
- require 'active_support/core_ext/hash'
2
1
  require 'active_support'
2
+ require 'active_support/core_ext/hash'
3
3
  require 'active_record'
4
- require "sakuramochi/version"
5
- require 'sakuramochi/config'
6
- require 'sakuramochi/predicate'
7
- require 'sakuramochi/predicate_builder'
8
- require 'sakuramochi/condition'
9
- require 'sakuramochi/relation'
4
+ require 'sakuramochi/version'
10
5
 
11
6
  module Sakuramochi
7
+ autoload :Configuration, 'sakuramochi/configuration'
8
+ autoload :Predicate, 'sakuramochi/predicate'
9
+ autoload :PredicateBuilder, 'sakuramochi/predicate_builder'
10
+ autoload :Condition, 'sakuramochi/condition'
11
+ autoload :Relation, 'sakuramochi/relation'
12
+
13
+ def self.configure(&block)
14
+ yield @config ||= Sakuramochi::Configuration.new
15
+ end
16
+
17
+ def self.config
18
+ @config
19
+ end
20
+
21
+ configure do |config|
22
+ predicates = {
23
+ :contains => [:contains],
24
+ :starts_with => [:starts_with, :start_with],
25
+ :ends_with => [:ends_with, :end_with],
26
+ :in => [:in],
27
+ :eq => [:eq, :equal, :equals],
28
+ :gt => [:gt],
29
+ :gte => [:gte, :gteq],
30
+ :lt => [:lt],
31
+ :lte => [:lte, :lteq],
32
+ }
33
+ negative = proc { |p| "not_#{p}" }
34
+
35
+ config.add predicates[:contains], :arel_predicate => :matches, :converter => proc { |v| "%#{v}%" }
36
+ config.add predicates[:contains].map(&negative), :arel_predicate => :does_not_match, :converter => proc { |v| "%#{v}%" }
37
+ config.add predicates[:starts_with], :arel_predicate => :matches, :converter => proc { |v| "#{v}%" }
38
+ config.add predicates[:starts_with].map(&negative), :arel_predicate => :does_not_match, :converter => proc { |v| "#{v}%" }
39
+ config.add predicates[:ends_with], :arel_predicate => :matches, :converter => proc { |v| "%#{v}" }
40
+ config.add predicates[:ends_with].map(&negative), :arel_predicate => :does_not_match, :converter => proc { |v| "%#{v}" }
41
+ config.add predicates[:in], :arel_predicate => :in
42
+ config.add predicates[:in].map(&negative), :arel_predicate => :not_in
43
+ config.add predicates[:eq], :arel_predicate => :eq
44
+ config.add predicates[:eq].map(&negative), :ne, :arel_predicate => :not_eq
45
+ config.add predicates[:gt], :arel_predicate => :gt
46
+ config.add predicates[:gte], :arel_predicate => :gteq
47
+ config.add predicates[:lt], :arel_predicate => :lt
48
+ config.add predicates[:lte], :arel_predicate => :lteq
49
+ end
50
+
12
51
  ActiveSupport.on_load(:active_record) do
13
52
  ActiveRecord::Relation.send(:include, Sakuramochi::Relation)
14
53
  ActiveRecord::PredicateBuilder.send(:include, Sakuramochi::PredicateBuilder)
@@ -0,0 +1,30 @@
1
+ require 'sakuramochi/predicate'
2
+
3
+ module Sakuramochi
4
+ class Configuration
5
+ attr_accessor :predicates
6
+
7
+ def initialize
8
+ @predicates = {}
9
+ end
10
+
11
+ def add(*args)
12
+ options = args.extract_options!
13
+ options.reverse_merge!(:grouping => true)
14
+
15
+ suffixes = [nil]
16
+ suffixes += ['any', 'all'] if options[:grouping]
17
+
18
+ args.flatten.each do |name|
19
+ name = name.to_s
20
+ suffixes.each do |suffix|
21
+ predicate_name = [name, suffix].compact.join('_')
22
+ @predicates[predicate_name] = Predicate.new(options.merge({
23
+ :name => predicate_name,
24
+ :arel_predicate => [options[:arel_predicate], suffix].compact.join('_')
25
+ }))
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -1,5 +1,3 @@
1
- require 'sakuramochi/config'
2
-
3
1
  module Sakuramochi
4
2
  class Predicate
5
3
  attr_reader :name, :arel_predicate, :expand, :converter, :validator
@@ -16,7 +14,7 @@ module Sakuramochi
16
14
  def convert(value)
17
15
  return value unless @converter
18
16
  if @expand
19
- Predicate.as_a(value).map { |v| @converter.call(v) }
17
+ Array(value).map { |v| @converter.call(v) }
20
18
  else
21
19
  @converter.call(value)
22
20
  end
@@ -24,16 +22,12 @@ module Sakuramochi
24
22
 
25
23
  def validate(value)
26
24
  if @expand
27
- Predicate.as_a(value).select { |v| @validator.call(v) }.any?
25
+ Array(value).select { |v| @validator.call(v) }.any?
28
26
  else
29
27
  @validator.call(value)
30
28
  end
31
29
  end
32
30
 
33
- def self.as_a(value)
34
- value.is_a?(Enumerable) ? value.to_a : [value]
35
- end
36
-
37
31
  def self.names
38
32
  Sakuramochi.config.predicates.keys
39
33
  end
@@ -6,6 +6,49 @@ module Sakuramochi
6
6
  extend ActiveSupport::Concern
7
7
 
8
8
  included do
9
+ unless respond_to? :build
10
+ model_class = defined?(ActiveRecord::Model) ? ActiveRecord::Model : ActiveRecord::Base
11
+
12
+ def self.build(attribute, value)
13
+ case value
14
+ when ActiveRecord::Relation
15
+ value = value.select(value.klass.arel_table[value.klass.primary_key]) if value.select_values.empty?
16
+ attribute.in(value.arel.ast)
17
+ when Array, ActiveRecord::Associations::CollectionProxy
18
+ values = value.to_a.map {|x| x.is_a?(model_class) ? x.id : x}
19
+ ranges, values = values.partition {|v| v.is_a?(Range)}
20
+
21
+ values_predicate = if values.include?(nil)
22
+ values = values.compact
23
+
24
+ case values.length
25
+ when 0
26
+ attribute.eq(nil)
27
+ when 1
28
+ attribute.eq(values.first).or(attribute.eq(nil))
29
+ else
30
+ attribute.in(values).or(attribute.eq(nil))
31
+ end
32
+ else
33
+ attribute.in(values)
34
+ end
35
+
36
+ array_predicates = ranges.map { |range| attribute.in(range) }
37
+ array_predicates << values_predicate
38
+ array_predicates.inject { |composite, predicate| composite.or(predicate) }
39
+ when Range
40
+ attribute.in(value)
41
+ when model_class
42
+ attribute.eq(value.id)
43
+ when Class
44
+ # FIXME: I think we need to deprecate this behavior
45
+ attribute.eq(value.name)
46
+ else
47
+ attribute.eq(value)
48
+ end
49
+ end
50
+ end
51
+
9
52
  instance_eval do
10
53
  alias :build_from_hash_without_predicate :build_from_hash
11
54
  alias :build_from_hash :build_from_hash_with_predicate
@@ -14,7 +57,7 @@ module Sakuramochi
14
57
 
15
58
  module ClassMethods
16
59
  def build_from_hash_with_predicate(engine, attributes, default_table)
17
- predicates = attributes.map do |column, value|
60
+ attributes.map do |column, value|
18
61
  table = default_table
19
62
 
20
63
  if value.is_a?(Hash)
@@ -28,69 +71,32 @@ module Sakuramochi
28
71
  table = Arel::Table.new(table_name, engine)
29
72
  end
30
73
 
31
- column_name, predicate = Predicate.detect(column.to_s)
74
+ column_name, predicate = Sakuramochi::Predicate.detect(column.to_s)
32
75
  attribute = table[column_name.to_sym]
33
76
 
34
77
  if predicate
35
- build_attribute_with_predicate(attribute, value, predicate)
78
+ build_with_predicate(attribute, value, predicate)
36
79
  else
37
- build_attribute(attribute, value)
80
+ build(attribute, value)
38
81
  end
39
82
  end
40
- end
41
-
42
- predicates.flatten.compact
83
+ end.flatten
43
84
  end
44
85
 
45
86
  private
46
87
 
47
- def build_attribute_with_predicate(attribute, value, predicate)
88
+ def build_with_predicate(attribute, value, predicate)
48
89
  if predicate.validate(value)
49
90
  if predicate.converter
50
91
  attribute.send(predicate.arel_predicate, predicate.convert(value))
51
92
  else
52
- relation = build_attribute(attribute, value)
93
+ relation = build(attribute, value)
53
94
  attribute.send(predicate.arel_predicate, relation.right)
54
95
  end
55
96
  else
56
97
  ''
57
98
  end
58
99
  end
59
-
60
- def build_attribute(attribute, value)
61
- case value
62
- when ActiveRecord::Relation
63
- value = value.select(value.klass.arel_table[value.klass.primary_key]) if value.select_values.empty?
64
- attribute.in(value.arel.ast)
65
- when Array, ActiveRecord::Associations::CollectionProxy
66
- values = value.to_a.map {|x| x.is_a?(ActiveRecord::Base) ? x.id : x}
67
- ranges, values = values.partition {|v| v.is_a?(Range) || v.is_a?(Arel::Relation)}
68
-
69
- array_predicates = ranges.map {|range| attribute.in(range)}
70
-
71
- if values.include?(nil)
72
- values = values.compact
73
- if values.empty?
74
- array_predicates << attribute.eq(nil)
75
- else
76
- array_predicates << attribute.in(values.compact).or(attribute.eq(nil))
77
- end
78
- else
79
- array_predicates << attribute.in(values)
80
- end
81
-
82
- array_predicates.inject {|composite, predicate| composite.or(predicate)}
83
- when Range, Arel::Relation
84
- attribute.in(value)
85
- when ActiveRecord::Base
86
- attribute.eq(value.id)
87
- when Class
88
- # FIXME: I think we need to deprecate this behavior
89
- attribute.eq(value.name)
90
- else
91
- attribute.eq(value)
92
- end
93
- end
94
100
  end
95
101
 
96
102
  end
@@ -1,3 +1,3 @@
1
1
  module Sakuramochi
2
- VERSION = "0.5.5"
2
+ VERSION = "0.5.6"
3
3
  end
@@ -3,7 +3,6 @@ require 'spec_helper'
3
3
  describe Sakuramochi::Configuration do
4
4
  before do
5
5
  Sakuramochi.configure do |config|
6
- config.clear
7
6
  @config = config
8
7
  end
9
8
  end
@@ -14,18 +13,6 @@ describe Sakuramochi::Configuration do
14
13
  its(:object_id) { should eq Sakuramochi.config.object_id }
15
14
  end
16
15
 
17
- describe '#clear' do
18
- before do
19
- @config.add :test1
20
- @config.add :test2
21
- @config.add :test3, :test4
22
- @config.clear
23
- end
24
- subject { @config.predicates }
25
-
26
- it { should be_empty }
27
- end
28
-
29
16
  describe '#add' do
30
17
  before do
31
18
  @config.add :test1, :grouping => true
@@ -5,7 +5,6 @@ describe Sakuramochi::PredicateBuilder do
5
5
  describe 'matches' do
6
6
  before do
7
7
  Sakuramochi.configure do |config|
8
- config.clear
9
8
  config.add :contains, :arel_predicate => :matches, :converter => proc { |v| "%#{v}%" }
10
9
  end
11
10
  @statuses = Status.where(key => value)
@@ -86,7 +86,6 @@ describe Sakuramochi::Predicate do
86
86
  context 'config.add :test' do
87
87
  before do
88
88
  Sakuramochi.configure do |config|
89
- config.clear
90
89
  config.add :test
91
90
  end
92
91
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sakuramochi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.5
4
+ version: 0.5.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-01-10 00:00:00.000000000Z
12
+ date: 2012-05-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
16
- requirement: &22523360 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,15 @@ dependencies:
21
21
  version: '3.0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *22523360
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '3.0'
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: activerecord
27
- requirement: &22522740 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ~>
@@ -32,10 +37,15 @@ dependencies:
32
37
  version: '3.0'
33
38
  type: :runtime
34
39
  prerelease: false
35
- version_requirements: *22522740
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '3.0'
36
46
  - !ruby/object:Gem::Dependency
37
47
  name: rake
38
- requirement: &22461240 !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
39
49
  none: false
40
50
  requirements:
41
51
  - - ! '>='
@@ -43,10 +53,15 @@ dependencies:
43
53
  version: '0'
44
54
  type: :development
45
55
  prerelease: false
46
- version_requirements: *22461240
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
47
62
  - !ruby/object:Gem::Dependency
48
63
  name: rspec
49
- requirement: &22460780 !ruby/object:Gem::Requirement
64
+ requirement: !ruby/object:Gem::Requirement
50
65
  none: false
51
66
  requirements:
52
67
  - - ! '>='
@@ -54,10 +69,15 @@ dependencies:
54
69
  version: '0'
55
70
  type: :development
56
71
  prerelease: false
57
- version_requirements: *22460780
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
58
78
  - !ruby/object:Gem::Dependency
59
79
  name: sqlite3
60
- requirement: &22460360 !ruby/object:Gem::Requirement
80
+ requirement: !ruby/object:Gem::Requirement
61
81
  none: false
62
82
  requirements:
63
83
  - - ! '>='
@@ -65,7 +85,12 @@ dependencies:
65
85
  version: '0'
66
86
  type: :development
67
87
  prerelease: false
68
- version_requirements: *22460360
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
69
94
  description: Predicates and conditions that extends to the ActiveRecord 3
70
95
  email:
71
96
  - mail@mashiro.org
@@ -82,7 +107,7 @@ files:
82
107
  - Rakefile
83
108
  - lib/sakuramochi.rb
84
109
  - lib/sakuramochi/condition.rb
85
- - lib/sakuramochi/config.rb
110
+ - lib/sakuramochi/configuration.rb
86
111
  - lib/sakuramochi/predicate.rb
87
112
  - lib/sakuramochi/predicate_builder.rb
88
113
  - lib/sakuramochi/relation.rb
@@ -108,15 +133,21 @@ required_ruby_version: !ruby/object:Gem::Requirement
108
133
  - - ! '>='
109
134
  - !ruby/object:Gem::Version
110
135
  version: '0'
136
+ segments:
137
+ - 0
138
+ hash: 1227588817688317651
111
139
  required_rubygems_version: !ruby/object:Gem::Requirement
112
140
  none: false
113
141
  requirements:
114
142
  - - ! '>='
115
143
  - !ruby/object:Gem::Version
116
144
  version: '0'
145
+ segments:
146
+ - 0
147
+ hash: 1227588817688317651
117
148
  requirements: []
118
149
  rubyforge_project: sakuramochi
119
- rubygems_version: 1.8.10
150
+ rubygems_version: 1.8.21
120
151
  signing_key:
121
152
  specification_version: 3
122
153
  summary: Minimal extensions for ActiveRecord 3
@@ -1,73 +0,0 @@
1
- require 'sakuramochi/predicate'
2
-
3
- module Sakuramochi
4
- def self.configure(&block)
5
- yield @config ||= Sakuramochi::Configuration.new
6
- end
7
-
8
- def self.config
9
- @config
10
- end
11
-
12
- class Configuration
13
- attr_reader :predicates
14
-
15
- def initialize
16
- @predicates = {}
17
- end
18
-
19
- def add(*args)
20
- options = args.extract_options!
21
- options.reverse_merge!(:grouping => true)
22
- args.flatten.each do |name|
23
- name = name.to_s
24
-
25
- suffixes = [nil]
26
- suffixes += ['any', 'all'] if options[:grouping]
27
-
28
- suffixes.each do |suffix|
29
- predicate_name = [name, suffix].compact.join('_')
30
- @predicates[predicate_name] = Predicate.new(options.merge({
31
- :name => predicate_name,
32
- :arel_predicate => [options[:arel_predicate], suffix].compact.join('_')
33
- }))
34
- end
35
- end
36
- end
37
-
38
- def clear
39
- @predicates.clear
40
- end
41
- end
42
-
43
- configure do |config|
44
- # default predicates
45
- PREDICATES = {
46
- :contains => [:contains],
47
- :starts_with => [:starts_with, :start_with],
48
- :ends_with => [:ends_with, :end_with],
49
- :in => [:in],
50
- :eq => [:eq, :equal, :equals],
51
- :gt => [:gt],
52
- :gte => [:gte, :gteq],
53
- :lt => [:lt],
54
- :lte => [:lte, :lteq],
55
- }
56
- _not = proc { |p| "not_#{p}" }
57
-
58
- config.add PREDICATES[:contains], :arel_predicate => :matches, :converter => proc { |v| "%#{v}%" }
59
- config.add PREDICATES[:contains].map(&_not), :arel_predicate => :does_not_match, :converter => proc { |v| "%#{v}%" }
60
- config.add PREDICATES[:starts_with], :arel_predicate => :matches, :converter => proc { |v| "#{v}%" }
61
- config.add PREDICATES[:starts_with].map(&_not), :arel_predicate => :does_not_match, :converter => proc { |v| "#{v}%" }
62
- config.add PREDICATES[:ends_with], :arel_predicate => :matches, :converter => proc { |v| "%#{v}" }
63
- config.add PREDICATES[:ends_with].map(&_not), :arel_predicate => :does_not_match, :converter => proc { |v| "%#{v}" }
64
- config.add PREDICATES[:in], :arel_predicate => :in
65
- config.add PREDICATES[:in].map(&_not), :arel_predicate => :not_in
66
- config.add PREDICATES[:eq], :arel_predicate => :eq
67
- config.add PREDICATES[:eq].map(&_not), :ne, :arel_predicate => :not_eq
68
- config.add PREDICATES[:gt], :arel_predicate => :gt
69
- config.add PREDICATES[:gte], :arel_predicate => :gteq
70
- config.add PREDICATES[:lt], :arel_predicate => :lt
71
- config.add PREDICATES[:lte], :arel_predicate => :lteq
72
- end
73
- end