rbbt-util 5.6.14 → 5.6.15
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 +4 -4
- data/bin/rbbt +30 -22
- data/lib/rbbt/persist.rb +2 -2
- data/lib/rbbt/tsv.rb +4 -2
- data/lib/rbbt/tsv/change_id.rb +8 -3
- data/lib/rbbt/util/log.rb +4 -0
- data/lib/rbbt/util/misc.rb +3 -3
- data/lib/rbbt/util/simpleopt.rb +1 -0
- data/lib/rbbt/util/simpleopt/get.rb +6 -0
- data/lib/rbbt/util/simpleopt/parse.rb +1 -0
- data/lib/rbbt/util/simpleopt/setup.rb +30 -0
- data/share/rbbt_commands/tsv/change_id +21 -22
- data/share/rbbt_commands/tsv/values +18 -1
- data/share/rbbt_commands/workflow/task +7 -3
- data/test/rbbt/util/simpleopt/test_setup.rb +76 -0
- data/test/rbbt/util/test_log.rb +4 -0
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dc353002e2a5fdbaaf0bbfc97b8fa79f5bdc4ffe
|
4
|
+
data.tar.gz: b912bbecb036910d98c35e3a5822f3fe2b9a9e4c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 409f4d6abe74bac82970a076ac9165843813f06524e61d0b6ab60c1c29d643f1f9b374b54d21c9e78b1472048f8c2431be0cc6693559e852c42e4258cff66372
|
7
|
+
data.tar.gz: 9064bdc5ff2a21b3b5844f8a10b963b0856383711dbda184d52238bc5ae591974d4c42a475fdecf954edd63a58802adcd9f798c22e40a0529f08054c9e197cc4
|
data/bin/rbbt
CHANGED
@@ -3,7 +3,18 @@
|
|
3
3
|
require 'rbbt'
|
4
4
|
require 'rbbt/util/simpleopt'
|
5
5
|
|
6
|
-
options = SOPT.
|
6
|
+
options = SOPT.setup <<EOF
|
7
|
+
This command controls many aspects of the Rbbt framework, from configuration tasks to running applications.
|
8
|
+
|
9
|
+
$ rbbt <command> <subcommand> ... -a --arg1 --arg2='value' --arg3 'another-value'"
|
10
|
+
|
11
|
+
|
12
|
+
--log* #{Log.color :yellow, "Log level from 0 (debug) 6 (errors)"}
|
13
|
+
-cd--command_dir* #{Log.color :yellow, "Directory from where to load commands"}
|
14
|
+
--profile #{Log.color :yellow, "Profile execution"}
|
15
|
+
--nocolor #{Log.color :yellow, "Disable colored output"}
|
16
|
+
--locate_file #{Log.color :yellow, "Locate file been executed"}
|
17
|
+
EOF
|
7
18
|
|
8
19
|
Log.nocolor = true if options[:nocolor]
|
9
20
|
locate = options.delete :locate_file
|
@@ -18,20 +29,17 @@ else
|
|
18
29
|
$rbbt_command_dir = Rbbt.share.rbbt_commands
|
19
30
|
end
|
20
31
|
|
32
|
+
SOPT.description =<<EOF
|
33
|
+
Commands are implemented in separate files under the Rbbt path '#{$rbbt_command_dir}'.
|
34
|
+
Known locations are: #{([$rbbt_command_dir] + $rbbt_command_dir.find_all) * ", " }.
|
35
|
+
You can place your own commads at #{$rbbt_command_dir.find(:user)}.
|
36
|
+
EOF
|
37
|
+
|
21
38
|
if options[:profile]
|
22
39
|
require 'ruby-prof'
|
23
40
|
RubyProf.start
|
24
41
|
end
|
25
42
|
|
26
|
-
SOPT.synopsys = "rbbt <command> <subcommand> ... -a --arg1 --arg2='value' --arg3 'another-value'"
|
27
|
-
SOPT.summary = "Ruby bioinformatics toolkit"
|
28
|
-
SOPT.description = <<-EOF
|
29
|
-
This command controls many aspects of the Rbbt framework, from configuration tasks to running applications.
|
30
|
-
|
31
|
-
Commands are implemented in separate files under the Rbbt path '#{$rbbt_command_dir}'.
|
32
|
-
Known locations are: #{([$rbbt_command_dir] + $rbbt_command_dir.find_all) * ", " }.
|
33
|
-
You can place your own commads at #{$rbbt_command_dir.find(:user)}.
|
34
|
-
EOF
|
35
43
|
|
36
44
|
def prev_dir(prev)
|
37
45
|
rbbt_command_dir = $rbbt_command_dir
|
@@ -76,6 +84,7 @@ def rbbt_usage(prev = nil)
|
|
76
84
|
end
|
77
85
|
end
|
78
86
|
puts
|
87
|
+
true
|
79
88
|
end
|
80
89
|
|
81
90
|
def print_error(error, backtrace = nil)
|
@@ -102,34 +111,34 @@ def cmd_alias
|
|
102
111
|
end
|
103
112
|
|
104
113
|
dir = $rbbt_command_dir
|
105
|
-
|
114
|
+
$previous_commands = []
|
106
115
|
|
107
116
|
cmd_alias
|
108
117
|
|
109
118
|
begin
|
110
119
|
while ARGV.any?
|
111
|
-
command = ARGV.shift
|
120
|
+
$command = ARGV.shift
|
112
121
|
case
|
113
|
-
when File.directory?(dir[command].find)
|
114
|
-
|
115
|
-
dir = dir[command]
|
116
|
-
when dir[command].exists?
|
122
|
+
when File.directory?(dir[$command].find)
|
123
|
+
$previous_commands << $command
|
124
|
+
dir = dir[$command]
|
125
|
+
when dir[$command].exists?
|
117
126
|
if locate
|
118
|
-
puts dir[command].find
|
127
|
+
puts dir[$command].find
|
119
128
|
exit 0
|
120
129
|
else
|
121
|
-
load dir[command].find
|
130
|
+
load dir[$command].find
|
122
131
|
exit 0
|
123
132
|
end
|
124
133
|
else
|
125
|
-
error = "Command '#{command }' not understood"
|
126
|
-
rbbt_usage(
|
134
|
+
error = "Command '#{$command }' not understood"
|
135
|
+
rbbt_usage($previous_commands)
|
127
136
|
print_error(error)
|
128
137
|
exit -1
|
129
138
|
end
|
130
139
|
end
|
131
140
|
|
132
|
-
rbbt_usage(
|
141
|
+
rbbt_usage($previous_commands)
|
133
142
|
exit 0
|
134
143
|
|
135
144
|
rescue ParameterException
|
@@ -145,4 +154,3 @@ ensure
|
|
145
154
|
printer.print(STDOUT, :min_percent => 10)
|
146
155
|
end
|
147
156
|
end
|
148
|
-
|
data/lib/rbbt/persist.rb
CHANGED
@@ -260,7 +260,7 @@ module Persist
|
|
260
260
|
|
261
261
|
if is_persisted?(path, persist_options)
|
262
262
|
Log.low "Persist up-to-date: #{ path } - #{Misc.fingerprint persist_options}"
|
263
|
-
return
|
263
|
+
return path if persist_options[:no_load]
|
264
264
|
return load_file(path, type)
|
265
265
|
end
|
266
266
|
|
@@ -269,7 +269,7 @@ module Persist
|
|
269
269
|
Misc.lock lock_filename do
|
270
270
|
if is_persisted?(path, persist_options)
|
271
271
|
Log.low "Persist up-to-date (suddenly): #{ path } - #{Misc.fingerprint persist_options}"
|
272
|
-
return
|
272
|
+
return path if persist_options[:no_load]
|
273
273
|
return load_file(path, type)
|
274
274
|
end
|
275
275
|
|
data/lib/rbbt/tsv.rb
CHANGED
@@ -17,7 +17,7 @@ require 'rbbt/tsv/field_index'
|
|
17
17
|
|
18
18
|
module TSV
|
19
19
|
class << self
|
20
|
-
attr_accessor :lock_dir
|
20
|
+
attr_accessor :lock_dir, :unnamed
|
21
21
|
|
22
22
|
def lock_dir
|
23
23
|
@lock_dir ||= Rbbt.tmp.tsv_open_locks.find
|
@@ -25,7 +25,7 @@ module TSV
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def self.setup(hash, options = {})
|
28
|
-
options = Misc.add_defaults options, :default_value => []
|
28
|
+
options = Misc.add_defaults options, :default_value => [], :unnamed => TSV.unnamed
|
29
29
|
default_value = Misc.process_options options, :default_value
|
30
30
|
hash = Misc.array2hash(hash, default_value) if Array === hash
|
31
31
|
hash.extend TSV
|
@@ -49,6 +49,8 @@ module TSV
|
|
49
49
|
|
50
50
|
persist_options = Misc.pull_keys options, :persist
|
51
51
|
|
52
|
+
raise "TSV source is nil" if source.nil?
|
53
|
+
|
52
54
|
filename = get_filename source
|
53
55
|
serializer = Misc.process_options options, :serializer
|
54
56
|
unnamed = Misc.process_options options, :unnamed
|
data/lib/rbbt/tsv/change_id.rb
CHANGED
@@ -12,7 +12,11 @@ module TSV
|
|
12
12
|
orig_type = tsv.type
|
13
13
|
tsv = tsv.to_double if orig_type != :double
|
14
14
|
|
15
|
-
|
15
|
+
if Array === identifiers
|
16
|
+
tsv = tsv.attach identifiers.first, :fields => [format], :persist_input => true, :identifiers => identifiers.last
|
17
|
+
else
|
18
|
+
tsv = tsv.attach identifiers, :fields => [format], :persist_input => true
|
19
|
+
end
|
16
20
|
tsv = tsv.reorder(format, tsv.fields - [format])
|
17
21
|
|
18
22
|
tsv = tsv.to_flat if orig_type == :flat
|
@@ -23,8 +27,9 @@ module TSV
|
|
23
27
|
end
|
24
28
|
end
|
25
29
|
|
26
|
-
def change_key(
|
27
|
-
|
30
|
+
def change_key(format, options = {})
|
31
|
+
options = Misc.add_defaults options, :identifiers => self.identifiers
|
32
|
+
TSV.change_key(self, format, options)
|
28
33
|
end
|
29
34
|
|
30
35
|
def self.swap_id(tsv, field, format, options = {})
|
data/lib/rbbt/util/log.rb
CHANGED
data/lib/rbbt/util/misc.rb
CHANGED
@@ -322,9 +322,9 @@ module Misc
|
|
322
322
|
end
|
323
323
|
end
|
324
324
|
|
325
|
-
def self.remove_long_items(obj)
|
326
|
-
|
327
|
-
end
|
325
|
+
#def self.remove_long_items(obj)
|
326
|
+
# return fingerprint(obj)
|
327
|
+
#end
|
328
328
|
|
329
329
|
def self.ensembl_server(organism)
|
330
330
|
date = organism.split("/")[1]
|
data/lib/rbbt/util/simpleopt.rb
CHANGED
@@ -38,4 +38,10 @@ module SOPT
|
|
38
38
|
SOPT.parse(opt_str)
|
39
39
|
SOPT.consume(ARGV)
|
40
40
|
end
|
41
|
+
|
42
|
+
def self.require(options, *parameters)
|
43
|
+
parameters.flatten.each do |parameter|
|
44
|
+
raise ParameterException, "Parameter '#{ parameter }' not given" if options[parameter].nil?
|
45
|
+
end
|
46
|
+
end
|
41
47
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'rbbt/util/simpleopt/parse'
|
2
|
+
require 'rbbt/util/simpleopt/get'
|
3
|
+
require 'rbbt/util/simpleopt/doc'
|
4
|
+
module SOPT
|
5
|
+
def self.setup(str)
|
6
|
+
summary, synopsys, description, options = str.split(/\n\n+/)
|
7
|
+
|
8
|
+
if summary[0]=="-"
|
9
|
+
summary, synopsys, description, options = nil, nil, nil, summary
|
10
|
+
end
|
11
|
+
|
12
|
+
if synopsys and synopsys[0] != "$"
|
13
|
+
description, options = synopsys, description
|
14
|
+
synopsys = nil
|
15
|
+
end
|
16
|
+
|
17
|
+
if description and description[0] == "-"
|
18
|
+
description, options = nil, description
|
19
|
+
end
|
20
|
+
|
21
|
+
synopsys.sub!(/^\$\s+/,'') if synopsys
|
22
|
+
|
23
|
+
SOPT.summary = summary.strip if summary
|
24
|
+
SOPT.synopsys = synopsys.strip if synopsys
|
25
|
+
SOPT.description = description.strip if description
|
26
|
+
SOPT.parse options if options
|
27
|
+
|
28
|
+
SOPT.consume
|
29
|
+
end
|
30
|
+
end
|
@@ -2,13 +2,29 @@
|
|
2
2
|
|
3
3
|
require 'rbbt-util'
|
4
4
|
require 'rbbt/util/simpleopt'
|
5
|
-
require 'rbbt/sources/organism'
|
6
5
|
|
7
|
-
options = SOPT.
|
6
|
+
options = SOPT.setup <<EOF
|
7
|
+
|
8
|
+
Change the ID format of a column in a tsv file
|
9
|
+
|
10
|
+
$ rbbt command command [options] -f file
|
11
|
+
|
12
|
+
Use - to read from STDIN. The `field` is the tsv column to change.
|
13
|
+
the `target` is the target format, as appearing in the `identifiers`
|
14
|
+
file or in `Organism.identifiers("Hsa")`.
|
8
15
|
|
9
|
-
|
10
|
-
|
11
|
-
|
16
|
+
-f--file* File to process
|
17
|
+
-f--field* Field to change
|
18
|
+
-t--target* Target format
|
19
|
+
-i--identifiers* Identifier file to use
|
20
|
+
-h--help Help
|
21
|
+
|
22
|
+
EOF
|
23
|
+
rbbt_usage and exit 0 if options[:help]
|
24
|
+
|
25
|
+
SOPT.require options, :file, :field, :target
|
26
|
+
|
27
|
+
require 'rbbt/sources/organism'
|
12
28
|
|
13
29
|
identifiers = options[:identifiers] || Organism.identifiers("Hsa").find
|
14
30
|
|
@@ -32,20 +48,3 @@ tsv.fields = tsv.fields.collect{|f| f == field ? target : f}
|
|
32
48
|
|
33
49
|
puts tsv
|
34
50
|
|
35
|
-
exit
|
36
|
-
|
37
|
-
#stream = Open.open file
|
38
|
-
#header = TSV.parse_header stream
|
39
|
-
#field_pos = header.all_fields.index field
|
40
|
-
#raise ParameterException, "Unknown field: #{ field }" unless field_pos
|
41
|
-
#
|
42
|
-
#out = STDOUT
|
43
|
-
#out.puts TSV.header_lines :fields => header.fields, :key_field =
|
44
|
-
#while line = stream.gets do
|
45
|
-
# if line =~ /^#/
|
46
|
-
# out.puts line
|
47
|
-
# next
|
48
|
-
# else
|
49
|
-
# end
|
50
|
-
#end
|
51
|
-
#
|
@@ -3,7 +3,22 @@
|
|
3
3
|
require 'rbbt-util'
|
4
4
|
require 'rbbt/util/simpleopt'
|
5
5
|
|
6
|
-
options = SOPT.
|
6
|
+
options = SOPT.setup <<EOF
|
7
|
+
|
8
|
+
Pulls the values from a tsv colum
|
9
|
+
|
10
|
+
$ rbbt tsv values [options] <filename.tsv|->
|
11
|
+
|
12
|
+
Use - to read from STDIN
|
13
|
+
|
14
|
+
-tch--tokyocabinet File is a tokyocabinet hash database
|
15
|
+
-tcb--tokyocabinet_bd File is a tokyocabinet B database
|
16
|
+
-f--field* Limit to a particular field
|
17
|
+
-h--help Print this help
|
18
|
+
|
19
|
+
EOF
|
20
|
+
rbbt_usage and exit 0 if options[:help]
|
21
|
+
|
7
22
|
|
8
23
|
file = ARGV.shift
|
9
24
|
|
@@ -22,4 +37,6 @@ else
|
|
22
37
|
tsv = TSV.open(file)
|
23
38
|
end
|
24
39
|
|
40
|
+
tsv = tsv.slice(field) if field
|
41
|
+
|
25
42
|
tsv.each{|k,v| puts (Array === v ? v.flatten*"\t" : v.to_s ) }
|
@@ -65,7 +65,7 @@ def SOPT_options(workflow, task)
|
|
65
65
|
short = name.to_s.chars.first
|
66
66
|
boolean = workflow.rec_input_types(task.name)[name].to_sym == :boolean
|
67
67
|
|
68
|
-
sopt_options << "-#{short}--#{name}*"
|
68
|
+
sopt_options << "-#{short}--#{name}#{boolean ? "" : "*"}"
|
69
69
|
end
|
70
70
|
|
71
71
|
sopt_options * ":"
|
@@ -79,7 +79,7 @@ def fix_options(workflow, task, job_options)
|
|
79
79
|
job_options.each do |name, value|
|
80
80
|
value = case option_types[name].to_sym
|
81
81
|
when :boolean
|
82
|
-
%w(true TRUE T yes).include? value
|
82
|
+
TrueClass === true or %w(true TRUE T yes).include? value
|
83
83
|
when :float
|
84
84
|
value.to_f
|
85
85
|
when :integer
|
@@ -255,11 +255,15 @@ begin
|
|
255
255
|
|
256
256
|
if do_fork
|
257
257
|
job.fork
|
258
|
+
puts
|
258
259
|
while not job.done?
|
259
260
|
message = job.messages ? job.messages.last : "no message"
|
260
|
-
|
261
|
+
status = job.status
|
262
|
+
puts("No status yet") and next if status.nil?
|
263
|
+
puts Log.return_line + "Waiting on #{job.pid} " + [Log.color(:magenta, status.to_s),message]*" " + " " * 100
|
261
264
|
sleep 2
|
262
265
|
end
|
266
|
+
Signal.trap(:INT){ job.abort }
|
263
267
|
raise job.messages.last if job.error?
|
264
268
|
res = job.load
|
265
269
|
else
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), '../../..', 'test_helper.rb')
|
2
|
+
require 'rbbt/util/simpleopt/setup'
|
3
|
+
|
4
|
+
class TestSOPTSetup < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
SOPT.inputs = nil
|
7
|
+
SOPT.input_types = nil
|
8
|
+
SOPT.input_descriptions = nil
|
9
|
+
SOPT.input_shortcuts = nil
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_setup
|
13
|
+
SOPT.setup <<-EOF
|
14
|
+
Test application
|
15
|
+
|
16
|
+
$ test cmd -arg 1
|
17
|
+
|
18
|
+
It does some imaginary stuff
|
19
|
+
|
20
|
+
-a--arg* Argument
|
21
|
+
-a2--arg2* Argument
|
22
|
+
|
23
|
+
EOF
|
24
|
+
|
25
|
+
assert_equal "test cmd -arg 1", SOPT.synopsys
|
26
|
+
assert SOPT.inputs.include? "arg"
|
27
|
+
assert SOPT.inputs.include? "arg2"
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_setup_alt
|
31
|
+
SOPT.setup <<-EOF
|
32
|
+
Test application
|
33
|
+
|
34
|
+
It does some imaginary stuff
|
35
|
+
|
36
|
+
-a--arg* Argument
|
37
|
+
-a2--arg2* Argument
|
38
|
+
|
39
|
+
EOF
|
40
|
+
|
41
|
+
assert SOPT.inputs.include? "arg"
|
42
|
+
assert SOPT.inputs.include? "arg2"
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_setup_alt2
|
46
|
+
SOPT.setup <<-EOF
|
47
|
+
Test application
|
48
|
+
|
49
|
+
-a--arg* Argument
|
50
|
+
-a2--arg2* Argument
|
51
|
+
|
52
|
+
EOF
|
53
|
+
|
54
|
+
assert SOPT.inputs.include? "arg"
|
55
|
+
assert SOPT.inputs.include? "arg2"
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_setup_alt3
|
59
|
+
SOPT.setup <<-EOF
|
60
|
+
Pulls the values from a tsv colum
|
61
|
+
|
62
|
+
$ rbbt tsv values [options] <filename.tsv|->
|
63
|
+
|
64
|
+
Use - to read from STDIN
|
65
|
+
|
66
|
+
-tch--tokyocabinet File is a tokyocabinet hash database
|
67
|
+
-tcb--tokyocabinet_bd File is a tokyocabinet B database
|
68
|
+
-h--help Print this help
|
69
|
+
EOF
|
70
|
+
|
71
|
+
assert SOPT.inputs.include? "tokyocabinet"
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
|
data/test/rbbt/util/test_log.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rbbt-util
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.6.
|
4
|
+
version: 5.6.15
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Miguel Vazquez
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-02
|
11
|
+
date: 2014-03-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -187,6 +187,7 @@ files:
|
|
187
187
|
- lib/rbbt/util/simpleopt/doc.rb
|
188
188
|
- lib/rbbt/util/simpleopt/get.rb
|
189
189
|
- lib/rbbt/util/simpleopt/parse.rb
|
190
|
+
- lib/rbbt/util/simpleopt/setup.rb
|
190
191
|
- lib/rbbt/util/tar.rb
|
191
192
|
- lib/rbbt/util/task/job.rb
|
192
193
|
- lib/rbbt/util/tmpfile.rb
|
@@ -266,6 +267,7 @@ files:
|
|
266
267
|
- test/rbbt/tsv/test_util.rb
|
267
268
|
- test/rbbt/util/simpleopt/test_get.rb
|
268
269
|
- test/rbbt/util/simpleopt/test_parse.rb
|
270
|
+
- test/rbbt/util/simpleopt/test_setup.rb
|
269
271
|
- test/rbbt/util/test_R.rb
|
270
272
|
- test/rbbt/util/test_chain_methods.rb
|
271
273
|
- test/rbbt/util/test_cmd.rb
|
@@ -302,7 +304,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
302
304
|
version: '0'
|
303
305
|
requirements: []
|
304
306
|
rubyforge_project:
|
305
|
-
rubygems_version: 2.2.
|
307
|
+
rubygems_version: 2.2.2
|
306
308
|
signing_key:
|
307
309
|
specification_version: 4
|
308
310
|
summary: Utilities for the Ruby Bioinformatics Toolkit (rbbt)
|
@@ -310,6 +312,7 @@ test_files:
|
|
310
312
|
- test/rbbt/test_workflow.rb
|
311
313
|
- test/rbbt/resource/test_path.rb
|
312
314
|
- test/rbbt/util/test_cmd.rb
|
315
|
+
- test/rbbt/util/simpleopt/test_setup.rb
|
313
316
|
- test/rbbt/util/simpleopt/test_get.rb
|
314
317
|
- test/rbbt/util/simpleopt/test_parse.rb
|
315
318
|
- test/rbbt/util/test_chain_methods.rb
|