cloudfactory 0.1.21 → 0.1.22

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/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ ## 0.1.22 (2011-08-26)
2
+
3
+ * Fixed #317
4
+ * Fixed #156
5
+ * Fixed #328
6
+ * Store the account name and email ad while cf login
7
+ * For runs and lines listing, :page => 'all' added to return all the records #321
8
+ * Inserting units to existing production run #310
9
+
1
10
  ## 0.1.21 (2011-08-25)
2
11
 
3
12
  * Line listing with pagination with custom flags
data/bin/cf CHANGED
@@ -9,4 +9,10 @@ $LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib)
9
9
 
10
10
  require 'cf/cli'
11
11
 
12
- Cf::CLI.start
12
+ begin
13
+ Cf::CLI.start
14
+ rescue ArgumentError
15
+ $stderr.puts "\n\tError during processing: #{$!.message}\n\n"
16
+ rescue Psych::SyntaxError
17
+ $stderr.puts "\n\tError during processing: #{$!.message}\n\n"
18
+ end
data/cf.gemspec CHANGED
@@ -34,17 +34,20 @@ Gem::Specification.new do |s|
34
34
 
35
35
  3. Generate your first assembly line...
36
36
  > cf line generate <line-title>
37
-
38
- 4. Edit the generated line.yml to design your perfect assembly line
37
+
38
+ 4. Go into generated line directory
39
+ > cd <line-title>
40
+
41
+ 5. Edit the generated line.yml to design your perfect assembly line
39
42
  See http://developers.cloudfactory.com/lines/yaml.html
40
-
41
- 5. Create your line in CloudFactory
43
+
44
+ 6. Create your line in CloudFactory
42
45
  > cf line create
43
46
 
44
- 6. Do a test production run in the sandbox first...
47
+ 7. Do a test production run in the sandbox first...
45
48
  > cf production start TITLE -i=INPUT_DATA.CSV
46
49
 
47
- 7. Go live! Send your production run to real workers...
50
+ 8. Go live! Send your production run to real workers...
48
51
  > cf production start TITLE -i=INPUT_DATA.CSV --live
49
52
 
50
53
  ------------------------------------------------------------------------------
data/lib/cf/cli.rb CHANGED
@@ -17,10 +17,11 @@ require 'active_support/core_ext/object/blank'
17
17
 
18
18
  cli_directory = File.expand_path("../cf/cli", File.dirname(__FILE__))
19
19
  require "#{cli_directory}/config"
20
+ require "#{cli_directory}/line_yaml_validator"
20
21
  require "#{cli_directory}/line"
21
22
  require "#{cli_directory}/form"
22
23
  require "#{cli_directory}/production"
23
- require "#{cli_directory}/line_yaml_validator"
24
+
24
25
 
25
26
  if ENV['TEST']
26
27
  require 'ruby-debug'
data/lib/cf/cli/line.rb CHANGED
@@ -27,6 +27,8 @@ end
27
27
  module Cf # :nodoc: all
28
28
  class Line < Thor # :nodoc: all
29
29
  include Cf::Config
30
+ include Cf::LineYamlValidator
31
+
30
32
  desc "line generate LINE-TITLE", "generates a line template at <line-title>/line.yml"
31
33
  method_option :force, :type => :boolean, :default => false, :aliases => "-f", :desc => "force to overwrite the files if the line already exists, default is false"
32
34
  # method_option :with_custom_form, :type => :boolean, :default => false, :aliases => "-wcf", :desc => "generate the template with custom task form and the sample files, default is true"
@@ -68,9 +70,9 @@ module Cf # :nodoc: all
68
70
  CF.account_name = CF::Account.info.name
69
71
  line_title = options['line'].parameterize
70
72
  end
71
-
72
- line = CF::Line.find(line_title)
73
- line = Hashie::Mash.new(line)
73
+
74
+ resp_line = CF::Line.find(line_title)
75
+ line = Hashie::Mash.new(resp_line)
74
76
  if line.title == line_title
75
77
  if options.force
76
78
  CF::Line.destroy(line_title, :forced => true)
@@ -78,12 +80,11 @@ module Cf # :nodoc: all
78
80
  else
79
81
 
80
82
  # Check whether this line has existing runs or not
81
- runs = CF::Run.all(:line_title => line_title)
82
- if runs.class == Array and runs.present?
83
+ resp_runs = CF::Run.all({:line_title => line_title})
84
+
85
+ if resp_runs.has_key?("runs") && resp_runs['runs'].present?
83
86
  say("!!! Warning !!!\nThe following are the existing production runs based on this line.", :cyan)
84
-
85
- existing_runs = Cf::Production.new
86
- existing_runs.options = {"line" => line_title}
87
+ existing_runs = Cf::Production.new([],{'line' => line_title, 'all' => true})
87
88
  existing_runs.list
88
89
 
89
90
  delete_forcefully = agree("Do you still want to delete this line? [y/n] ")
@@ -126,8 +127,7 @@ module Cf # :nodoc: all
126
127
  say "The line.yml file does not exist in this directory", :red
127
128
  return
128
129
  end
129
-
130
- errors = LineYamlValidator.validate(yaml_source)
130
+ errors = validate(yaml_source)
131
131
 
132
132
  if errors.present?
133
133
  say("Invalid line.yml file. Correct its structure as per the errors shown below.", :red)
@@ -310,7 +310,7 @@ module Cf # :nodoc: all
310
310
  say("You don't have any lines to list", :yellow) and return if lines.blank?
311
311
 
312
312
  if resp_lines['total_pages']
