naf 2.1.12 → 2.1.13
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +4 -3
- data/RELEASE_NOTES.rdoc +17 -4
- data/app/assets/images/download.png +0 -0
- data/app/assets/javascripts/dataTablesTemplates/jobs.js +37 -0
- data/app/controllers/naf/historical_jobs_controller.rb +30 -0
- data/app/controllers/naf/log_parsers_controller.rb +9 -0
- data/app/helpers/naf/application_helper.rb +1 -1
- data/app/models/logical/naf/application_schedule.rb +7 -3
- data/app/models/logical/naf/log_parser/base.rb +1 -0
- data/app/models/logical/naf/log_parser/job.rb +4 -3
- data/app/models/logical/naf/log_parser/job_downloader.rb +156 -0
- data/app/models/logical/naf/log_parser/runner.rb +4 -3
- data/app/models/logical/naf/metric_sender.rb +62 -0
- data/app/models/process/naf/database_models_cleanup.rb +91 -0
- data/app/models/process/naf/runner.rb +52 -35
- data/app/views/naf/historical_jobs/_button_control.html.erb +64 -0
- data/app/views/naf/historical_jobs/index.json.erb +26 -5
- data/app/views/naf/historical_jobs/show.html.erb +20 -29
- data/app/views/naf/log_viewer/_job_log_download_button.html.erb +11 -0
- data/app/views/naf/log_viewer/_job_logs.html.erb +3 -0
- data/app/views/naf/log_viewer/_log_display.html.erb +4 -4
- data/app/views/naf/log_viewer/_log_layout.html.erb +5 -0
- data/config/routes.rb +4 -0
- data/lib/naf.rb +8 -0
- data/lib/naf/configuration.rb +5 -1
- data/lib/naf/version.rb +1 -1
- data/naf.gemspec +5 -2
- data/spec/controllers/naf/log_parsers_controller_spec.rb +35 -0
- data/spec/models/logical/naf/application_schedule_spec.rb +41 -0
- data/spec/models/logical/naf/construction_zone/boss_spec.rb +5 -0
- data/spec/models/logical/naf/construction_zone/foreman_spec.rb +6 -3
- data/spec/models/logical/naf/job_downloader_spec.rb +72 -0
- data/spec/models/logical/naf/job_statuses/errored_spec.rb +33 -0
- data/spec/models/logical/naf/job_statuses/finished_less_minute_spec.rb +33 -0
- data/spec/models/logical/naf/job_statuses/finished_spec.rb +33 -0
- data/spec/models/logical/naf/job_statuses/queued_spec.rb +34 -0
- data/spec/models/logical/naf/job_statuses/running_spec.rb +37 -0
- data/spec/models/logical/naf/job_statuses/terminated_spec.rb +33 -0
- data/spec/models/logical/naf/job_statuses/waiting_spec.rb +33 -0
- metadata +80 -6
@@ -137,6 +137,18 @@
|
|
137
137
|
"#", { class: "terminate" }
|
138
138
|
%></td>
|
139
139
|
</tr>
|
140
|
+
<% elsif !['Terminating'].include?(@logical_job.status) -%>
|
141
|
+
<tr>
|
142
|
+
<td>Enqueue Application</td>
|
143
|
+
<td><% params = { class: "re-enqueue", content: "#{naf.historical_jobs_path}/reenqueue", id: @historical_job.id } %>
|
144
|
+
<% if @historical_job.application_id.present? -%>
|
145
|
+
<% params[:app_id] = @historical_job.application.id %>
|
146
|
+
<% end %>
|
147
|
+
<%= link_to image_tag('control_play_blue.png',
|
148
|
+
class: 'action',
|
149
|
+
title: "Re-enqueue one instance of job #{@historical_job.id}"),
|
150
|
+
"#", params %>
|
151
|
+
</td>
|
140
152
|
<% end %>
|
141
153
|
</tbody>
|
142
154
|
</table>
|
@@ -163,8 +175,12 @@
|
|
163
175
|
</tbody>
|
164
176
|
</table>
|
165
177
|
</br>
|
166
|
-
<%= render partial: 'naf/log_viewer/log_layout', locals: {
|
167
|
-
|
178
|
+
<%= render partial: 'naf/log_viewer/log_layout', locals: {
|
179
|
+
record_id: @historical_job.id,
|
180
|
+
record_type: 'job',
|
181
|
+
runner_name: @logical_job.runner,
|
182
|
+
server: @logical_job.started_on_machine.try(:server_name),
|
183
|
+
status: @logical_job.status } %>
|
168
184
|
</div>
|
169
185
|
<% end %>
|
170
186
|
|
@@ -177,30 +193,5 @@
|
|
177
193
|
logs_url: "#{http_protocol}#{@logical_job.runner}#{naf.logs_log_parsers_path}",
|
178
194
|
record_type: 'job' } %>
|
179
195
|
|
180
|
-
|
181
|
-
|
182
|
-
jQuery(document).ready(function () {
|
183
|
-
jQuery(document).delegate('.terminate', "click", function(){
|
184
|
-
var answer = confirm("You are terminating this job. Are you sure you want to do this?");
|
185
|
-
if (!answer) {
|
186
|
-
return false;
|
187
|
-
}
|
188
|
-
var id = <%= @historical_job.id %>;
|
189
|
-
jQuery.ajax({
|
190
|
-
url: id,
|
191
|
-
type:'POST',
|
192
|
-
dataType:'json',
|
193
|
-
data:{ "historical_job[request_to_terminate]": 1, "historical_job_id": id, "_method": "put" },
|
194
|
-
success:function (data) {
|
195
|
-
if (data.success) {
|
196
|
-
var title = data.title ? data.title : data.command
|
197
|
-
jQuery("<p id='notice'>A Job " + title + " was terminated!</p>").
|
198
|
-
appendTo('#flash_message').slideDown().delay(5000).slideUp();
|
199
|
-
setTimeout('window.location.reload()', 5600);
|
200
|
-
}
|
201
|
-
}
|
202
|
-
});
|
203
|
-
});
|
204
|
-
});
|
205
|
-
</script>
|
206
|
-
<% end %>
|
196
|
+
<!-- This partial controls terminate and re-enqueue links -->
|
197
|
+
<% render partial: 'button_control', locals: { historical_job_id: @historical_job.id } %>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<% style_text = "vertical-align: bottom;" %>
|
2
|
+
<% if status == 'Queued' || server.blank?
|
3
|
+
style_text << " display: none;"
|
4
|
+
end %>
|
5
|
+
<%= button_tag(style: "#{style_text}") do
|
6
|
+
link_to 'Download',
|
7
|
+
link_path,
|
8
|
+
style: "color: black;"
|
9
|
+
end
|
10
|
+
%>
|
11
|
+
</button>
|
@@ -48,6 +48,9 @@
|
|
48
48
|
</br>
|
49
49
|
|
50
50
|
<%= submit_tag("Search the logs", id: 'log_search_submit') %>
|
51
|
+
<%= render partial: 'job_log_download_button', locals: { server: @job.started_on_machine.try(:server_name),
|
52
|
+
status: logical_job.status,
|
53
|
+
link_path: "#{http_protocol}#{logical_job.runner}#{naf.download_log_parsers_path}?record_id=#{@job.id}&record_type=job" } %>
|
51
54
|
|
52
55
|
<%= link_to 'Back to Job', { controller: 'historical_jobs', action: 'show', id: @job.id } %>
|
53
56
|
</div>
|
@@ -129,7 +129,7 @@
|
|
129
129
|
jQuery('#stdout').text('')
|
130
130
|
jQuery('#stdout').append(logs);
|
131
131
|
if(jQuery('#stdout').text() == '') {
|
132
|
-
logs = "No logs were found for this search query
|
132
|
+
logs = "<pre style='display: inline; word-wrap: break-word;'>No logs were found for this search query!</pre><br>";
|
133
133
|
setAutoScrollOff();
|
134
134
|
}
|
135
135
|
jQuery("#stdout").scrollTop(jQuery('#stdout')[0].scrollHeight);
|
@@ -138,7 +138,7 @@
|
|
138
138
|
}
|
139
139
|
else{
|
140
140
|
if(logs == '' && jQuery('#stdout')[0].children.length == 0) {
|
141
|
-
logs = "
|
141
|
+
logs = "<span><pre style='display: inline; word-wrap: break-word;'>No logs were found!</pre><br></span>";
|
142
142
|
setAutoScrollOff();
|
143
143
|
}
|
144
144
|
|
@@ -165,10 +165,10 @@
|
|
165
165
|
}
|
166
166
|
},
|
167
167
|
error: function(response) {
|
168
|
-
message = '
|
168
|
+
message = '<span><pre style="display: inline; word-wrap: break-word;">Failed to retrieve ' + '<%= record_type %>' + '(' +
|
169
169
|
'<%= record_id %>' + ') logs from ' + '<%= logs_url %>'.match(/^https?\:\/\/([^\/?#]+)/).pop() + '. Please refer to ' +
|
170
170
|
'Naf FAQs on the' + ' wiki'.link('https://github.com/fiksu/naf/wiki/Frequently-Asked-Questions') +
|
171
|
-
' for further information
|
171
|
+
' for further information.</pre><br></span>';
|
172
172
|
|
173
173
|
jQuery('#stdout').prepend(message);
|
174
174
|
}
|
@@ -47,6 +47,11 @@
|
|
47
47
|
<%= link_to 'Auto Scroll (ON)', '#', id: :auto_scroll %>
|
48
48
|
</br></br>
|
49
49
|
<%= submit_tag("Search the logs", id: 'log_search_submit') %>
|
50
|
+
<% if record_type == 'job' %>
|
51
|
+
<%= render partial: 'naf/log_viewer/job_log_download_button', locals: {
|
52
|
+
server: server, status: status,
|
53
|
+
link_path: "#{http_protocol}#{runner_name}#{naf.download_log_parsers_path}?record_id=#{record_id}&record_type=job" } %>
|
54
|
+
<% end %>
|
50
55
|
<%= link_to 'Full Screen',
|
51
56
|
{ controller: 'log_viewer', action: 'index', record_id: record_id, record_type: record_type },
|
52
57
|
{ class: 'full_screen' } %>
|
data/config/routes.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
Naf::Engine.routes.draw do
|
2
2
|
resources :historical_jobs, except: [:edit] do
|
3
|
+
collection do
|
4
|
+
post :reenqueue
|
5
|
+
end
|
3
6
|
resources :historical_job_affinity_tabs, except: [:destroy]
|
4
7
|
end
|
5
8
|
|
@@ -31,6 +34,7 @@ Naf::Engine.routes.draw do
|
|
31
34
|
resources :log_parsers, only: [] do
|
32
35
|
collection do
|
33
36
|
get :logs
|
37
|
+
get :download
|
34
38
|
end
|
35
39
|
end
|
36
40
|
resources :status, only: [:index]
|
data/lib/naf.rb
CHANGED
@@ -45,6 +45,14 @@ module Naf
|
|
45
45
|
configuration.simple_cluster_authenticator_cookie_expiration_time
|
46
46
|
end
|
47
47
|
|
48
|
+
def metric_tags
|
49
|
+
configuration.metric_tags
|
50
|
+
end
|
51
|
+
|
52
|
+
def metric_send_delay
|
53
|
+
configuration.metric_send_delay
|
54
|
+
end
|
55
|
+
|
48
56
|
def using_another_database?
|
49
57
|
model_class != ActiveRecord::Base
|
50
58
|
end
|
data/lib/naf/configuration.rb
CHANGED
@@ -8,7 +8,9 @@ module Naf
|
|
8
8
|
:layout,
|
9
9
|
:default_page_options,
|
10
10
|
:api_domain_cookie_name,
|
11
|
-
:simple_cluster_authenticator_cookie_expiration_time
|
11
|
+
:simple_cluster_authenticator_cookie_expiration_time,
|
12
|
+
:metric_tags,
|
13
|
+
:metric_send_delay
|
12
14
|
|
13
15
|
def initialize
|
14
16
|
@model_class = "::ActiveRecord::Base"
|
@@ -19,6 +21,8 @@ module Naf
|
|
19
21
|
@api_controller_class = "Naf::ApiSimpleClusterAuthenticatorApplicationController"
|
20
22
|
@simple_cluster_authenticator_cookie_expiration_time = 1.week
|
21
23
|
@api_domain_cookie_name = "naf_#{Rails.application.class.parent.name.underscore}"
|
24
|
+
@metric_tags = ["#{Rails.env}"]
|
25
|
+
@metric_send_delay = 120
|
22
26
|
end
|
23
27
|
|
24
28
|
end
|
data/lib/naf/version.rb
CHANGED
data/naf.gemspec
CHANGED
@@ -8,7 +8,7 @@ Gem::Specification.new do |s|
|
|
8
8
|
s.name = 'naf'
|
9
9
|
s.version = Naf::VERSION
|
10
10
|
s.license = 'New BSD License'
|
11
|
-
s.date = '2014-
|
11
|
+
s.date = '2014-07-08'
|
12
12
|
s.summary = 'Creates infrastructure for a customizable and robust Postgres-backed script scheduling/running'
|
13
13
|
s.description = 'A cloud based distributed cron, application framework and operations console. Naf works as a distributed script running ' +
|
14
14
|
'system that provides scheduling, logging, alarming, machine redundancy, and the ability to set constraint during script execution'
|
@@ -24,8 +24,11 @@ Gem::Specification.new do |s|
|
|
24
24
|
s.add_dependency 'jquery-rails'
|
25
25
|
s.add_dependency 'will_paginate'
|
26
26
|
s.add_dependency 'facter', '~> 1.7.5'
|
27
|
+
s.add_dependency 'aws-sdk', '>= 1.1.0'
|
28
|
+
s.add_dependency 'yajl-ruby', '>= 1.1.0'
|
29
|
+
s.add_dependency 'dogstatsd-ruby', '>= 1.2.0'
|
27
30
|
s.add_development_dependency 'pg'
|
28
|
-
s.add_development_dependency 'rspec-rails'
|
31
|
+
s.add_development_dependency 'rspec-rails', '~> 2.14.0'
|
29
32
|
s.add_development_dependency 'factory_girl_rails', '~> 4.0.0'
|
30
33
|
s.add_development_dependency 'awesome_print'
|
31
34
|
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Naf
|
4
|
+
|
5
|
+
describe LogParsersController do
|
6
|
+
|
7
|
+
before do
|
8
|
+
Logical::Naf::LogParser::JobDownloader.any_instance.stub(:logs_for_download).and_return("Test Log String")
|
9
|
+
end
|
10
|
+
|
11
|
+
it "raises no exceptions" do
|
12
|
+
assert_nothing_raised do
|
13
|
+
get :download, {'record_id' => 3}
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
it "has a successful response" do
|
18
|
+
get :download, {'record_id' => 3}
|
19
|
+
assert_response(:success)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "returns the correct string" do
|
23
|
+
get :download, {'record_id' => 3}
|
24
|
+
expect(response.body).to eql("Test Log String\n")
|
25
|
+
end
|
26
|
+
|
27
|
+
it "has the right disposition of attachment" do
|
28
|
+
get :download, {'record_id' => 3}
|
29
|
+
disposition = response.header["Content-Disposition"]
|
30
|
+
expect(disposition.include?("attachment")).to be_true
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Logical
|
4
|
+
module Naf
|
5
|
+
|
6
|
+
describe ApplicationSchedule do
|
7
|
+
|
8
|
+
describe '#exact_time_of_day' do
|
9
|
+
|
10
|
+
#----------------
|
11
|
+
# *** Methods ***
|
12
|
+
#++++++++++++++++
|
13
|
+
|
14
|
+
def update_schedule(run_interval)
|
15
|
+
schedule.run_interval = run_interval
|
16
|
+
schedule.save
|
17
|
+
|
18
|
+
::Logical::Naf::ApplicationSchedule.new(schedule)
|
19
|
+
end
|
20
|
+
|
21
|
+
#------------------------
|
22
|
+
# *** Shared Examples ***
|
23
|
+
#++++++++++++++++++++++++
|
24
|
+
|
25
|
+
shared_examples 'displays the hour correctly' do |run_interval, time|
|
26
|
+
it { update_schedule(run_interval).exact_time_of_day.should == time }
|
27
|
+
end
|
28
|
+
|
29
|
+
let!(:schedule) { FactoryGirl.create(:schedule_base) }
|
30
|
+
|
31
|
+
it_should_behave_like 'displays the hour correctly', 10, '12:10 AM'
|
32
|
+
it_should_behave_like 'displays the hour correctly', 480, '08:00 AM'
|
33
|
+
it_should_behave_like 'displays the hour correctly', 2880, '12:00 AM'
|
34
|
+
it_should_behave_like 'displays the hour correctly', 20160, '12:00 AM'
|
35
|
+
it_should_behave_like 'displays the hour correctly', 46080, '12:00 AM'
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
@@ -32,6 +32,11 @@ module Logical::Naf::ConstructionZone
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
+
before do
|
36
|
+
::Naf::HistoricalJob.delete_all
|
37
|
+
::Naf::ApplicationType.all
|
38
|
+
end
|
39
|
+
|
35
40
|
describe '#enqueue_application' do
|
36
41
|
let(:application) { FactoryGirl.create(:application) }
|
37
42
|
let(:prereq) { FactoryGirl.create(:job) }
|
@@ -44,13 +44,16 @@ module Logical::Naf::ConstructionZone
|
|
44
44
|
describe 'run group restriction is set to limited per machine' do
|
45
45
|
let!(:machine) { FactoryGirl.create(:machine) }
|
46
46
|
let(:historical_job) { FactoryGirl.create(:job, application_run_group_name: 'test') }
|
47
|
-
let(:tab) { FactoryGirl.create(:machine_job_affinity_tab, historical_job_id: historical_job.id) }
|
47
|
+
let!(:tab) { FactoryGirl.create(:machine_job_affinity_tab, historical_job_id: historical_job.id) }
|
48
48
|
|
49
49
|
before do
|
50
|
-
FactoryGirl.create(:queued_job, application_run_group_name: 'test',
|
50
|
+
FactoryGirl.create(:queued_job, application_run_group_name: 'test',
|
51
|
+
id: historical_job.id,
|
52
|
+
historical_job: historical_job)
|
51
53
|
FactoryGirl.create(:running_job_base, application_run_group_name: 'test',
|
52
54
|
started_on_machine_id: machine.id,
|
53
|
-
|
55
|
+
historical_job: historical_job,
|
56
|
+
id: historical_job.id)
|
54
57
|
end
|
55
58
|
|
56
59
|
it 'return false when application does not have affinity associated with machine' do
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Logical
|
4
|
+
module Naf
|
5
|
+
module LogParser
|
6
|
+
describe JobDownloader do
|
7
|
+
# Create a test file, making sure to not overwrite a current file.
|
8
|
+
|
9
|
+
let!(:test_record_id) { 3 }
|
10
|
+
let!(:test_file_path) { "#{::Naf::PREFIX_PATH}/#{::Naf.schema_name}/jobs/#{test_record_id}" }
|
11
|
+
let!(:test_file_name) { "1_20140613_161535.json" }
|
12
|
+
let!(:test_file_text) { "{\n" +
|
13
|
+
" \"line_number\": 1,\n" +
|
14
|
+
" \"output_time\": \"2014-06-13 16:15:35.689\",\n" +
|
15
|
+
" \"message\": \"140613 12:15:35.689 pid=6020 jid=3 Process::Naf::LogArchiver INFO Starting to save files to s3...\"\n" +
|
16
|
+
"}" }
|
17
|
+
let!(:test_file_output) { "1 2014-06-13 16:15:35.689: 140613 12:15:35.689 pid=6020 jid=3 Process::Naf::LogArchiver INFO Starting to save files to s3...\n" }
|
18
|
+
let!(:segments_to_reset) { {} }
|
19
|
+
let!(:file_preserved) { false }
|
20
|
+
|
21
|
+
before() do
|
22
|
+
# Create a file/directory for example log. If directory exists, move it and save it
|
23
|
+
segments_to_reset = {}
|
24
|
+
total_path = ""
|
25
|
+
file_preserved = false
|
26
|
+
|
27
|
+
test_file_path.split("/").each do |segment|
|
28
|
+
unless segment == ""
|
29
|
+
segments_to_reset[segment] = false
|
30
|
+
unless File.exists?(total_path + segment + "/")
|
31
|
+
Dir.mkdir(total_path + segment + "/")
|
32
|
+
segments_to_reset[segment] = true
|
33
|
+
end
|
34
|
+
total_path += segment + "/"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
if File.exists?("#{test_file_path}/#{test_file_name}")
|
39
|
+
FileUtils.mv("#{test_file_path}/#{test_file_name}", "#{test_file_path}/#{test_file_name}-preserving")
|
40
|
+
file_preserved = true
|
41
|
+
end
|
42
|
+
|
43
|
+
File.open("#{test_file_path}/#{test_file_name}", 'w') { |file| file.write(test_file_text) }
|
44
|
+
end
|
45
|
+
|
46
|
+
after() do
|
47
|
+
# Delete the example log file. If a directory was saved before, move it back
|
48
|
+
File.delete("#{test_file_path}/#{test_file_name}")
|
49
|
+
|
50
|
+
if file_preserved
|
51
|
+
FileUtils.mv("#{test_file_path}/#{test_file_name}-preserving", "#{test_file_path}/#{test_file_name}")
|
52
|
+
end
|
53
|
+
|
54
|
+
current_path = test_file_path
|
55
|
+
test_file_path.split("/").reverse_each do |segment|
|
56
|
+
if segments_to_reset[segment]
|
57
|
+
Dir.rmdir(current_path)
|
58
|
+
current_path = current_path[0..-(segment.size + 2)]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
it "returns the correct log" do
|
65
|
+
job_log_downloader = JobDownloader.new({ 'record_id' => test_record_id })
|
66
|
+
job_log_downloader.logs_for_download.should eql(test_file_output)
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Logical
|
4
|
+
module Naf
|
5
|
+
module JobStatuses
|
6
|
+
|
7
|
+
describe Errored do
|
8
|
+
|
9
|
+
context "no conditions" do
|
10
|
+
|
11
|
+
let!(:conditions) { "" }
|
12
|
+
|
13
|
+
it "returns executable query" do
|
14
|
+
expect { ActiveRecord::Base.connection.execute(Errored.all(conditions)) }.to_not raise_error
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
context "with conditions" do
|
20
|
+
|
21
|
+
let!(:conditions) { "TEST STRING" }
|
22
|
+
|
23
|
+
it "adds conditions to returned sql string" do
|
24
|
+
expect(Errored.all(conditions).include?(conditions)).to be_true
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Logical
|
4
|
+
module Naf
|
5
|
+
module JobStatuses
|
6
|
+
|
7
|
+
describe FinishedLessMinute do
|
8
|
+
|
9
|
+
context "no conditions" do
|
10
|
+
|
11
|
+
let!(:conditions) { "" }
|
12
|
+
|
13
|
+
it "returns executable query" do
|
14
|
+
expect { ActiveRecord::Base.connection.execute(FinishedLessMinute.all(conditions)) }.to_not raise_error
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
context "with conditions" do
|
20
|
+
|
21
|
+
let!(:conditions) { "TEST STRING" }
|
22
|
+
|
23
|
+
it "adds conditions to returned sql string" do
|
24
|
+
expect(FinishedLessMinute.all(conditions).include?(conditions)).to be_true
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|