csv_record 1.4.0 → 1.5.0

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/README.md CHANGED
@@ -27,10 +27,12 @@ $ gem install csv_record
27
27
  ## Usage
28
28
 
29
29
  ```ruby
30
- requite 'csv_record'
30
+ require 'csv_record'
31
31
 
32
32
  class Car
33
33
  include CsvRecord::Document
34
+
35
+ attr_accessor :year, :make, :model, :description, :price
34
36
  end
35
37
  ```
36
38
 
@@ -70,6 +72,54 @@ Car.first # retrieves the first record in the database
70
72
  Car.last # retrieves the last record in the database
71
73
  ```
72
74
 
75
+ ##Associations
76
+ ###Belongs To
77
+ A Belongs To association can be declared through the following method:
78
+ ```ruby
79
+ class Company
80
+ include CsvRecord::Document
81
+
82
+ attr_accessor :name
83
+ end
84
+
85
+ class Car
86
+ include CsvRecord::Document
87
+
88
+ belongs_to :company
89
+ end
90
+
91
+ company = Company.create :name => 'Chuts'
92
+
93
+ car = Car.new :model => 'F450'
94
+
95
+ car.company = company
96
+ # or
97
+ car.company_id = company.id
98
+
99
+ car.save
100
+
101
+ car.company # #<Company:0x007f9b249b24d8>
102
+ ```
103
+
104
+ ###Has Many
105
+ Extending the previous example, you can use the `has_many` method to stablish the inverse relationship:
106
+ ```ruby
107
+ class Company
108
+ include CsvRecord::Document
109
+
110
+ has_many :cars
111
+
112
+ attr_accessor :name
113
+ end
114
+
115
+ company = Company.create :name => 'Chutz'
116
+
117
+ car.company = company
118
+ car.save
119
+
120
+ company.cars # [#<Car:0x007f9b249b24d8>]
121
+ ```
122
+
73
123
  ##Callbacks
74
124
  Callbacks can be used to execute code on predetermined moments.
75
125
 
@@ -82,6 +132,7 @@ after_create do |obj|
82
132
  obj.do_something
83
133
  end
84
134
  ```
135
+ `obj` refers to the instance you are in
85
136
 
86
137
  ##Precautions
87
138
  CsvRecord creates a `db` folder in the root of your application. Be sure that it has permission to do so.
data/csv_record.gemspec CHANGED
@@ -15,6 +15,8 @@ Gem::Specification.new do |gem|
15
15
  gem.require_paths = ["lib"]
16
16
  gem.version = CsvRecord::VERSION
17
17
 
18
+ gem.add_dependency 'activesupport'
19
+
18
20
  gem.add_development_dependency 'rake'
19
21
  gem.add_development_dependency 'timecop'
20
22
  gem.add_development_dependency 'turn'
@@ -0,0 +1,31 @@
1
+ module CsvRecord
2
+ module Associations
3
+ def belongs_to(klass)
4
+ klass_name = klass.to_s
5
+
6
+ self.class_eval do
7
+ self.send :attr_writer, "#{klass}_id"
8
+
9
+ define_method klass do
10
+ klass_name.to_class.find self.id
11
+ end
12
+ define_method "#{klass}=" do |value|
13
+ self.send "#{klass}_id=", value.to_param
14
+ end
15
+ define_method "#{klass}_id" do
16
+ eval("@#{klass}_id").to_i
17
+ end
18
+ end
19
+ end
20
+
21
+ def has_many(klass)
22
+ klass_name = klass.to_s
23
+
24
+ self.class_eval do
25
+ define_method klass do
26
+ klass_name.to_class.where :"#{self.underscored_class_name}_id" => self.id
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -1,9 +1,12 @@
1
+ require 'active_support/core_ext/string/inflections.rb'
2
+
1
3
  require 'csv_record/connector'
2
4
  require 'csv_record/writer'
3
5
  require 'csv_record/reader'
4
6
  require 'csv_record/timestamps'
5
7
  require 'csv_record/callbacks'
6
8
  require 'csv_record/helpers'
9
+ require 'csv_record/associations'
7
10
 
8
11
  module CsvRecord
9
12
 
@@ -11,21 +14,19 @@ module CsvRecord
11
14
  # the database.
12
15
  module Document
13
16
  def self.included(receiver)
14
- self.const_set('DATABASE_LOCATION',"db/#{parse_caller(caller[1]).downcase}.csv")
15
- self.const_set('DATABASE_LOCATION_TMP',"db/#{parse_caller(caller[1]).downcase}_tmp.csv")
17
+ klass = receiver.name
18
+
19
+ receiver.const_set 'DATABASE_LOCATION',"db/#{klass.underscore.pluralize}.csv"
20
+ receiver.const_set 'DATABASE_LOCATION_TMP',"db/#{klass.underscore.pluralize}_tmp.csv"
16
21
 
17
22
  receiver.extend CsvRecord::Connector
18
23
  receiver.extend CsvRecord::Writer::ClassMethods
19
24
  receiver.extend CsvRecord::Reader::ClassMethods
25
+ receiver.extend CsvRecord::Associations
20
26
  receiver.send :include, CsvRecord::Writer::InstanceMethods
21
27
  receiver.send :include, CsvRecord::Reader::InstanceMethods
22
28
  receiver.send :include, CsvRecord::Timestamps
23
29
  receiver.send :include, CsvRecord::Callbacks
24
30
  end
25
-
26
- def self.parse_caller(at)
27
- /(?:(\<class\:)(\w+))/ =~ at
28
- $2
29
- end
30
31
  end
31
32
  end
@@ -8,4 +8,28 @@ class Object
8
8
  self.to_s =~ /^\d+\.\d+$/
9
9
  !$0.empty?
10
10
  end
11
+
12
+ def to_param
13
+ self
14
+ end
15
+
16
+ def underscored_class_name
17
+ self.class.name.underscore
18
+ end
19
+ end
20
+
21
+ class String
22
+ def constantize
23
+ self.split('_').map {|w| w.capitalize}.join
24
+ end
25
+ def to_class
26
+ Object.const_get self.constantize.singularize
27
+ end
28
+ def underscore
29
+ self.gsub(/::/, '/').
30
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
31
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
32
+ tr("-", "_").
33
+ downcase
34
+ end
11
35
  end
@@ -7,12 +7,12 @@ module CsvRecord
7
7
  inst = new
8
8
  params.each do |key, value|
9
9
  inst.public_send("#{key}=", value)
10
- end
10
+ end if params
11
11
  inst
12
12
  end
13
13
 
14
14
  def __fields__
15
- instance_methods(false).select { |m| m.to_s !~ /=$/ }
15
+ @relevant_instance_variables
16
16
  end
17
17
 
18
18
  def all
@@ -35,9 +35,8 @@ module CsvRecord
35
35
  end
36
36
  end
37
37
 
38
- def __find__(param)
39
- param = param.id unless param.is_a? Integer
40
- (__where__ id: param).first
38
+ def __find__(condition)
39
+ (__where__ id: condition.to_param).first
41
40
  end
42
41
 
43
42
  def __where__(params)
@@ -102,8 +101,13 @@ module CsvRecord
102
101
  Hash[self.class.fields.zip self.values]
103
102
  end
104
103
 
104
+ def __to_param__
105
+ self.id
106
+ end
107
+
105
108
  alias :attributes :__attributes__
106
109
  alias :values :__values__
110
+ alias :to_param :__to_param__
107
111
  end
108
112
  end
109
113
  end
@@ -1,3 +1,3 @@
1
1
  module CsvRecord
2
- VERSION = "1.4.0"
2
+ VERSION = "1.5.0"
3
3
  end
@@ -1,5 +1,3 @@
1
- require 'csv'
2
-
3
1
  module CsvRecord
4
2
  module Writer
5
3
  module ClassMethods
@@ -11,6 +9,14 @@ module CsvRecord
11
9
  instance
12
10
  end
13
11
 
12
+ [:attr_accessor, :attr_writer].each do |custom_accessor|
13
+ define_method custom_accessor do |*args|
14
+ @relevant_instance_variables ||= []
15
+ args.each { |arg| @relevant_instance_variables << arg }
16
+ super *args
17
+ end
18
+ end
19
+
14
20
  alias :create :__create__
