hystorical 0.2.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -99,11 +99,17 @@ $ rails g hystorical:dates Subscription
99
99
  $ create db/migrate/20120917150948_add_start_date_end_date_to_subscriptions.rb
100
100
  ```
101
101
 
102
+ ## Filtering
103
+
104
+ You can filter a dataset by passing in a block. This works similarly to Enumerable's `select` method.
105
+
106
+ ```ruby
107
+ Hystorical.current subscriptions { |subscription| subscription.type == :gold }
108
+ ```
109
+
102
110
  ## Philosophy
103
111
  This gem was created using TDD and README-driven development. The architecture was designed with a strong focus on modularity and extensibility. Using ruby's `Enumerable` methods to return current object was chosen because of it's great flexibility to adapt to all ruby projects. However, when working with large datasets stored in a relational database, using SQL would yield greater performance. An adapter was added for ActiveRecord, but extending this to another ORM (such as DataMapper or Mongoid) is as simple as creating a new class that defines all the methods in the public api and adding a conditional in `Hystorical.delegate_class`.
104
112
 
105
- ## TODO
106
- * Add ability to pass in a block option that can further filter results
107
113
 
108
114
  ## Contributing
109
115
 
@@ -2,11 +2,13 @@ module Hystorical
2
2
  class ARRelation
3
3
  class << self
4
4
  def current(collection)
5
- collection.where(end_date: nil)
5
+ current_items = collection.where(end_date: nil)
6
+ block_given? ? current_items.select { |item| yield item } : current_items
6
7
  end
7
8
 
8
9
  def current_on(collection, date)
9
- collection.where("? BETWEEN start_date AND end_date", date)
10
+ current_items = collection.where("? BETWEEN start_date AND end_date", date)
11
+ block_given? ? current_items.select { |item| yield item } : current_items
10
12
  end
11
13
  end
12
14
  end
@@ -3,18 +3,24 @@ module Hystorical
3
3
  class << self
4
4
 
5
5
  def current(collection)
6
- collection.select { |obj| obj.respond_to?(:[]) ? obj[:end_date].nil? : obj.end_date.nil? }
6
+ collection.select do |obj|
7
+ current = get_attr(obj, :end_date).nil?
8
+ block_given? ? (yield obj) && current : current
9
+ end
7
10
  end
8
11
 
9
12
  def current_on(collection, date)
10
13
  collection.select do |obj|
11
- if obj.respond_to?(:[])
12
- obj[:start_date] <= date && obj[:end_date] >= date
13
- else
14
- obj.start_date <= date && obj.end_date >= date
15
- end
14
+ current = (get_attr(obj, :start_date) <= date) && (get_attr(obj, :end_date) >= date)
15
+ block_given? ? (yield obj) && current : current
16
16
  end
17
17
  end
18
+
19
+ private
20
+ def get_attr(obj, attribute)
21
+ obj.respond_to?(:[]) ? obj[attribute] : obj.send(attribute)
22
+ end
23
+
18
24
  end
19
25
  end
20
26
  end
@@ -1,3 +1,3 @@
1
1
  module Hystorical
2
- VERSION = "0.2.0"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -5,6 +5,7 @@ describe Hystorical::ARRelation do
5
5
  with_model :Subscription do
6
6
  table do |t|
7
7
  t.integer :user_id
8
+ t.string :service
8
9
  t.date :start_date
9
10
  t.date :end_date
10
11
  end
@@ -17,16 +18,25 @@ describe Hystorical::ARRelation do
17
18
  end
18
19
 
19
20
  describe "current" do
20
- let!(:obj1) { Subscription.create(user_id: 1, start_date: Date.new(2012, 9, 1), end_date: nil) }
21
- let!(:obj2) { Subscription.create(user_id: 2, start_date: Date.new(2012, 9, 6), end_date: Date.new(2012, 9, 10)) }
22
- let!(:obj3) { Subscription.create(user_id: 2, start_date: Date.new(2012, 9, 11), end_date: nil) }
21
+ let!(:obj1) { Subscription.create(user_id: 1, service: "gold", start_date: Date.new(2012, 9, 1), end_date: nil) }
22
+ let!(:obj2) { Subscription.create(user_id: 2, service: "silver", start_date: Date.new(2012, 9, 6), end_date: Date.new(2012, 9, 10)) }
23
+ let!(:obj3) { Subscription.create(user_id: 2, service: "gold", start_date: Date.new(2012, 9, 11), end_date: nil) }
23
24
 
24
25
  it "should return the current subscription" do
25
26
  Hystorical::ARRelation.current(Subscription.for_user(2)).should eq [obj3]
26
27
  end
28
+
29
+ context "block filter" do
30
+ let!(:obj4) { Subscription.create(user_id: 2, service: "silver", start_date: Date.new(2012, 9, 6), end_date: nil) }
31
+ it "should return the current filtered subscriptions" do
32
+ Hystorical::ARRelation.current Subscription.for_user(2) do |sub|
33
+ sub.service == "silver"
34
+ end.should eq [obj4]
35
+ end
36
+ end
27
37
  end
28
38
 
29
- describe "current" do
39
+ describe "current_on" do
30
40
  let!(:obj1) { Subscription.create(user_id: 1, start_date: Date.new(2012, 9, 1), end_date: nil) }
31
41
  let!(:obj2) { Subscription.create(user_id: 2, start_date: Date.new(2012, 9, 6), end_date: Date.new(2012, 9, 10)) }
32
42
  let!(:obj3) { Subscription.create(user_id: 2, start_date: Date.new(2012, 9, 11), end_date: nil) }
@@ -34,5 +44,14 @@ describe Hystorical::ARRelation do
34
44
  it "should return the current subscription as of Sept 8" do
35
45
  Hystorical::ARRelation.current_on(Subscription.for_user(2), Date.new(2012, 9, 8)).should eq [obj2]
36
46
  end
47
+
48
+ context "block filter" do
49
+ let!(:obj4) { Subscription.create(user_id: 2, service: "gold", start_date: Date.new(2012, 9, 6), end_date: Date.new(2012, 9, 10)) }
50
+ it "should return the current filtered subscriptions" do
51
+ Hystorical::ARRelation.current_on Subscription.for_user(2), Date.new(2012, 9, 8) do |sub|
52
+ sub.service == "gold"
53
+ end.should eq [obj4]
54
+ end
55
+ end
37
56
  end
38
57
  end
@@ -2,23 +2,24 @@ require 'spec_helper'
2
2
 
3
3
  describe Hystorical::RubyCollection do
4
4
  class HistoricalObjet
5
- attr_accessor :start_date, :end_date
5
+ attr_accessor :start_date, :end_date, :type
6
6
 
7
- def initialize(start_date, end_date)
7
+ def initialize(type, start_date, end_date)
8
+ @type = type
8
9
  @start_date = start_date
9
10
  @end_date = end_date
10
11
  end
11
12
  end
12
13
 
13
- let(:obj1) { {start_date: Date.new(2012, 8, 15), end_date: Date.new(2012, 8, 26)} }
14
- let(:obj2) { {start_date: Date.new(2012, 8, 27), end_date: Date.new(2012, 9, 4)} }
15
- let(:obj3) { {start_date: Date.new(2012, 9, 5), end_date: nil} }
14
+ let(:obj1) { {type: :gold, start_date: Date.new(2012, 8, 15), end_date: Date.new(2012, 8, 26)} }
15
+ let(:obj2) { {type: :silver, start_date: Date.new(2012, 8, 27), end_date: Date.new(2012, 9, 4)} }
16
+ let(:obj3) { {type: :gold, start_date: Date.new(2012, 9, 5), end_date: nil} }
16
17
  let(:collection) { [obj1, obj2, obj3] }
17
18
 
18
19
 
19
- let(:obj4) { HistoricalObjet.new(Date.new(2012, 8, 15), Date.new(2012, 8, 26)) }
20
- let(:obj5) { HistoricalObjet.new(Date.new(2012, 8, 27), Date.new(2012, 9, 4)) }
21
- let(:obj6) { HistoricalObjet.new(Date.new(2012, 9, 5), nil) }
20
+ let(:obj4) { HistoricalObjet.new(:gold, Date.new(2012, 8, 15), Date.new(2012, 8, 26)) }
21
+ let(:obj5) { HistoricalObjet.new(:silver, Date.new(2012, 8, 27), Date.new(2012, 9, 4)) }
22
+ let(:obj6) { HistoricalObjet.new(:gold, Date.new(2012, 9, 5), nil) }
22
23
  let(:collection2) { [obj4, obj5, obj6] }
23
24
 
24
25
  describe ".current" do
@@ -33,6 +34,15 @@ describe Hystorical::RubyCollection do
33
34
  Hystorical::RubyCollection.current(collection2).should eq [obj6]
34
35
  end
35
36
  end
37
+
38
+ context "filter block" do
39
+ let(:obj5) { HistoricalObjet.new(:silver, Date.new(2012, 8, 27), nil) }
40
+ it "should be filterable via a block" do
41
+ Hystorical::RubyCollection.current collection2 do |sub|
42
+ sub.type == :silver
43
+ end.should eq [obj5]
44
+ end
45
+ end
36
46
  end
37
47
 
38
48
  describe ".current_on" do
@@ -49,5 +59,14 @@ describe Hystorical::RubyCollection do
49
59
  Hystorical::RubyCollection.current_on(collection2, date).should eq [obj5]
50
60
  end
51
61
  end
62
+
63
+ context "filter block" do
64
+ let(:obj6) { HistoricalObjet.new(:gold, Date.new(2012, 9, 5), Date.new(2012, 9, 4)) }
65
+ it "should be filterable via a block" do
66
+ Hystorical::RubyCollection.current_on collection2, date do |sub|
67
+ sub.type == :silver
68
+ end.should eq [obj5]
69
+ end
70
+ end
52
71
  end
53
72
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hystorical
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 1.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-09-17 00:00:00.000000000 Z
12
+ date: 2012-09-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec