functio 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.
- checksums.yaml +7 -0
- data/.gitignore +3 -0
- data/CHANGELOG.md +9 -0
- data/COPYING +674 -0
- data/Gemfile +16 -0
- data/Gemfile.lock +79 -0
- data/README.md +109 -0
- data/Rakefile +47 -0
- data/bin/fn +28 -0
- data/features/expression_evaluation.feature +58 -0
- data/features/function_creation.feature +74 -0
- data/features/function_deletion.feature +37 -0
- data/features/function_list.feature +35 -0
- data/features/function_use.feature +56 -0
- data/features/help_option.feature +13 -0
- data/features/step_definitions/steps.rb +36 -0
- data/features/support/env.rb +41 -0
- data/features/support/functio_world.rb +45 -0
- data/features/version_option.feature +19 -0
- data/functio.gemspec +43 -0
- data/lib/functio.rb +24 -0
- data/lib/functio/data_storage.rb +90 -0
- data/lib/functio/errors.rb +47 -0
- data/lib/functio/expression.rb +61 -0
- data/lib/functio/formatted_num.rb +39 -0
- data/lib/functio/functio_cli.rb +111 -0
- data/lib/functio/function.rb +104 -0
- data/lib/functio/function_repository.rb +73 -0
- data/lib/functio/version.rb +23 -0
- data/test/doubles/expression_double.rb +33 -0
- data/test/doubles/function_double.rb +34 -0
- data/test/doubles/storage_double.rb +36 -0
- data/test/doubles/test_expression_double.rb +30 -0
- data/test/doubles/test_function_double.rb +30 -0
- data/test/doubles/test_storage_double.rb +30 -0
- data/test/expression_interface_test.rb +30 -0
- data/test/interface_test_helper.rb +25 -0
- data/test/license_test_helper.rb +49 -0
- data/test/storable_interface_test.rb +30 -0
- data/test/storage_interface_test.rb +30 -0
- data/test/test_data_storage.rb +127 -0
- data/test/test_expression.rb +89 -0
- data/test/test_formatted_num.rb +56 -0
- data/test/test_function.rb +142 -0
- data/test/test_function_repository.rb +97 -0
- data/test/test_helper.rb +22 -0
- data/test/test_licenses_compatibility.rb +29 -0
- metadata +140 -0
@@ -0,0 +1,34 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (C) 2016 Cassiano Rocha Kuplich
|
3
|
+
#
|
4
|
+
# This file is part of Functio.
|
5
|
+
#
|
6
|
+
# Functio is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# Functio is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with Functio. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#++
|
19
|
+
|
20
|
+
class FunctionDouble # :nodoc:
|
21
|
+
attr_reader :attributes
|
22
|
+
|
23
|
+
def self.build(attributes)
|
24
|
+
new(attributes)
|
25
|
+
end
|
26
|
+
|
27
|
+
def initialize(attributes)
|
28
|
+
@attributes = attributes
|
29
|
+
end
|
30
|
+
|
31
|
+
def ==(other)
|
32
|
+
attributes == other.attributes
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (C) 2016 Cassiano Rocha Kuplich
|
3
|
+
#
|
4
|
+
# This file is part of Functio.
|
5
|
+
#
|
6
|
+
# Functio is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# Functio is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with Functio. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#++
|
19
|
+
|
20
|
+
class StorageDouble # :nodoc:
|
21
|
+
attr_reader :all
|
22
|
+
|
23
|
+
def initialize(results = {})
|
24
|
+
@find = results[:find]
|
25
|
+
@all = results[:all]
|
26
|
+
@delete = results[:delete]
|
27
|
+
end
|
28
|
+
|
29
|
+
def find(_fields)
|
30
|
+
@find
|
31
|
+
end
|
32
|
+
|
33
|
+
def delete(_fields)
|
34
|
+
@delete
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (C) 2016 Cassiano Rocha Kuplich
|
3
|
+
#
|
4
|
+
# This file is part of Functio.
|
5
|
+
#
|
6
|
+
# Functio is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# Functio is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with Functio. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#++
|
19
|
+
|
20
|
+
require 'minitest/autorun'
|
21
|
+
require 'doubles/expression_double'
|
22
|
+
require 'expression_interface_test'
|
23
|
+
|
24
|
+
class TestExpressionDouble < Minitest::Test # :nodoc:
|
25
|
+
include ExpressionInterfaceTest
|
26
|
+
|
27
|
+
def setup
|
28
|
+
@object = ExpressionDouble.new
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (C) 2016 Cassiano Rocha Kuplich
|
3
|
+
#
|
4
|
+
# This file is part of Functio.
|
5
|
+
#
|
6
|
+
# Functio is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# Functio is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with Functio. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#++
|
19
|
+
|
20
|
+
require 'minitest/autorun'
|
21
|
+
require 'doubles/function_double'
|
22
|
+
require 'storable_interface_test'
|
23
|
+
|
24
|
+
class TestFunctionDouble < Minitest::Test # :nodoc:
|
25
|
+
include StorableInterfaceTest
|
26
|
+
|
27
|
+
def setup
|
28
|
+
@object = FunctionDouble.new({})
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (C) 2016 Cassiano Rocha Kuplich
|
3
|
+
#
|
4
|
+
# This file is part of Functio.
|
5
|
+
#
|
6
|
+
# Functio is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# Functio is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with Functio. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#++
|
19
|
+
|
20
|
+
require 'minitest/autorun'
|
21
|
+
require 'doubles/storage_double'
|
22
|
+
require 'storage_interface_test'
|
23
|
+
|
24
|
+
class TestStorageDouble < Minitest::Test # :nodoc:
|
25
|
+
include StorageInterfaceTest
|
26
|
+
|
27
|
+
def setup
|
28
|
+
@object = StorageDouble.new
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (C) 2016 Cassiano Rocha Kuplich
|
3
|
+
#
|
4
|
+
# This file is part of Functio.
|
5
|
+
#
|
6
|
+
# Functio is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# Functio is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with Functio. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#++
|
19
|
+
|
20
|
+
require 'interface_test_helper'
|
21
|
+
|
22
|
+
module ExpressionInterfaceTest # :nodoc:
|
23
|
+
include InterfaceTestHelper
|
24
|
+
|
25
|
+
def test_implements_the_expression_interface
|
26
|
+
assert_implements(@object, :expression, 0)
|
27
|
+
assert_implements(@object, :variables, 0)
|
28
|
+
assert_implements(@object, :evaluate, -1)
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (C) 2016 Cassiano Rocha Kuplich
|
3
|
+
#
|
4
|
+
# This file is part of Functio.
|
5
|
+
#
|
6
|
+
# Functio is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# Functio is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with Functio. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#++
|
19
|
+
|
20
|
+
module InterfaceTestHelper # :nodoc:
|
21
|
+
def assert_implements(object, method, arity)
|
22
|
+
assert_respond_to(object, method)
|
23
|
+
assert_equal(arity, object.method(method).arity)
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (C) 2016 Cassiano Rocha Kuplich
|
3
|
+
#
|
4
|
+
# This file is part of Functio.
|
5
|
+
#
|
6
|
+
# Functio is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# Functio is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with Functio. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#++
|
19
|
+
|
20
|
+
require 'minitest/autorun'
|
21
|
+
require 'papers'
|
22
|
+
|
23
|
+
# Configures Papers for license compatibility validation.
|
24
|
+
Papers.configure do |config|
|
25
|
+
# A whitelist of accepted licenses.
|
26
|
+
config.license_whitelist = ['MIT', 'BSD', 'BSD-2-Clause', 'Ruby', 'GPL-3.0+']
|
27
|
+
|
28
|
+
# The location of your dependency manifest. Defaults to
|
29
|
+
# config/papers_manifest.yml
|
30
|
+
config.manifest_file = File.join('config', 'papers_manifest.yml')
|
31
|
+
|
32
|
+
# Configures Papers to validate licenses for bundled gems. Defaults to true.
|
33
|
+
config.validate_gems = true
|
34
|
+
|
35
|
+
# Configures Papers to validate licenses for included JavaScript and
|
36
|
+
# CoffeScript files. Defaults to true.
|
37
|
+
config.validate_javascript = false
|
38
|
+
|
39
|
+
# Configures Papers to validate licenses for bower components. Defaults to
|
40
|
+
# false.
|
41
|
+
config.validate_bower_components = false
|
42
|
+
|
43
|
+
# Configures Papers to validate licenses for NPM dependencies. Defaults to
|
44
|
+
# false.
|
45
|
+
config.validate_npm_packages = false
|
46
|
+
|
47
|
+
# Configured Papers to ignore NPM dev dependencies. Defaults to false.
|
48
|
+
config.ignore_npm_dev_dependencies = false
|
49
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (C) 2016 Cassiano Rocha Kuplich
|
3
|
+
#
|
4
|
+
# This file is part of Functio.
|
5
|
+
#
|
6
|
+
# Functio is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# Functio is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with Functio. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#++
|
19
|
+
|
20
|
+
require 'interface_test_helper'
|
21
|
+
|
22
|
+
module StorableInterfaceTest # :nodoc:
|
23
|
+
include InterfaceTestHelper
|
24
|
+
|
25
|
+
def test_implements_the_storable_interface
|
26
|
+
assert_implements(@object.class, :build, 1)
|
27
|
+
assert_implements(@object, :attributes, 0)
|
28
|
+
assert_implements(@object, :==, 1)
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (C) 2016 Cassiano Rocha Kuplich
|
3
|
+
#
|
4
|
+
# This file is part of Functio.
|
5
|
+
#
|
6
|
+
# Functio is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# Functio is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with Functio. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#++
|
19
|
+
|
20
|
+
require 'interface_test_helper'
|
21
|
+
|
22
|
+
module StorageInterfaceTest # :nodoc:
|
23
|
+
include InterfaceTestHelper
|
24
|
+
|
25
|
+
def test_implements_storage_interface
|
26
|
+
assert_implements(@object, :all, 0)
|
27
|
+
assert_implements(@object, :find, 1)
|
28
|
+
assert_implements(@object, :delete, 1)
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (C) 2016 Cassiano Rocha Kuplich
|
3
|
+
#
|
4
|
+
# This file is part of Functio.
|
5
|
+
#
|
6
|
+
# Functio is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# Functio is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with Functio. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#++
|
19
|
+
|
20
|
+
require 'test_helper'
|
21
|
+
require 'functio/data_storage'
|
22
|
+
require 'fileutils'
|
23
|
+
require 'storage_interface_test'
|
24
|
+
|
25
|
+
class TestDataStorage < Minitest::Test # :nodoc:
|
26
|
+
include StorageInterfaceTest
|
27
|
+
|
28
|
+
def setup
|
29
|
+
@real_home = ENV['HOME']
|
30
|
+
|
31
|
+
ENV['HOME'] = File.join('/tmp', 'fake_home')
|
32
|
+
@default_data_file = File.join(ENV['HOME'], '.functio', 'functions.csv')
|
33
|
+
|
34
|
+
FileUtils.remove_dir(ENV['HOME'], true)
|
35
|
+
FileUtils.mkdir_p(ENV['HOME'])
|
36
|
+
|
37
|
+
@object = @storage = DataStorage.new
|
38
|
+
end
|
39
|
+
|
40
|
+
def teardown
|
41
|
+
ENV['HOME'] = @real_home
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_store
|
45
|
+
@storage.store(name: 'first', definition: 'record')
|
46
|
+
first = "name,definition\nfirst,record\n"
|
47
|
+
|
48
|
+
assert File.exist?(@default_data_file)
|
49
|
+
assert_equal(first, File.read(@default_data_file))
|
50
|
+
|
51
|
+
@storage.store(name: 'second', definition: 'record')
|
52
|
+
assert_equal(first + "second,record\n", File.read(@default_data_file))
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_find_stored_record
|
56
|
+
set_fixture_csv
|
57
|
+
expected = { name: 'first', definition: 'one' }
|
58
|
+
assert_equal(expected, @storage.find(name: 'first'))
|
59
|
+
assert_equal(expected, @storage.find(definition: 'one'))
|
60
|
+
assert_equal(expected, @storage.find(name: 'first', definition: 'one'))
|
61
|
+
|
62
|
+
expected = { name: 'second', definition: 'two' }
|
63
|
+
assert_equal(expected, @storage.find(name: 'second'))
|
64
|
+
assert_equal(expected, @storage.find(definition: 'two'))
|
65
|
+
assert_equal(expected, @storage.find(name: 'second', definition: 'two'))
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_find_inexistent_record
|
69
|
+
assert_nil(@storage.find(name: 'first'))
|
70
|
+
assert_nil(@storage.find(definition: 'two'))
|
71
|
+
|
72
|
+
set_fixture_csv
|
73
|
+
assert_nil(@storage.find(name: 'something else'))
|
74
|
+
assert_nil(@storage.find(definition: 'something else'))
|
75
|
+
assert_nil(@storage.find(name: 'first', definition: 'two'))
|
76
|
+
assert_nil(@storage.find(other: 'test'))
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_get_all_records
|
80
|
+
assert_equal([], @storage.all)
|
81
|
+
|
82
|
+
set_fixture_csv
|
83
|
+
all_records = @storage.all
|
84
|
+
assert_equal(2, all_records.size)
|
85
|
+
assert_includes(all_records, name: 'first', definition: 'one')
|
86
|
+
assert_includes(all_records, name: 'second', definition: 'two')
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_delete_stored_record
|
90
|
+
set_fixture_csv
|
91
|
+
|
92
|
+
expected = "name,definition\nsecond,two\n"
|
93
|
+
assert @storage.delete(name: 'first')
|
94
|
+
assert_equal(expected, File.read(@default_data_file))
|
95
|
+
|
96
|
+
assert @storage.delete(definition: 'two', name: 'second')
|
97
|
+
refute File.exist?(@default_data_file)
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_delete_from_empty_data
|
101
|
+
refute @storage.delete(name: 'something', definition: 'else')
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_delete_inexistent_record
|
105
|
+
set_fixture_csv
|
106
|
+
|
107
|
+
expected = "name,definition\nfirst,one\nsecond,two\n"
|
108
|
+
fields_cases = [{ name: 'something else' },
|
109
|
+
{ definition: 'something else' },
|
110
|
+
{ other: 'something else' }]
|
111
|
+
fields_cases.each do |fields|
|
112
|
+
refute @storage.delete(fields)
|
113
|
+
assert_equal(expected, File.read(@default_data_file))
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
private
|
118
|
+
|
119
|
+
def set_fixture_csv
|
120
|
+
FileUtils.mkdir_p(File.dirname(@default_data_file))
|
121
|
+
File.open(@default_data_file, 'a') do |f|
|
122
|
+
f.puts 'name,definition'
|
123
|
+
f.puts 'first,one'
|
124
|
+
f.puts 'second,two'
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|