sakuramochi 0.5.5 → 0.5.6

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 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