313
- say("Showing page #{current_page} of #{resp_lines['total_pages']} (Total lines: #{resp_lines['total_lines']})")
313
+ say("Showing page #{current_page} of #{resp_lines['total_pages']}\tTotal lines: #{resp_lines['total_lines']}")
314
314
  end
315
315
  lines.sort! { |a, b| a['title'] <=> b['title'] }
316
316
  lines_table = table do |t|
@@ -1,181 +1,182 @@
1
1
  module Cf
2
- class LineYamlValidator
2
+ module LineYamlValidator
3
3
 
4
- def self.validate(yaml_path)
5
- line_dump = YAML::load(File.read(yaml_path).strip)
6
- errors = []
7
- # Checking Department
8
- if line_dump['department'].nil?
9
- errors << "The line Department is missing!"
10
- end
4
+ def validate(yaml_path)
5
+ line_dump = YAML::load(File.read(yaml_path).strip)
6
+ errors = []
7
+ # Checking Department
8
+ if line_dump['department'].nil?
9
+ errors << "The line Department is missing!"
10
+ end
11
11
 
12
- # Checking Input Formats
13
- input_formats = line_dump['input_formats']
14
- if input_formats.nil?
15
- errors << "The Input Format is missing!"
16
- else
17
- if input_formats.class == Array
18
- input_formats.each_with_index do |input_format, index|
19
- name = input_format['name']
20
- required = input_format['required']
21
- valid_type = input_format['valid_type']
22
- if name.nil?
23
- errors << "Input Format name is missing in Block #{index+1}!"
12
+ # Checking Input Formats
13
+ input_formats = line_dump['input_formats']
14
+ if input_formats.nil?
15
+ errors << "The Input Format is missing!"
16
+ else
17
+ if input_formats.class == Array
18
+ input_formats.each_with_index do |input_format, index|
19
+ name = input_format['name']
20
+ required = input_format['required']
21
+ valid_type = input_format['valid_type']
22
+ if name.nil?
23
+ errors << "Input Format name is missing in Block #{index+1}!"
24
+ end
24
25
  end
25
26
  end
26
27
  end
27
- end
28
28
 
29
- # Checking Stations
30
- stations = line_dump['stations']
31
- if stations.nil?
32
- errors << "Station is missing!"
33
- else
34
- if stations.class == Array
35
- if stations.first['station'].nil?
36
- errors << "Station Settings missing!"
37
- else
38
- stations.each_with_index do |station, i|
39
- station_index = station['station']['station_index']
40
- errors << "Station Index is missing in Block station #{i+1}!" if station_index.nil?
29
+ # Checking Stations
30
+ stations = line_dump['stations']
31
+ if stations.nil?
32
+ errors << "Station is missing!"
33
+ else
34
+ if stations.class == Array
35
+ if stations.first['station'].nil?
36
+ errors << "Station Settings missing!"
37
+ else
38
+ stations.each_with_index do |station, i|
39
+ station_index = station['station']['station_index']
40
+ errors << "Station Index is missing in Block station #{i+1}!" if station_index.nil?
41
41
 
42
- station_type = station['station']['station_type']
43
- errors << "Station type is missing in Block station #{i+1}!" if station_type.nil?
42
+ station_type = station['station']['station_type']
43
+ errors << "Station type is missing in Block station #{i+1}!" if station_type.nil?
44
44
 
45
- if station_type == "tournament"
46
- jury_worker = station['station']['jury_worker']
47
- if jury_worker.nil?
48
- errors << "Jury worker setting is missing in Block station #{i+1}!"
49
- elsif !jury_worker.nil?
50
- reward = jury_worker['reward']
51
- errors << "Reward for Jury worker is missing in block of Tournament Station #{i+1}!" if reward.nil?
52
- errors << "Reward Must be greater than 0 in Block station #{i+1}!" if !reward.nil? && reward < 1
53
- end
54
- end
55
- # Checking Worker
56
- worker = station['station']['worker']
57
- if worker.class != Hash
58
- errors << "Worker is missing in Block station #{i+1}!"
59
- elsif worker.class == Hash
60
- # Checking Worker type
61
- worker.each_pair do |k, v|
62
- errors << "Should not be an array" if v.class == Array && k != "skill_badges"
45
+ if station_type == "tournament"
46
+ jury_worker = station['station']['jury_worker']
47
+ if jury_worker.nil?
48
+ errors << "Jury worker setting is missing in Block station #{i+1}!"
49
+ elsif !jury_worker.nil?
50
+ reward = jury_worker['reward']
51
+ errors << "Reward for Jury worker is missing in block of Tournament Station #{i+1}!" if reward.nil?
52
+ errors << "Reward Must be greater than 0 in Block station #{i+1}!" if !reward.nil? && reward < 1
53
+ end
63
54
  end