15
21
  end
16
22
 
@@ -53,6 +59,9 @@ module CsvRecord
53
59
 
54
60
  def calculate_id
55
61
  @id = self.class.count + 1
62
+ # if self.respond_to? :jedi_order_id
63
+ # p "#{self.class} -> #{@id} -> #{self.jedi_order_id}"
64
+ # end
56
65
  end
57
66
 
58
67
  def append_registry
@@ -0,0 +1,48 @@
1
+ require_relative '../test_helper'
2
+
3
+ require_relative '../models/jedi'
4
+ require_relative '../models/jedi_order'
5
+
6
+ describe CsvRecord::Associations do
7
+ describe 'initializing class methods' do
8
+ it ('responds to belongs_to') { Jedi.must_respond_to :belongs_to }
9
+ it ('responds to jedi_order') { Jedi.new.must_respond_to :jedi_order }
10
+ it ('responds to jedi_order=') { Jedi.new.must_respond_to :jedi_order= }
11
+ it ('responds to jedi_order_id') { Jedi.new.must_respond_to :jedi_order_id }
12
+ it ('responds to has_many') { JediOrder.must_respond_to :has_many }
13
+ end
14
+
15
+ describe 'belongs_to behavior' do
16
+ it 'checking to param extraction' do
17
+ jedi_council.save
18
+ luke.save
19
+ luke.jedi_order = jedi_council
20
+ luke.jedi_order_id.wont_be_nil
21
+ luke.jedi_order_id.must_be_instance_of Fixnum
22
+ luke.jedi_order_id.must_equal 1
23
+ end
24
+
25
+ it 'has a single jedi order associated' do
26
+ jedi_council.save
27
+ luke.jedi_order = jedi_council
28
+ luke.save.must_equal true
29
+ first_jedi = Jedi.first
30
+ first_jedi.jedi_order.wont_be_nil
31
+ first_jedi.jedi_order_id.must_be_instance_of Fixnum
32
+ first_jedi.jedi_order.must_be_instance_of JediOrder
33
+ end
34
+ end
35
+
36
+ describe 'has_many behavior' do
37
+ it 'has many jedis associated' do
38
+ jedi_council.save
39
+ yoda.jedi_order = jedi_council
40
+ yoda.save
41
+ Jedi.create name: 'Qui-Gon Jinn', age: 37, midi_chlorians: '3k', jedi_order: jedi_council
42
+ luke.save
43
+ jedis = jedi_council.jedis
44
+ jedis.count.must_equal 2
45
+ jedis.first.must_be_instance_of Jedi
46
+ end
47
+ end
48
+ end
@@ -63,6 +63,13 @@ describe CsvRecord::Reader do
63
63
  Car.count.must_equal 2
64
64
  end
65
65
 
66
+ it 'checking to_param' do
67
+ car.save
68
+ car.to_param.wont_be_nil
69
+ car.to_param.must_be_instance_of Fixnum
70
+ car.to_param.must_equal 1
71
+ end
72
+
66
73
  describe 'simple query' do
67
74
  let (:cars) { [] }
68
75
 
@@ -118,8 +125,8 @@ describe CsvRecord::Reader do
118
125
  result = Car.where year: 2008, make: 'Chevroletion'
119
126
  result.must_be_empty
120
127
  end
121
-
122
128
  end
129
+
123
130
  describe 'dynamic finders' do
124
131
  before do
125
132
  car.save
@@ -22,7 +22,7 @@ describe CsvRecord::Writer do
22
22
 
23
23
  describe 'validating the methods behavior' do
24
24
  let(:second_car) do
