csv_record 1.4.0 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
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