64
- worker_type = worker['worker_type']
65
- if worker_type.nil?
66
- errors << "Worker Type is missing!"
67
- else
68
- if worker_type != "human"
69
- errors << "Worker type is invalid in Block station #{i+1}!" if worker_type.split("_").last != "robot"
70
- if worker_type.split("_").last == "robot"
71
- settings = worker['settings']
72
- errors << "Settings for the robot worker is missingin Block station #{i+1}!" if settings.nil?
73
- end
74
- elsif worker_type == "human"
75
- # Checking number of workers if worker_type == "human"
76
- num_workers = worker['num_workers']
77
- if num_workers.nil?
78
- errors << "Number of workers not specified in Block station #{i+1}!"
79
- else
80
- errors << "Number of workers must be greater than 0 in Block station #{i+1}!" if num_workers < 1
81
- end
55
+ # Checking Worker
56
+ worker = station['station']['worker']
57
+ if worker.class != Hash
58
+ errors << "Worker is missing in Block station #{i+1}!"
59
+ elsif worker.class == Hash
60
+ # Checking Worker type
61
+ worker.each_pair do |k, v|
62
+ errors << "Should not be an array" if v.class == Array && k != "skill_badges"
63
+ end
64
+ worker_type = worker['worker_type']
65
+ if worker_type.nil?
66
+ errors << "Worker Type is missing!"
67
+ else
68
+ if worker_type != "human"
69
+ errors << "Worker type is invalid in Block station #{i+1}!" if worker_type.split("_").last != "robot"
70
+ if worker_type.split("_").last == "robot"
71
+ settings = worker['settings']
72
+ errors << "Settings for the robot worker is missingin Block station #{i+1}!" if settings.nil?
73
+ end
74
+ elsif worker_type == "human"
75
+ # Checking number of workers if worker_type == "human"
76
+ num_workers = worker['num_workers']
77
+ if num_workers.nil?
78
+ errors << "Number of workers not specified in Block station #{i+1}!"
79
+ else
80
+ errors << "Number of workers must be greater than 0 in Block station #{i+1}!" if num_workers < 1
81
+ end
82
82
 
83
- # Checking reward of workers if worker_type == "human"
84
- reward = worker['reward']
85
- if reward.nil?
86
- errors << "Reward of workers not specified in Block station #{i+1}!"
87
- else
88
- errors << "Reward of workers must be greater than 0 in Block station #{i+1}!" if reward < 1
83
+ # Checking reward of workers if worker_type == "human"
84
+ reward = worker['reward']
85
+ if reward.nil?
86
+ errors << "Reward of workers not specified in Block station #{i+1}!"
87
+ else
88
+ errors << "Reward of workers must be greater than 0 in Block station #{i+1}!" if reward < 1
89
+ end
89
90
  end
90
91
  end
91
92
  end
92
- end
93
93
 
94
- if station_type != "improve"
95
- # Checking Stat_badge
96
- stat_badge = station['station']['worker']['stat_badge']
97
- if !stat_badge.nil?
98
- errors << "Stat badge setting is invalid in Block station #{i+1}!" if stat_badge.class != Hash
99
- end
94
+ if station_type != "improve"
95
+ # Checking Stat_badge
96
+ stat_badge = station['station']['worker']['stat_badge']
97
+ if !stat_badge.nil?
98
+ errors << "Stat badge setting is invalid in Block station #{i+1}!" if stat_badge.class != Hash
99
+ end
100
100
 
101
- # Checking skill_badge
102
- skill_badges = station['station']['worker']['skill_badges']
103
- if !skill_badges.nil?
104
- errors << "Skill badge settings is invalid in Block station #{i+1}!" if skill_badges.class != Array
105
- skill_badges.each_with_index do |badge, badge_index|
106
- badge_title = badge['title']
107
- badge_description = badge['description']
108
- max_badges = badge['max_badges']
109
- badge_test = badge['test']
110
- test_input = badge_test['input'] if badge_test.class == Hash
111
- expected_output = badge_test['expected_output'] if badge_test.class == Hash
112
- errors << "Skill badge title is Missing in Block #{badge_index+1}!" if badge_title.nil?
113
- errors << "Skill badge Description is Missing in Block #{badge_index+1}!" if badge_description.nil?
114
- errors << "Skill badge max_badges must be greater than 1000 in Block #{badge_index+1}!" if max_badges < 1000 && !max_badges.nil?
115
- errors << "Skill badge Test is Missing in Block #{badge_index+1}!" if badge_test.nil?
116
- errors << "Skill badge Test is Invalid (must be Hash) in Block #{badge_index+1}!" if badge_test.class != Hash && !badge_test.nil?
117
- errors << "Skill badge Test input is Missing in Block #{badge_index+1}!" if test_input.nil? && !badge_test.nil?
118
- errors << "Skill badge Test input is Invalid (must be Hash) in Block #{badge_index+1}!" if test_input.class != Hash && !test_input.nil? && !badge_test.nil?
119
- errors << "Skill badge Test expected_output is Missing in Block #{badge_index+1}!" if expected_output.nil? && !badge_test.nil?
120
- errors << "Skill badge Test expected_output is Invalid (must be an array) in Block #{badge_index+1}!" if expected_output.class != Array && !expected_output.nil? && !badge_test.nil?
101
+ # Checking skill_badge
102
+ skill_badges = station['station']['worker']['skill_badges']
103
+ if !skill_badges.nil?
104
+ errors << "Skill badge settings is invalid in Block station #{i+1}!" if skill_badges.class != Array
105
+ skill_badges.each_with_index do |badge, badge_index|
106
+ badge_title = badge['title']
107
+ badge_description = badge['description']
108
+ max_badges = badge['max_badges']
109
+ badge_test = badge['test']
110
+ test_input = badge_test['input'] if badge_test.class == Hash
111
+ expected_output = badge_test['expected_output'] if badge_test.class == Hash
112
+ errors << "Skill badge title is Missing in Block #{badge_index+1}!" if badge_title.nil?
113
+ errors << "Skill badge Description is Missing in Block #{badge_index+1}!" if badge_description.nil?
114
+ errors << "Skill badge max_badges must be greater than 1000 in Block #{badge_index+1}!" if max_badges < 1000 && !max_badges.nil?
115
+ errors << "Skill badge Test is Missing in Block #{badge_index+1}!" if badge_test.nil?
116
+ errors << "Skill badge Test is Invalid (must be Hash) in Block #{badge_index+1}!" if badge_test.class != Hash && !badge_test.nil?
117
+ errors << "Skill badge Test input is Missing in Block #{badge_index+1}!" if test_input.nil? && !badge_test.nil?
118
+ errors << "Skill badge Test input is Invalid (must be Hash) in Block #{badge_index+1}!" if test_input.class != Hash && !test_input.nil? && !badge_test.nil?
119
+ errors << "Skill badge Test expected_output is Missing in Block #{badge_index+1}!" if expected_output.nil? && !badge_test.nil?
120
+ errors << "Skill badge Test expected_output is Invalid (must be an array) in Block #{badge_index+1}!" if expected_output.class != Array && !expected_output.nil? && !badge_test.nil?
121
+ end
121
122
  end