25
- Car.new(
25
+ Car.build(
26
26
  year: 2007,
27
27
  make: 'Chevrolet',
28
28
  model: 'F450',
@@ -0,0 +1,15 @@
1
+ require 'csv_record'
2
+
3
+ class Jedi
4
+ include CsvRecord::Document
5
+
6
+ belongs_to :jedi_order
7
+
8
+ def initialize(params={})
9
+ params.each do |key, value|
10
+ self.public_send("#{key}=", value)
11
+ end
12
+ end
13
+
14
+ attr_accessor :name, :age, :midi_chlorians
15
+ end
@@ -0,0 +1,15 @@
1
+ require 'csv_record'
2
+
3
+ class JediOrder
4
+ include CsvRecord::Document
5
+
6
+ has_many :jedis
7
+
8
+ def initialize(params={})
9
+ params.each do |key, value|
10
+ self.public_send("#{key}=", value)
11
+ end
12
+ end
13
+
14
+ attr_accessor :rank
15
+ end
data/test/test_helper.rb CHANGED
@@ -2,6 +2,8 @@ require 'minitest/spec'
2
2
  require 'minitest/autorun'
3
3
  require 'turn'
4
4
 
5
+ require 'csv_record'
6
+
5
7
  module TestHelper
6
8
  BASE_PATH = File.expand_path("../fixtures", __FILE__)
7
9
 
@@ -24,4 +26,27 @@ class MiniTest::Spec
24
26
  price: 3000.00
25
27
  )
26
28
  end
29
+
30
+ let(:jedi_council) { JediOrder.build rank: 'council' }
31
+ let(:luke) do
32
+ Jedi.build(
33
+ name: 'Luke Skywalker',
34
+ age: 18,
35
+ midi_chlorians: '12k'
36
+ )
37
+ end
38
+ let(:yoda) do
39
+ Jedi.build(
40
+ name: 'Yoda the green',
41
+ age: 852,
42
+ midi_chlorians: '8k'
43
+ )
44
+ end
45
+ let(:qui_gon_jinn) do
46
+ Jedi.build(
47
+ name: 'Qui-Gon Jinn',
48
+ age: 37,
49
+ midi_chlorians: '3k'
50
+ )
51
+ end
27
52
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: csv_record
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.5.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,8 +9,24 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-11-05 00:00:00.000000000 Z
12
+ date: 2012-11-10 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activesupport
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
14
30
  - !ruby/object:Gem::Dependency
15
31
  name: rake
16
32
  requirement: !ruby/object:Gem::Requirement
@@ -74,6 +90,7 @@ files:
74
90
  - Rakefile
75
91
  - csv_record.gemspec
76
92
  - lib/csv_record.rb
93
+ - lib/csv_record/associations.rb
77
94
  - lib/csv_record/callbacks.rb
78
95
  - lib/csv_record/connector.rb
79
96
  - lib/csv_record/document.rb
@@ -82,6 +99,7 @@ files:
82
99
  - lib/csv_record/timestamps.rb
83
100
  - lib/csv_record/version.rb
84
101
  - lib/csv_record/writer.rb
102
+ - test/csv_record/associations_test.rb
85
103
  - test/csv_record/callbacks_test.rb
86
104
  - test/csv_record/connector_test.rb
87
105
  - test/csv_record/csv_record_test.rb
@@ -92,6 +110,8 @@ files:
92
110
  - test/csv_record/writer_test.rb
93
111
  - test/models/callback_test_class.rb
94
112
  - test/models/car.rb
113
+ - test/models/jedi.rb
114
+ - test/models/jedi_order.rb
95
115
  - test/test_helper.rb
96
116
  homepage: https://github.com/lukasalexandre/csv_record
97
117
  licenses: []
@@ -119,6 +139,7 @@ specification_version: 3
119
139
  summary: CSV Record connects Ruby classes to CSV documents database to establish an
120
140
  almost zero-configuration persistence layer for applications.
121
141
  test_files:
142
+ - test/csv_record/associations_test.rb
122
143
  - test/csv_record/callbacks_test.rb
123
144
  - test/csv_record/connector_test.rb
124
145
  - test/csv_record/csv_record_test.rb
@@ -129,4 +150,6 @@ test_files:
129
150
  - test/csv_record/writer_test.rb
130
151
  - test/models/callback_test_class.rb
131
152
  - test/models/car.rb
153
+ - test/models/jedi.rb
154
+ - test/models/jedi_order.rb
132
155
  - test/test_helper.rb