active_csv 0.1.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.
@@ -0,0 +1,2 @@
1
+ *.gem
2
+ *todolist.txt
data/README ADDED
File without changes
@@ -0,0 +1,13 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'active_csv'
3
+ s.version = '0.1.0'
4
+ s.add_dependency('activemodel', '>= 3.0.0')
5
+ s.summary = 'Inteds to allow you to work with csv data files with an API ActiveRecord-like'
6
+ s.description = 'Inteds to allow you to work with csv data files with an API ActiveRecord-like'
7
+ s.files = `git ls-files`.split("\n")
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Marco Antonio Fogaça Nogueira"]
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.3.7")
11
+ s.email = ["marcofognog@gmail.com"]
12
+ s.require_paths = ["lib"]
13
+ end
data/init.rb ADDED
@@ -0,0 +1,2 @@
1
+ $: << File.expand_path("lib")
2
+ require 'active_csv'
@@ -0,0 +1,125 @@
1
+ require 'active_csv/errors'
2
+ require 'active_csv/class_methods'
3
+ require 'active_csv/attr_file'
4
+ require 'active_csv/db_file'
5
+ require 'rubygems'
6
+ require 'active_model'
7
+
8
+ class ActiveCSV
9
+ require 'csv'
10
+ require 'yaml'
11
+
12
+ extend ClassMethods
13
+ extend ActiveModel::Naming
14
+ include ActiveModel::Validations
15
+ include ActiveModel::Conversion
16
+
17
+ attr_accessor :id, :attr_file, :db_file
18
+
19
+ def initialize(*attributes)
20
+ if attributes[0].is_a? Hash || attributes[0].is_a?(ActiveSupport::HashWithIndifferentAccess)
21
+ hash_to_obj(attributes[0])
22
+ end
23
+ self.attr_file = AttrFile.new("config/csv_attributes.yml")
24
+ self.db_file = DbFile.new("db/"+model_name+".csv")
25
+ end
26
+
27
+ def model_name
28
+ self.class.to_s.downcase
29
+ end
30
+
31
+ def field_values
32
+ attributes = Array.new
33
+ attr_file.fields(model_name).each do |field|
34
+ attributes << eval(field)
35
+ end
36
+ attributes #String
37
+ end
38
+
39
+ def last_id
40
+ attr_array = self.db_file.csv_content
41
+ unless attr_array.count == 0
42
+ attr_array.last[0]
43
+ else
44
+ 0
45
+ end
46
+ end
47
+
48
+ def next_id
49
+ last_id.to_i+1
50
+ end
51
+
52
+ def persist_existing
53
+ destroy
54
+ persist_new_obj
55
+ end
56
+
57
+ def persist_new_obj
58
+ a = db_file.csv_content
59
+ new_row = field_values
60
+ CSV.open(db_file.name,"wb") do |csv|
61
+ a.each do |line|
62
+ csv << line
63
+ end
64
+ csv << new_row
65
+ end
66
+ end
67
+
68
+ # Also used by form_for in the views on Rails
69
+ def persisted?
70
+ unless self.id.nil?
71
+ true
72
+ else
73
+ false
74
+ end
75
+ end
76
+
77
+ def save
78
+ if valid?
79
+ unless persisted?
80
+ self.id = next_id
81
+ end
82
+ persist_existing
83
+ return true
84
+ else
85
+ return false
86
+ end
87
+ end
88
+
89
+ def destroy
90
+ csv_rows = db_file.csv_content
91
+ target_index = ''
92
+ unless self.id.nil?
93
+ ids = [self.id]
94
+ target_index = ActiveCSV.find_with_ids(ids,csv_rows).first
95
+ unless target_index.nil?
96
+ csv_rows.delete_at(target_index)
97
+ CSV.open(db_file.name,"wb") do |csv|
98
+ csv_rows.each do |line|
99
+ csv << line
100
+ end
101
+ end
102
+ else
103
+ return false
104
+ end
105
+ end
106
+ self
107
+ end
108
+
109
+ def hash_to_obj(hash)
110
+ hash.each do |key, value|
111
+ key = key.to_s
112
+ send("#{key}=", value)
113
+ end
114
+ end
115
+
116
+ def update_attributes(hash_attr)
117
+ hash_to_obj(hash_attr)
118
+ if valid?
119
+ persist_existing
120
+ true
121
+ else
122
+ false
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,12 @@
1
+ class AttrFile
2
+ attr_accessor :name
3
+
4
+ def initialize(_name)
5
+ @name = _name
6
+ end
7
+ def fields(model_name)
8
+ # The sequency of the attributes is always the same as in the yaml file.
9
+ model_fields = YAML.load_file(@name)
10
+ model_fields[model_name].split(', ') #Array
11
+ end
12
+ end
@@ -0,0 +1,103 @@
1
+ module ClassMethods
2
+ def all
3
+ objects = Array.new
4
+ db_file = DbFile.new("db/"+model_name_+".csv")
5
+ attr_array = db_file.csv_content
6
+ objects = ar_to_obj(attr_array)
7
+ objects
8
+ end
9
+
10
+ def ar_to_obj(attr_array) # turns array of arrays into array of objects
11
+ objects = Array.new
12
+ attr_array.each do |row|
13
+ new_object = eval(self.name).new
14
+ fields_ar = new_object.attr_file.fields(model_name_)
15
+ fields_ar.each_index do |index|
16
+ new_object.send("#{fields_ar[index]}=",row[index])
17
+ end
18
+ objects << new_object
19
+ end
20
+ objects
21
+ end
22
+
23
+ #------- relacionadas ao find-----------
24
+ def check_attr?(attribute)
25
+ attr_file = AttrFile.new("config/csv_attributes.yml")
26
+ attr_file.fields(model_name_).include? attribute
27
+ end
28
+
29
+ def attr_column(attribute)
30
+ object = eval(self.name).new
31
+ object.attr_file.fields(model_name_).index attribute
32
+ end
33
+
34
+ def find_rows_by_indexes(indexes,content)
35
+ found_rows = Array.new
36
+ case indexes.size
37
+ when 0
38
+ raise RecordNotFound, "Couldn't find the especified ID"
39
+ else
40
+ indexes.each do |found|
41
+ found_rows << content[found]
42
+ end
43
+ end
44
+ found_rows
45
+ end
46
+
47
+ def find_with_ids(ids,content)
48
+ found_ids = Array.new
49
+ content.each_with_index do |row, index|
50
+ ids.each do |id|
51
+ if row[0] == id.to_s
52
+ found_ids << index
53
+ end
54
+ end
55
+ end
56
+ found_ids
57
+ end
58
+
59
+ def find_with_attr(attribute,value,content)
60
+ found_cols = Array.new
61
+ col = attr_column attribute.to_s
62
+ content.each_with_index do |row, index|
63
+ if row[col] == value
64
+ found_cols << index
65
+ end
66
+ end
67
+ found_cols #indexes
68
+ end
69
+
70
+ def find(*args)
71
+ file = DbFile.new("db/"+model_name_+".csv")
72
+ content = file.csv_content
73
+ if args[0].respond_to? "to_i"
74
+ ids = Array.new
75
+ args.each do |el|
76
+ ids << el.to_i
77
+ end
78
+ found_ids_indexes = find_with_ids(ids,content)
79
+ found_rows = find_rows_by_indexes(found_ids_indexes,content)
80
+ else
81
+ args[0].keys.each do |key|
82
+ if check_attr? key.to_s
83
+ found_rows_indexes = find_with_attr(key,args[0][key],content)
84
+ found_rows = find_rows_by_indexes(found_rows_indexes,content)
85
+ else
86
+ # raise error
87
+ end
88
+ end
89
+ end
90
+ found = ar_to_obj(found_rows)
91
+ if args.length == 1 && args[0].respond_to?("to_i")
92
+ return found.first
93
+ else
94
+ return found
95
+ end
96
+ end
97
+
98
+ #CAREFULL HERE
99
+ #use the method with the same name in ActiveModel::Naming
100
+ def model_name_
101
+ self.name.to_s.downcase
102
+ end
103
+ end
@@ -0,0 +1,29 @@
1
+ class DbFile
2
+ attr_accessor :name
3
+
4
+ def initialize(_name)
5
+ @name = _name
6
+ end
7
+ def csv_content
8
+ csv_rows = Array.new
9
+ if !file_exists?
10
+ create_db_file
11
+ end
12
+ CSV.read(name).each do |row|
13
+ csv_rows << row
14
+ end
15
+ csv_rows
16
+ end
17
+
18
+ def file_exists?
19
+ File.exists?(name)
20
+ end
21
+
22
+ def create_db_file
23
+ CSV.open(name,'w')
24
+ end
25
+
26
+ def field_values
27
+ ActiveCSV.field_values
28
+ end
29
+ end
@@ -0,0 +1,2 @@
1
+ class RecordNotFound < StandardError
2
+ end
@@ -0,0 +1,11 @@
1
+ require 'rake/testtask'
2
+
3
+ task :default => [:test_unit]
4
+
5
+ desc "Run basic tests"
6
+ Rake::TestTask.new("test_unit") do |t|
7
+ t.libs << ["../lib"]
8
+ t.test_files = FileList['test*.rb']
9
+ t.verbose = true
10
+ t.warning = true
11
+ end
@@ -0,0 +1,6 @@
1
+ require 'active_csv'
2
+
3
+ class Car < ActiveCSV
4
+ attr_accessor :color, :year, :brand
5
+ validates_presence_of :brand
6
+ end
@@ -0,0 +1,12 @@
1
+ expense:
2
+ id,
3
+ value,
4
+ description,
5
+ date,
6
+ mean
7
+
8
+ car:
9
+ id,
10
+ year,
11
+ color,
12
+ brand
@@ -0,0 +1,19 @@
1
+ require 'csv'
2
+
3
+ module TestHelpers
4
+ def create_sample_file
5
+ content = [["1","1997", "red","Fiat"],
6
+ ["2","1992", "red","Fiat"],
7
+ ["3","1964","yellow","Fusca"],
8
+ ["4","2012", "black","Citroën"]]
9
+ CSV.open("db/car.csv","wb") do |csv|
10
+ content.each do |line|
11
+ csv << line
12
+ end
13
+ end
14
+ end
15
+
16
+ def delete_sample
17
+ File.delete("db/car.csv")
18
+ end
19
+ end
@@ -0,0 +1,26 @@
1
+ require 'test/unit'
2
+ require 'test_helpers'
3
+ require 'car'
4
+
5
+ class AllTests < Test::Unit::TestCase
6
+ include TestHelpers
7
+
8
+ def test_all
9
+ create_sample_file
10
+ cars = Car.all
11
+ assert_equal(4,cars.length)
12
+ delete_sample
13
+ end
14
+
15
+ def test_kind_of_objects_from_all
16
+ create_sample_file
17
+ cars = Car.all
18
+ assert_instance_of Car, cars.first
19
+ delete_sample
20
+ end
21
+
22
+ def test_all_empty
23
+ cars = Car.all
24
+ assert_equal(0,cars.length)
25
+ end
26
+ end
@@ -0,0 +1,53 @@
1
+ require 'test/unit'
2
+ require 'test_helpers'
3
+ require 'car'
4
+
5
+ class DestroyTests < Test::Unit::TestCase
6
+ include TestHelpers
7
+
8
+ def test_destroy_when_exists
9
+ create_sample_file
10
+ car = Car.find(2)
11
+ car.destroy
12
+ assert_raise RecordNotFound do
13
+ Car.find(2)
14
+ end
15
+ delete_sample
16
+ end
17
+
18
+ def test_destroy_sequencially
19
+ create_sample_file
20
+ car = Car.find(2)
21
+ car.destroy
22
+ car2 = Car.find(3)
23
+ car2.destroy
24
+ assert_raise RecordNotFound do
25
+ Car.find(2)
26
+ end
27
+ assert_raise RecordNotFound do
28
+ Car.find(3)
29
+ end
30
+ assert_equal "red",Car.find(1).color
31
+ assert_equal "2012",Car.find(4).year
32
+ delete_sample
33
+ end
34
+
35
+ def test_destroy_obj_without_id
36
+ create_sample_file
37
+ car = Car.new
38
+ assert_kind_of Car, car.destroy
39
+ assert_equal 4, Car.all.length
40
+ assert_equal "2", Car.find(2).id
41
+ delete_sample
42
+ end
43
+
44
+ def test_destroy_file_without_id
45
+ create_sample_file
46
+ car = Car.new
47
+ car.id = 5
48
+ assert !car.destroy
49
+ assert_equal 4, Car.all.length
50
+ assert_equal "2", Car.find(2).id
51
+ delete_sample
52
+ end
53
+ end
@@ -0,0 +1,66 @@
1
+ require 'test/unit'
2
+ require 'test_helpers'
3
+ require 'car'
4
+ require 'rubygems'
5
+ require 'active_support/hash_with_indifferent_access'
6
+
7
+ class FindTests < Test::Unit::TestCase
8
+ include TestHelpers
9
+
10
+ def test_find_by_attr
11
+ create_sample_file
12
+ cars = Car.find(:color=>"red")
13
+ assert_equal "red", cars.first.color
14
+ delete_sample
15
+ end
16
+
17
+ def test_find_by_attr_missing
18
+ create_sample_file
19
+ assert_raise(RecordNotFound) { cars = Car.find(:color=>"darkblue") }
20
+ delete_sample
21
+ end
22
+
23
+ def test_find_by_attr_quatity
24
+ create_sample_file
25
+ cars = Car.find(:color=>"red")
26
+ assert_equal 2, cars.length
27
+ delete_sample
28
+ end
29
+
30
+ def test_find_by_id_2
31
+ create_sample_file
32
+ car = Car.find(2)
33
+ assert_equal "2", car.id
34
+ delete_sample
35
+ end
36
+
37
+ def test_find_by_id_3
38
+ create_sample_file
39
+ car = Car.find(3)
40
+ assert_equal "3", car.id
41
+ delete_sample
42
+ end
43
+
44
+ def test_find_by_id_missing
45
+ create_sample_file
46
+ assert_raise(RecordNotFound) { cars = Car.find(5) }
47
+ delete_sample
48
+ end
49
+
50
+ def test_find_by_ids
51
+ create_sample_file
52
+ cars = Car.find(3,4)
53
+ assert_equal "4", cars[1].id
54
+ assert_equal "3", cars[0].id
55
+ delete_sample
56
+ end
57
+
58
+ def test_find_with_active_support_hash
59
+ create_sample_file
60
+ params = ActiveSupport::HashWithIndifferentAccess.new
61
+ params[:id] = "2"
62
+ car = Car.find(params[:id])
63
+ assert_equal "2", car.id
64
+ delete_sample
65
+ end
66
+ end
@@ -0,0 +1,43 @@
1
+ require 'test/unit'
2
+ require 'test_helpers'
3
+ require 'car'
4
+ require 'rubygems'
5
+ require 'active_support/hash_with_indifferent_access'
6
+
7
+ class InitializeTests < Test::Unit::TestCase
8
+ include TestHelpers
9
+
10
+ def test_initialize_with_attr_hash
11
+ car = Car.new(:color=>"blues")
12
+ assert_equal "blues",car.color
13
+ end
14
+
15
+ def test_initialize_with_attr_hash
16
+ car = Car.new(:color=>"green")
17
+ assert_equal "green",car.color
18
+ end
19
+
20
+ def test_initialize_with_attr_symbol
21
+ car = Car.new(:color=>"darkblue", :year=>"1999",:brand=>"Renault")
22
+ assert_equal "darkblue",car.color
23
+ assert_equal "Renault",car.brand
24
+ assert_equal "1999",car.year
25
+ end
26
+
27
+ def test_initialize_with_attr_strings
28
+ car = Car.new("color"=>"darkblue", "year"=>"1999","brand"=>"Renault")
29
+ assert car.save
30
+ assert_equal "darkblue",car.color
31
+ assert_equal "Renault",car.brand
32
+ assert_equal "1999",car.year
33
+ end
34
+
35
+ def test_initialize_with_active_suport_hash
36
+ params = ActiveSupport::HashWithIndifferentAccess.new
37
+ params[:car] = {:color=>"blue", :year=>"1999", :brand=>"Gol"}
38
+ car = Car.new(params[:car])
39
+ assert_equal "Gol", car.brand
40
+ assert_equal "blue", car.color
41
+ assert_equal "1999", car.year
42
+ end
43
+ end
@@ -0,0 +1,15 @@
1
+ require 'test/unit'
2
+ require 'test_helpers'
3
+ require 'car'
4
+
5
+ class SaveTests < Test::Unit::TestCase
6
+ include TestHelpers
7
+
8
+ def test_persisted_is_still_false
9
+ create_sample_file
10
+ car = Car.new({:year=>"1999"})
11
+ assert !car.save #should return false and don't save, once Car validates_presence_of brand
12
+ assert !car.persisted?
13
+ delete_sample
14
+ end
15
+ end
@@ -0,0 +1,54 @@
1
+ require 'test/unit'
2
+ require 'test_helpers'
3
+ require 'car'
4
+
5
+ class SaveTests < Test::Unit::TestCase
6
+ include TestHelpers
7
+
8
+ def test_save_file_exists
9
+ car = Car.new
10
+ car.year = "1998"
11
+ car.color = "red"
12
+ car.brand = "wolksvagen"
13
+ car.save
14
+ assert File.exists? car.db_file.name
15
+ File.delete(car.db_file.name)
16
+ end
17
+
18
+ def test_save_quantity
19
+ create_sample_file
20
+ before = Car.all.length
21
+ car = Car.new
22
+ car.year = "1998"
23
+ car.color = "red"
24
+ car.brand = "wolksvagen"
25
+ assert car.save
26
+ assert_equal before+1, Car.all.length
27
+ delete_sample
28
+ end
29
+
30
+ def test_save_again
31
+ create_sample_file
32
+ before = Car.all.length
33
+ car = Car.new
34
+ car.year = "1998"
35
+ car.color = "red"
36
+ car.brand = "wolksvagen"
37
+ assert car.save
38
+ assert car.save
39
+ assert_equal before+1, Car.all.length
40
+ delete_sample
41
+ end
42
+
43
+ def test_dont_save_if_not_valid
44
+ create_sample_file
45
+ before = Car.all.length
46
+ car = Car.new
47
+ car.year = "1998"
48
+ car.color = "red"
49
+ assert !car.save
50
+ assert_equal before, Car.all.length
51
+ delete_sample
52
+ end
53
+
54
+ end
@@ -0,0 +1,66 @@
1
+ require 'test/unit'
2
+ require 'test_helpers'
3
+ require 'car'
4
+ require 'rubygems'
5
+ require 'active_support/hash_with_indifferent_access'
6
+
7
+ class UpdateAttributesTests < Test::Unit::TestCase
8
+ include TestHelpers
9
+
10
+ def test_update_attr_three_attr
11
+ create_sample_file
12
+ car = Car.find(1)
13
+ car.update_attributes({:year=>"2000",:color=>"yeallow", :brand=>"Fusquinha sem vergonha"})
14
+
15
+ assert_equal "yeallow",car.color
16
+ assert_equal "yeallow", Car.find(1).color
17
+ assert_equal "2000", Car.find(1).year
18
+ assert_equal "Fusquinha sem vergonha", Car.find(1).brand
19
+ delete_sample
20
+ end
21
+
22
+ def test_update_attr_two_attr
23
+ create_sample_file
24
+ car = Car.find(2)
25
+ car.update_attributes({:color=>"pink", :brand=>"Ferrari"})
26
+
27
+ assert_equal "pink",car.color
28
+ assert_equal "pink",Car.find(2).color
29
+ assert_equal "Ferrari",Car.find(2).brand
30
+ delete_sample
31
+ end
32
+
33
+ def test_update_attr_keeping_other_attr
34
+ create_sample_file
35
+ car = Car.find(2)
36
+ car.update_attributes({:brand=>"Gol bolinha"})
37
+
38
+ assert_equal "red",car.color
39
+ assert_equal "Gol bolinha",Car.find(2).brand
40
+ delete_sample
41
+ end
42
+
43
+ def test_update_attributes_with_as_hash
44
+ create_sample_file
45
+ params = ActiveSupport::HashWithIndifferentAccess.new
46
+ params[:car] = {:color => "blue", :year => "2000", :brand => "Gol"}
47
+ car = Car.find(2)
48
+ car.update_attributes(params[:car])
49
+ assert_equal "blue", Car.find(2).color
50
+ assert_equal "2000", Car.find(2).year
51
+ assert_equal "Gol", Car.find(2).brand
52
+ delete_sample
53
+ end
54
+
55
+ def test_dont_update_attributes_if_not_valid
56
+ create_sample_file
57
+ params = ActiveSupport::HashWithIndifferentAccess.new
58
+ params[:car] = {:color => "blue", :year => "2000", :brand=>""}
59
+ car = Car.find(2)
60
+ assert !car.update_attributes(params[:car])
61
+ assert_not_equal "blue", Car.find(2).color
62
+ assert_not_equal "2000", Car.find(2).year
63
+
64
+ delete_sample
65
+ end
66
+ end
metadata ADDED
@@ -0,0 +1,104 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: active_csv
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - "Marco Antonio Foga\xC3\xA7a Nogueira"
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-03-09 00:00:00 -03:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: activemodel
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 7
30
+ segments:
31
+ - 3
32
+ - 0
33
+ - 0
34
+ version: 3.0.0
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ description: Inteds to allow you to work with csv data files with an API ActiveRecord-like
38
+ email:
39
+ - marcofognog@gmail.com
40
+ executables: []
41
+
42
+ extensions: []
43
+
44
+ extra_rdoc_files: []
45
+
46
+ files:
47
+ - .gitignore
48
+ - README
49
+ - active_csv.gemspec
50
+ - init.rb
51
+ - lib/active_csv.rb
52
+ - lib/active_csv/attr_file.rb
53
+ - lib/active_csv/class_methods.rb
54
+ - lib/active_csv/db_file.rb
55
+ - lib/active_csv/errors.rb
56
+ - tests/Rakefile
57
+ - tests/car.rb
58
+ - tests/config/csv_attributes.yml
59
+ - tests/test_helpers.rb
60
+ - tests/tests_all.rb
61
+ - tests/tests_destroy.rb
62
+ - tests/tests_find.rb
63
+ - tests/tests_initialize.rb
64
+ - tests/tests_persisted.rb
65
+ - tests/tests_save.rb
66
+ - tests/tests_update_attributes.rb
67
+ has_rdoc: true
68
+ homepage:
69
+ licenses: []
70
+
71
+ post_install_message:
72
+ rdoc_options: []
73
+
74
+ require_paths:
75
+ - lib
76
+ required_ruby_version: !ruby/object:Gem::Requirement
77
+ none: false
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ hash: 3
82
+ segments:
83
+ - 0
84
+ version: "0"
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ hash: 21
91
+ segments:
92
+ - 1
93
+ - 3
94
+ - 7
95
+ version: 1.3.7
96
+ requirements: []
97
+
98
+ rubyforge_project:
99
+ rubygems_version: 1.6.1
100
+ signing_key:
101
+ specification_version: 3
102
+ summary: Inteds to allow you to work with csv data files with an API ActiveRecord-like
103
+ test_files: []
104
+