122
- end
123
123
 
124
- # Checking TaskForm
125
- if worker_type == "human"
126
- task_form = station['station']['task_form']
127
- if task_form.nil?
128
- custom_task_form = station['station']['custom_task_form']
129
- if custom_task_form.nil?
130
- errors << "Form is missing in Block station #{i+1}!"
131
- elsif custom_task_form.class == Hash
132
- form_title = custom_task_form['form_title']
133
- errors << "Form Title is missing in Block station #{i+1}!" if form_title.nil?
124
+ # Checking TaskForm
125
+ if worker_type == "human"
126
+ task_form = station['station']['task_form']
127
+ if task_form.nil?
128
+ custom_task_form = station['station']['custom_task_form']
129
+ if custom_task_form.nil?
130
+ errors << "Form is missing in Block station #{i+1}!"
131
+ elsif custom_task_form.class == Hash
132
+ form_title = custom_task_form['form_title']
133
+ errors << "Form Title is missing in Block station #{i+1}!" if form_title.nil?
134
134
 
135
- instruction = custom_task_form['instruction']
136
- errors << "Form Instruction is missing in Block station #{i+1}!" if instruction.nil?
135
+ instruction = custom_task_form['instruction']
136
+ errors << "Form Instruction is missing in Block station #{i+1}!" if instruction.nil?
137
137
 
138
- errors << "station_#{i+1} folder is missing! Create station_#{i+1} folder in #{Dir.pwd}" if !File.exist?("#{Dir.pwd}/station_#{i+1}")
138
+ errors << "station_#{i+1} folder is missing! Create station_#{i+1} folder in #{Dir.pwd}" if !File.exist?("#{Dir.pwd}/station_#{i+1}")
139
139
 
140
- if File.exist?("#{Dir.pwd}/station_#{i+1}")
141
- station_source = "#{Dir.pwd}/station_#{i+1}"
142
- errors << "form.html is missing in folder #{Dir.pwd}/station_#{i+1} !" if !File.exist?("#{station_source}/form.html")
140
+ if File.exist?("#{Dir.pwd}/station_#{i+1}")
141
+ station_source = "#{Dir.pwd}/station_#{i+1}"
142
+ errors << "form.html is missing in folder #{Dir.pwd}/station_#{i+1} !" if !File.exist?("#{station_source}/form.html")
143
+ end
143
144
  end
144
- end
145
- elsif task_form.class == Hash
146
- form_title = task_form['form_title']
147
- errors << "Form Title is missing in Block station #{i+1}!" if form_title.nil?
145
+ elsif task_form.class == Hash
146
+ form_title = task_form['form_title']
147
+ errors << "Form Title is missing in Block station #{i+1}!" if form_title.nil?
148
148
 
149
- instruction = task_form['instruction']
150
- errors << "Form Instruction is missing in Block station #{i+1}!" if instruction.nil?
149
+ instruction = task_form['instruction']
150
+ errors << "Form Instruction is missing in Block station #{i+1}!" if instruction.nil?
151
151
 
152
- # Checking Form Fields
153
- form_fields = task_form['form_fields']
154
- errors << "Form Field is missing in Block station #{i+1}!" if form_fields.nil?
155
- if form_fields.class == Array
156
- form_fields.each_with_index do |form_field, index|
157
- field_label = form_field['label']
158
- errors << "Label is missing in block #{index+1} of Form Field within Station #{i+1}!" if field_label.nil?
159
- required = form_field['required']
160
- field_type = form_field['field_type']
161
- if !field_type.nil?
162
- unless %w(short_answer long_answer radio_button check_box select_box date email number).include?(field_type)
163
- errors << "Field Type of Form Field is invalid in Block #{index+1} of station Block #{i+1}!"
164
- end
165
- if field_type == "radio_button" || field_type == "select_box"
166
- option_values = form_field['option_values']
167
- if option_values.nil?
168
- errors << "Option values is required for field_type => #{field_type} in block #{index+1} of Form Field within Station #{i+1} !"
169
- elsif !option_values.nil?
170
- if option_values.class != Array
171
- errors << "Option values must be an array for field_type => #{field_type} in block #{index+1} of Form Field within Station #{i+1}!"
152
+ # Checking Form Fields
153
+ form_fields = task_form['form_fields']
154
+ errors << "Form Field is missing in Block station #{i+1}!" if form_fields.nil?
155
+ if form_fields.class == Array
156
+ form_fields.each_with_index do |form_field, index|
157
+ field_label = form_field['label']
158
+ errors << "Label is missing in block #{index+1} of Form Field within Station #{i+1}!" if field_label.nil?
159
+ required = form_field['required']
160
+ field_type = form_field['field_type']
161
+ if !field_type.nil?
162
+ unless %w(short_answer long_answer radio_button check_box select_box date email number).include?(field_type)
163
+ errors << "Field Type of Form Field is invalid in Block #{index+1} of station Block #{i+1}!"
164
+ end
165
+ if field_type == "radio_button" || field_type == "select_box"
166
+ option_values = form_field['option_values']
167
+ if option_values.nil?
168
+ errors << "Option values is required for field_type => #{field_type} in block #{index+1} of Form Field within Station #{i+1} !"
169
+ elsif !option_values.nil?
170
+ if option_values.class != Array
171
+ errors << "Option values must be an array for field_type => #{field_type} in block #{index+1} of Form Field within Station #{i+1}!"
172
+ end
172
173
  end
173
174
  end
174
175
  end
175
176
  end
177
+ else
178
+ errors << "Form fields must be an array for Station #{i+1}!"
176
179
  end
177
- else
178
- errors << "Form fields must be an array for Station #{i+1}!"
179
180
  end
180
181
  end
181
182
  end
@@ -183,8 +184,7 @@ module Cf
183
184
  end
184
185
  end
185
186
  end
186
- end
187
- return errors
187
+ return errors
188
188
  end
189
189
  end
190
190
  end
@@ -134,26 +134,57 @@ module Cf # :nodoc: all
134
134
  end
135
135
 
136
136
  desc "production list", "list the production runs"
137
- method_option :line, :type => :string, :aliases => "-l", :desc => "the title of the line"
137
+ method_option :line, :type => :string, :aliases => "-l", :desc => "the title of the line, if the line title is not given, it will show all the production runs under your account"
138
138
  method_option :page, :type => :numeric, :aliases => "-p", :desc => "page number"
139
+ method_option :all, :type => :boolean, :default => false, :aliases => '-a', :desc => "list all the production runs"
139
140
  def list
140
141
  set_target_uri(false)
141
142
  set_api_key
142
143
  CF.account_name = CF::Account.info.name
144
+ param = {}
145
+ current_page = 1
146
+
143
147
  if options['line'].present?
144
148
  line_title = options['line'].parameterize
145
- runs = CF::Run.all(:line_title => line_title)
149
+ param.merge!({:line_title => line_title})
150
+
151
+ if options['all']
152
+ param.merge!({:page => "all"})
153
+ current_page = 1
154
+ end
155
+
156
+ if page = options['page'].presence
157
+ param.merge!({:page => page})
158
+ current_page = page
159
+ end
160
+
146
161
  else
147
- runs = CF::Run.all
148
- end
162
+ if options['all']
163
+ param = {:page => "all"}
164
+ current_page = 1
165
+ end
149
166
 
150
- unless runs.kind_of?(Array)
151
- if runs.error.present?
152
- say("No Runs\n#{runs.error.message}", :red) and exit(1)
167
+ if page = options['page'].presence
168
+ param.merge!({:page => page})
169
+ current_page = page
153
170
  end
154
171
  end
155
172
 
156
- runs.sort! {|a, b| a[:name] <=> b[:name] }
173
+ resp_runs = CF::Run.all(param)
174
+
175
+ if resp_runs.has_key?('error')
176
+ say("#{resp_runs['error']}", :red) and exit(1)
177
+ end
178
+
179
+ if resp_runs.has_key?("runs") && resp_runs['runs'].blank?
180
+ say("\nRun list is empty.\n", :yellow) and return
181
+ end
182
+
183
+ if resp_runs['total_pages']
184
+ say("\nShowing page #{current_page} of #{resp_runs['total_pages']} (Total runs: #{resp_runs['total_runs']})")
185
+ end
186
+ runs = resp_runs['runs'].presence
187
+ runs.sort! {|a, b| a['title'] <=> b['title'] }
157
188
  runs_table = table do |t|
158
189
  t.headings = ["Run Title", 'URL']
159
190
  runs.each do |run|
@@ -184,6 +215,35 @@ module Cf # :nodoc: all
184
215
  # if result.status == "resumed"
185
216
  say("Run with title \"#{result.title}\" is resumed!", :green)
186
217
  # end
187
- end
218
+ end
219
+
220
+ desc "production add_units", "add units to already existing production run"
221
+ method_option :run_title, :type => :string, :required => true, :aliases => "-t", :desc => "the title of the run to resume"
222
+ method_option :input_data, :type => :string, :required => true, :aliases => "-i", :desc => "the path of the input data file"
223
+
224
+ def add_units
225
+ set_target_uri(false)
226
+ set_api_key
227
+ CF.account_name = CF::Account.info.name
228
+ run_title = options[:run_title].parameterize
229
+ input_data = options[:input_data].presence
230
+
231
+ if input_data =~ /^\// #checking absolute input data path
232
+ input_data_file = input_data
233
+ else
234
+ unless File.exist?(input_data)
235
+ say("The input data file named #{input_data} doesn't exist", :red) and return
236
+ end
237
+ input_data_file = "#{Dir.pwd}/#{input_data}"
238
+ end
239
+ units = CF::Run.add_units({:run_title => run_title, :file => input_data_file})
240
+ if units['error'].present?
241
+ say("Error: #{units['error']['message']}", :red) and exit(1)
242
+ end
243
+
244
+ # if result.status == "resumed"
245
+ say("\"#{units['successfull']}\"!", :green)
246
+ # end
247
+ end
188
248
  end
189
249
  end
data/lib/cf/run.rb CHANGED
@@ -89,18 +89,27 @@ module CF
89
89
  def self.add_units(options={})
90
90
  units = options[:units].presence
91
91
  run_title = options[:run_title].presence
92
-
93
- request =
94
- {
95
- :body =>
92
+ file = options[:file].presence
93
+ if units
94
+ request =
96
95
  {
97
- :api_key => CF.api_key,
98
- :data => units
96
+ :body =>
97
+ {
98
+ :api_key => CF.api_key,
99
+ :data => units
100
+ }
99
101
  }
100
- }
101
- resp = HTTParty.post("#{CF.api_url}#{CF.api_version}/runs/#{CF.account_name}/#{run_title.downcase}/units.json",request)
102
- @errors = resp['error']['message'] if resp.code != 200
103
- return resp.parsed_response
102
+ resp = HTTParty.post("#{CF.api_url}#{CF.api_version}/runs/#{CF.account_name}/#{run_title.downcase}/units.json",request)
103
+ @errors = resp['error']['message'] if resp.code != 200
104
+ return resp.parsed_response
105
+ elsif file
106
+ if File.exist?(file.to_s)
107
+ file_upload = File.new(file, 'rb')
108
+ resp = post("/runs/#{CF.account_name}/#{run_title.downcase}/units.json", {:file => file_upload})
109
+ @errors = resp.error.message if resp.code != 200
110
+ return resp.to_hash
111
+ end
112
+ end
104
113
  end
105
114
  # ==Returns Final Output of production Run
106
115
  # ===Usage Example:
@@ -216,7 +225,12 @@ module CF
216
225
  resp = get("/lines/#{CF.account_name}/#{line_title}/list_runs.json", :page => page)
217
226
  end
218
227
  end
219
- @errors = resp.error.message if resp.code != 200
228
+
229
+ if resp.code != 200
230
+ send_resp = {"error" => resp.error.message}
231
+ return send_resp
232
+ end
233
+
220
234
  new_resp = []
221
235
  if resp.code == 200
222
236
  if resp.runs
@@ -226,7 +240,7 @@ module CF
226
240
  end
227
241
  end
228
242
  end
229
- send_resp = {"runs" => new_resp, "total_pages" => resp.total_pages}
243
+ send_resp = {"runs" => new_resp, "total_pages" => resp.total_pages, "total_runs" => resp.total_runs}
230
244
  return send_resp
231
245
  end
232
246
  end
data/lib/cf/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module CF # :nodoc: all
2
- VERSION = "0.1.21"
2
+ VERSION = "0.1.22"
3
3
  end
data/spec/run_spec.rb CHANGED
@@ -379,7 +379,8 @@ module CF
379
379
 
380
380
  got_run = CF::Run.all
381
381
  got_run['runs'].class.should eql(Array)
382
- got_run['total_pages'].should eql(2)
382
+ got_run['runs'].first['progress'].should eql(100)
383
+ got_run['runs'].first['status'].should eql("active")
383
384
  end
384
385
  end
385
386
 
@@ -407,6 +408,8 @@ module CF
407
408
  # WebMock.allow_net_connect!
408
409
  run = CF::Run.all({:page => 1})
409
410
  run['runs'].class.should eql(Array)
411
+ run['runs'].first['progress'].should eql(100)
412
+ run['runs'].first['status'].should eql("active")
410
413
  end
411
414
  end
412
415
 
@@ -481,6 +484,28 @@ module CF
481
484
  end
482
485
  end
483
486
 
487
+ it "should add units by passing file" do
488
+ VCR.use_cassette "run/block/adding_units_file", :record => :new_episodes do
489
+ # WebMock.allow_net_connect!
490
+ line = CF::Line.create("adding_units_file","Digitization") do |l|
491
+ CF::InputFormat.new({:line => l, :name => "Company", :required => true, :valid_type => "general"})
492
+ CF::InputFormat.new({:line => l, :name => "Website", :required => true, :valid_type => "url"})
493
+ CF::Station.create({:line => l, :type => "work"}) do |s|
494
+ CF::HumanWorker.new({:station => s, :number => 1, :reward => 20})
495
+ CF::TaskForm.create({:station => s, :title => "Enter text from a business card image", :instruction => "Describe"}) do |i|
496
+ CF::FormField.new({:form => i, :label => "First Name", :field_type => "short_answer", :required => "true"})
497
+ CF::FormField.new({:form => i, :label => "Middle Name", :field_type => "short_answer"})
498
+ CF::FormField.new({:form => i, :label => "Last Name", :field_type => "short_answer", :required => "true"})
499
+ end
500
+ end
501
+ end
502
+ run = CF::Run.create(line, "adding_units_file_run", [{"Company"=>"Sprout","Website"=>"sprout.com"}])
503
+ added_units = CF::Run.add_units({:run_title => "adding_units_file_run", :file => File.expand_path("../../fixtures/input_data/test.csv", __FILE__)})
504
+ added_units['successfull'].should eql("sucessfully added 1 units, failed :0")
505
+ run.title.should eql("adding_units_file_run")
506
+ end
507
+ end
508
+
484
509
  it "should throw errors for invalid input while adding units" do
485
510
  VCR.use_cassette "run/block/adding_units_errors", :record => :new_episodes do
486
511
  # WebMock.allow_net_connect!
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cloudfactory
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.21
4
+ version: 0.1.22
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2011-08-25 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: i18n
16
- requirement: &2154423560 !ruby/object:Gem::Requirement
16
+ requirement: &2161047200 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *2154423560
24
+ version_requirements: *2161047200
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: activesupport
27
- requirement: &2154423060 !ruby/object:Gem::Requirement
27
+ requirement: &2161046700 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '3.0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *2154423060
35
+ version_requirements: *2161046700
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: hashie
38
- requirement: &2154422560 !ruby/object:Gem::Requirement
38
+ requirement: &2161046200 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '1.0'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *2154422560
46
+ version_requirements: *2161046200
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: rest-client
49
- requirement: &2157390480 !ruby/object:Gem::Requirement
49
+ requirement: &2161045820 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *2157390480
57
+ version_requirements: *2161045820
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: json
60
- requirement: &2157390020 !ruby/object:Gem::Requirement
60
+ requirement: &2161045360 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :runtime
67
67
  prerelease: false
68
- version_requirements: *2157390020
68
+ version_requirements: *2161045360
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: thor
71
- requirement: &2157389520 !ruby/object:Gem::Requirement
71
+ requirement: &2161044860 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ~>
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '0.14'
77
77
  type: :runtime
78
78
  prerelease: false
79
- version_requirements: *2157389520
79
+ version_requirements: *2161044860
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: highline
82
- requirement: &2157389100 !ruby/object:Gem::Requirement
82
+ requirement: &2161044440 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
@@ -87,10 +87,10 @@ dependencies:
87
87
  version: '0'
88
88
  type: :runtime
89
89
  prerelease: false
90
- version_requirements: *2157389100
90
+ version_requirements: *2161044440
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: httparty
93
- requirement: &2157388560 !ruby/object:Gem::Requirement
93
+ requirement: &2161043900 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - ~>
@@ -98,10 +98,10 @@ dependencies:
98
98
  version: '0.7'
99
99
  type: :runtime
100
100
  prerelease: false
101
- version_requirements: *2157388560
101
+ version_requirements: *2161043900
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: terminal-table
104
- requirement: &2157388060 !ruby/object:Gem::Requirement
104
+ requirement: &2161043400 !ruby/object:Gem::Requirement
105
105
  none: false
106
106
  requirements:
107
107
  - - ~>
@@ -109,10 +109,10 @@ dependencies:
109
109
  version: '1.4'
110
110
  type: :runtime
111
111
  prerelease: false
112
- version_requirements: *2157388060
112
+ version_requirements: *2161043400
113
113
  - !ruby/object:Gem::Dependency
114
114
  name: millisami-csv-hash
115
- requirement: &2157387680 !ruby/object:Gem::Requirement
115
+ requirement: &2161043020 !ruby/object:Gem::Requirement
116
116
  none: false
117
117
  requirements:
118
118
  - - ! '>='
@@ -120,10 +120,10 @@ dependencies:
120
120
  version: '0'
121
121
  type: :runtime
122
122
  prerelease: false
123
- version_requirements: *2157387680
123
+ version_requirements: *2161043020
124
124
  - !ruby/object:Gem::Dependency
125
125
  name: awesome_print
126
- requirement: &2157387220 !ruby/object:Gem::Requirement
126
+ requirement: &2161060720 !ruby/object:Gem::Requirement
127
127
  none: false
128
128
  requirements:
129
129
  - - ! '>='
@@ -131,10 +131,10 @@ dependencies:
131
131
  version: '0'
132
132
  type: :runtime
133
133
  prerelease: false
134
- version_requirements: *2157387220
134
+ version_requirements: *2161060720
135
135
  - !ruby/object:Gem::Dependency
136
136
  name: ruby-debug19
137
- requirement: &2157386800 !ruby/object:Gem::Requirement
137
+ requirement: &2161060300 !ruby/object:Gem::Requirement
138
138
  none: false
139
139
  requirements:
140
140
  - - ! '>='
@@ -142,10 +142,10 @@ dependencies:
142
142
  version: '0'
143
143
  type: :development
144
144
  prerelease: false
145
- version_requirements: *2157386800
145
+ version_requirements: *2161060300
146
146
  - !ruby/object:Gem::Dependency
147
147
  name: aruba
148
- requirement: &2157386380 !ruby/object:Gem::Requirement
148
+ requirement: &2161059880 !ruby/object:Gem::Requirement
149
149
  none: false
150
150
  requirements:
151
151
  - - ! '>='
@@ -153,10 +153,10 @@ dependencies:
153
153
  version: '0'
154
154
  type: :development
155
155
  prerelease: false
156
- version_requirements: *2157386380
156
+ version_requirements: *2161059880
157
157
  - !ruby/object:Gem::Dependency
158
158
  name: rails
159
- requirement: &2157385880 !ruby/object:Gem::Requirement
159
+ requirement: &2161059380 !ruby/object:Gem::Requirement
160
160
  none: false
161
161
  requirements:
162
162
  - - ~>
@@ -164,10 +164,10 @@ dependencies:
164
164
  version: 3.0.3
165
165
  type: :development
166
166
  prerelease: false
167
- version_requirements: *2157385880
167
+ version_requirements: *2161059380
168
168
  - !ruby/object:Gem::Dependency
169
169
  name: bundler
170
- requirement: &2157385380 !ruby/object:Gem::Requirement
170
+ requirement: &2161058880 !ruby/object:Gem::Requirement
171
171
  none: false
172
172
  requirements:
173
173
  - - ~>
@@ -175,10 +175,10 @@ dependencies:
175
175
  version: 1.0.0
176
176
  type: :development
177
177
  prerelease: false
178
- version_requirements: *2157385380
178
+ version_requirements: *2161058880
179
179
  - !ruby/object:Gem::Dependency
180
180
  name: generator_spec
181
- requirement: &2157384920 !ruby/object:Gem::Requirement
181
+ requirement: &2161058420 !ruby/object:Gem::Requirement
182
182
  none: false
183
183
  requirements:
184
184
  - - ~>
@@ -186,10 +186,10 @@ dependencies:
186
186
  version: 0.8.3
187
187
  type: :development
188
188
  prerelease: false
189
- version_requirements: *2157384920
189
+ version_requirements: *2161058420
190
190
  - !ruby/object:Gem::Dependency
191
191
  name: rspec-rails
192
- requirement: &2157384540 !ruby/object:Gem::Requirement
192
+ requirement: &2161058040 !ruby/object:Gem::Requirement
193
193
  none: false
194
194
  requirements:
195
195
  - - ! '>='
@@ -197,10 +197,10 @@ dependencies:
197
197
  version: '0'
198
198
  type: :development
199
199
  prerelease: false
200
- version_requirements: *2157384540
200
+ version_requirements: *2161058040
201
201
  - !ruby/object:Gem::Dependency
202
202
  name: cucumber
203
- requirement: &2157384080 !ruby/object:Gem::Requirement
203
+ requirement: &2161057580 !ruby/object:Gem::Requirement
204
204
  none: false
205
205
  requirements:
206
206
  - - ! '>='
@@ -208,10 +208,10 @@ dependencies:
208
208
  version: '0'
209
209
  type: :development
210
210
  prerelease: false
211
- version_requirements: *2157384080
211
+ version_requirements: *2161057580
212
212
  - !ruby/object:Gem::Dependency
213
213
  name: rdoc
214
- requirement: &2157383580 !ruby/object:Gem::Requirement
214
+ requirement: &2161057080 !ruby/object:Gem::Requirement
215
215
  none: false
216
216
  requirements:
217
217
  - - ~>
@@ -219,10 +219,10 @@ dependencies:
219
219
  version: 3.5.3
220
220
  type: :development
221
221
  prerelease: false
222
- version_requirements: *2157383580
222
+ version_requirements: *2161057080
223
223
  - !ruby/object:Gem::Dependency
224
224
  name: vcr
225
- requirement: &2157383160 !ruby/object:Gem::Requirement
225
+ requirement: &2161056660 !ruby/object:Gem::Requirement
226
226
  none: false
227
227
  requirements:
228
228
  - - ! '>='
@@ -230,10 +230,10 @@ dependencies:
230
230
  version: '0'
231
231
  type: :development
232
232
  prerelease: false
233
- version_requirements: *2157383160
233
+ version_requirements: *2161056660
234
234
  - !ruby/object:Gem::Dependency
235
235
  name: rake
236
- requirement: &2157382700 !ruby/object:Gem::Requirement
236
+ requirement: &2161056200 !ruby/object:Gem::Requirement
237
237
  none: false
238
238
  requirements:
239
239
  - - ! '>='
@@ -241,10 +241,10 @@ dependencies:
241
241
  version: '0'
242
242
  type: :development
243
243
  prerelease: false
244
- version_requirements: *2157382700
244
+ version_requirements: *2161056200
245
245
  - !ruby/object:Gem::Dependency
246
246
  name: webmock
247
- requirement: &2157398660 !ruby/object:Gem::Requirement
247
+ requirement: &2161055780 !ruby/object:Gem::Requirement
248
248
  none: false
249
249
  requirements:
250
250
  - - ! '>='
@@ -252,10 +252,10 @@ dependencies:
252
252
  version: '0'
253
253
  type: :development
254
254
  prerelease: false
255
- version_requirements: *2157398660
255
+ version_requirements: *2161055780
256
256
  - !ruby/object:Gem::Dependency
257
257
  name: timecop
258
- requirement: &2157398240 !ruby/object:Gem::Requirement
258
+ requirement: &2161055360 !ruby/object:Gem::Requirement
259
259
  none: false
260
260
  requirements:
261
261
  - - ! '>='
@@ -263,7 +263,7 @@ dependencies:
263
263
  version: '0'
264
264
  type: :development
265
265
  prerelease: false
266
- version_requirements: *2157398240
266
+ version_requirements: *2161055360
267
267
  description: A Ruby wrapper and CLI for to interact with Cloudfactory.com REST API
268
268
  email:
269
269
  - info@cloudfactory.com
@@ -369,12 +369,12 @@ post_install_message: ! " ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁
369
369
  your API key\n http://cloudfactory.com/users/sign_up\n Get API key from welcome
370
370
  email or http://cloudfactory.com/account#settings\n\n 2. Login with your credentials\n
371
371
  \ > cf login\n \n 3. Generate your first assembly line...\n > cf line generate
372
- <line-title>\n\n 4. Edit the generated line.yml to design your perfect assembly
373
- line\n See http://developers.cloudfactory.com/lines/yaml.html\n\n 5. Create your
374
- line in CloudFactory\n > cf line create\n\n 6. Do a test production run in the
375
- sandbox first...\n > cf production start TITLE -i=INPUT_DATA.CSV\n\n 7. Go live!
376
- Send your production run to real workers...\n > cf production start TITLE -i=INPUT_DATA.CSV
377
- --live\n \n ------------------------------------------------------------------------------\n
372
+ <line-title>\n \n 4. Go into generated line directory\n > cd <line-title>\n \n
373
+ \ 5. Edit the generated line.yml to design your perfect assembly line\n See http://developers.cloudfactory.com/lines/yaml.html\n
374
+ \ \n 6. Create your line in CloudFactory\n > cf line create\n\n 7. Do a test
375
+ production run in the sandbox first...\n > cf production start TITLE -i=INPUT_DATA.CSV\n\n
376
+ \ 8. Go live! Send your production run to real workers...\n > cf production start
377
+ TITLE -i=INPUT_DATA.CSV --live\n \n ------------------------------------------------------------------------------\n
378
378
  \n Follow @thecloudfactory on Twitter for announcements, updates, and news.\n https://twitter.com/thecloudfactory\n\n
379
379
  \ Add your project or organization to the apps wiki!\n https://github.com/sprout/cloudfactory_ruby/wiki/Apps\n
380
380
  \ \n ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