bootstrap-timepicker-rails-addon 0.3.0 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +18 -9
- data/lib/bootstrap-timepicker-rails-addon/version.rb +1 -1
- data/vendor/assets/javascripts/bootstrap-timepicker.js +145 -89
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d53e7c7b6dc408b23358a61a8a105affdd3a1894
|
4
|
+
data.tar.gz: fafa6ddbf978c829658e6ff259686b3afd9eb50b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0591e472cfe6a3dc622a12e67fb6ea46ce74a22afb0118fd008743ada85f54cfe5c935d2bbaa664526d2960a4b85791208d4f9735b69465763c220441f14d26b
|
7
|
+
data.tar.gz: d721ffc180649f5c0953fe8542d87b92172dd43d992c5945bfc6833294d67db60df60928720d6785e04deffae2d785e168c33db0cf60e057d3f140157ff9983b
|
data/README.md
CHANGED
@@ -1,19 +1,28 @@
|
|
1
1
|
# Bootstrap::Timepicker::Rails::Addon
|
2
2
|
This is the GEMified version of [bootstrap-timepicker](https://github.com/jdewit/bootstrap-timepicker)
|
3
3
|
|
4
|
-
bootstrap-timepicker-rails-addon project integrates Timepicker for Twitter Bootstrap with Rails 3 and 4 assets pipeline.
|
4
|
+
bootstrap-timepicker-rails-addon project integrates Timepicker for Twitter Bootstrap 3 with Rails 3 and 4 assets pipeline.
|
5
5
|
|
6
6
|
## Installation
|
7
7
|
|
8
8
|
Add this line to your application's Gemfile:
|
9
9
|
|
10
|
+
1) if you used Bootstrap 3 version,
|
11
|
+
```ruby
|
12
|
+
gem 'bootstrap-sass', '~> 3.3.5'
|
13
|
+
gem 'bootstrap-timepicker-rails-addon', '~> 0.5.1'
|
14
|
+
```
|
15
|
+
|
16
|
+
2) if you used Bootstrap 2 version,
|
17
|
+
```ruby
|
10
18
|
gem 'bootstrap-sass', '~> 2.3.2.0'
|
11
|
-
gem 'bootstrap-timepicker-rails-addon'
|
19
|
+
gem 'bootstrap-timepicker-rails-addon', '0.3.0'
|
20
|
+
```
|
12
21
|
|
13
|
-
Or you can install from latest build:
|
22
|
+
Or you can install from latest build(only support Bootstrap 3 version in master branch):
|
14
23
|
|
15
24
|
```ruby
|
16
|
-
gem 'bootstrap-sass', '~>
|
25
|
+
gem 'bootstrap-sass', '~> 3.3.5'
|
17
26
|
gem 'bootstrap-timepicker-rails-addon', :require => 'bootstrap-timepicker-rails-addon',
|
18
27
|
:git => 'git://github.com/ywjno/bootstrap-timepicker-rails-addon.git'
|
19
28
|
```
|
@@ -32,9 +41,9 @@ Add this line to app/assets/javascripts/application.js
|
|
32
41
|
|
33
42
|
//= require bootstrap-timepicker
|
34
43
|
|
35
|
-
Add this line to app/assets/stylesheets/application.css
|
44
|
+
Add this line to app/assets/stylesheets/application.css.scss
|
36
45
|
|
37
|
-
|
46
|
+
@import "bootstrap-timepicker";
|
38
47
|
|
39
48
|
Just call timepicker() with any selector in view.
|
40
49
|
|
@@ -45,9 +54,9 @@ $('#timepicker').timepicker();
|
|
45
54
|
And here is the html code sample.
|
46
55
|
|
47
56
|
```html
|
48
|
-
<div class="input-
|
49
|
-
<input id="
|
50
|
-
<span class="
|
57
|
+
<div class="input-group bootstrap-timepicker timepicker">
|
58
|
+
<input id="timepicker1" type="text" class="form-control input-small">
|
59
|
+
<span class="input-group-addon"><i class="glyphicon glyphicon-time"></i></span>
|
51
60
|
</div>
|
52
61
|
```
|
53
62
|
|
@@ -8,7 +8,7 @@
|
|
8
8
|
* For the full copyright and license information, please view the LICENSE
|
9
9
|
* file that was distributed with this source code.
|
10
10
|
*/
|
11
|
-
(function($, window, document
|
11
|
+
(function($, window, document) {
|
12
12
|
'use strict';
|
13
13
|
|
14
14
|
// TIMEPICKER PUBLIC CLASS DEFINITION
|
@@ -23,14 +23,26 @@
|
|
23
23
|
this.modalBackdrop = options.modalBackdrop;
|
24
24
|
this.orientation = options.orientation;
|
25
25
|
this.secondStep = options.secondStep;
|
26
|
+
this.snapToStep = options.snapToStep;
|
26
27
|
this.showInputs = options.showInputs;
|
27
28
|
this.showMeridian = options.showMeridian;
|
28
29
|
this.showSeconds = options.showSeconds;
|
29
30
|
this.template = options.template;
|
30
31
|
this.appendWidgetTo = options.appendWidgetTo;
|
31
32
|
this.showWidgetOnAddonClick = options.showWidgetOnAddonClick;
|
32
|
-
this.maxHours = options.maxHours
|
33
|
-
|
33
|
+
this.maxHours = options.maxHours;
|
34
|
+
this.explicitMode = options.explicitMode; // If true 123 = 1:23, 12345 = 1:23:45, else invalid.
|
35
|
+
|
36
|
+
this.handleDocumentClick = function (e) {
|
37
|
+
var self = e.data.scope;
|
38
|
+
// This condition was inspired by bootstrap-datepicker.
|
39
|
+
// The element the timepicker is invoked on is the input but it has a sibling for addon/button.
|
40
|
+
if (!(self.$element.parent().find(e.target).length ||
|
41
|
+
self.$widget.is(e.target) ||
|
42
|
+
self.$widget.find(e.target).length)) {
|
43
|
+
self.hideWidget();
|
44
|
+
}
|
45
|
+
};
|
34
46
|
this._init();
|
35
47
|
};
|
36
48
|
|
@@ -40,8 +52,8 @@
|
|
40
52
|
_init: function() {
|
41
53
|
var self = this;
|
42
54
|
|
43
|
-
if (this.showWidgetOnAddonClick && (this.$element.parent().hasClass('input-
|
44
|
-
this.$element.parent('.input-
|
55
|
+
if (this.showWidgetOnAddonClick && (this.$element.parent().hasClass('input-group') && this.$element.parent().hasClass('bootstrap-timepicker'))) {
|
56
|
+
this.$element.parent('.input-group.bootstrap-timepicker').find('.input-group-addon').on({
|
45
57
|
'click.timepicker': $.proxy(this.showWidget, this)
|
46
58
|
});
|
47
59
|
this.$element.on({
|
@@ -120,7 +132,7 @@
|
|
120
132
|
}
|
121
133
|
} else {
|
122
134
|
if (this.hour <= 0) {
|
123
|
-
this.hour = this.maxHours;
|
135
|
+
this.hour = this.maxHours - 1;
|
124
136
|
} else {
|
125
137
|
this.hour--;
|
126
138
|
}
|
@@ -156,14 +168,28 @@
|
|
156
168
|
},
|
157
169
|
|
158
170
|
elementKeydown: function(e) {
|
159
|
-
switch (e.
|
171
|
+
switch (e.which) {
|
160
172
|
case 9: //tab
|
173
|
+
if (e.shiftKey) {
|
174
|
+
if (this.highlightedUnit === 'hour') {
|
175
|
+
break;
|
176
|
+
}
|
177
|
+
this.highlightPrevUnit();
|
178
|
+
} else if ((this.showMeridian && this.highlightedUnit === 'meridian') || (this.showSeconds && this.highlightedUnit === 'second') || (!this.showMeridian && !this.showSeconds && this.highlightedUnit ==='minute')) {
|
179
|
+
break;
|
180
|
+
} else {
|
181
|
+
this.highlightNextUnit();
|
182
|
+
}
|
183
|
+
e.preventDefault();
|
184
|
+
this.updateFromElementVal();
|
185
|
+
break;
|
161
186
|
case 27: // escape
|
162
187
|
this.updateFromElementVal();
|
163
188
|
break;
|
164
189
|
case 37: // left arrow
|
165
190
|
e.preventDefault();
|
166
191
|
this.highlightPrevUnit();
|
192
|
+
this.updateFromElementVal();
|
167
193
|
break;
|
168
194
|
case 38: // up arrow
|
169
195
|
e.preventDefault();
|
@@ -190,6 +216,7 @@
|
|
190
216
|
case 39: // right arrow
|
191
217
|
e.preventDefault();
|
192
218
|
this.highlightNextUnit();
|
219
|
+
this.updateFromElementVal();
|
193
220
|
break;
|
194
221
|
case 40: // down arrow
|
195
222
|
e.preventDefault();
|
@@ -349,7 +376,7 @@
|
|
349
376
|
this.$widget.removeClass('open');
|
350
377
|
}
|
351
378
|
|
352
|
-
$(document).off('mousedown.timepicker, touchend.timepicker');
|
379
|
+
$(document).off('mousedown.timepicker, touchend.timepicker', this.handleDocumentClick);
|
353
380
|
|
354
381
|
this.isOpen = false;
|
355
382
|
// show/hide approach taken by datepicker
|
@@ -433,15 +460,15 @@
|
|
433
460
|
|
434
461
|
this.highlightedUnit = 'hour';
|
435
462
|
|
436
|
-
|
437
|
-
|
463
|
+
if ($element.setSelectionRange) {
|
464
|
+
setTimeout(function() {
|
438
465
|
if (self.hour < 10) {
|
439
466
|
$element.setSelectionRange(0,1);
|
440
467
|
} else {
|
441
468
|
$element.setSelectionRange(0,2);
|
442
469
|
}
|
443
|
-
|
444
|
-
|
470
|
+
}, 0);
|
471
|
+
}
|
445
472
|
},
|
446
473
|
|
447
474
|
highlightMinute: function() {
|
@@ -450,15 +477,15 @@
|
|
450
477
|
|
451
478
|
this.highlightedUnit = 'minute';
|
452
479
|
|
453
|
-
|
454
|
-
|
480
|
+
if ($element.setSelectionRange) {
|
481
|
+
setTimeout(function() {
|
455
482
|
if (self.hour < 10) {
|
456
483
|
$element.setSelectionRange(2,4);
|
457
484
|
} else {
|
458
485
|
$element.setSelectionRange(3,5);
|
459
486
|
}
|
460
|
-
|
461
|
-
|
487
|
+
}, 0);
|
488
|
+
}
|
462
489
|
},
|
463
490
|
|
464
491
|
highlightSecond: function() {
|
@@ -467,15 +494,15 @@
|
|
467
494
|
|
468
495
|
this.highlightedUnit = 'second';
|
469
496
|
|
470
|
-
|
471
|
-
|
497
|
+
if ($element.setSelectionRange) {
|
498
|
+
setTimeout(function() {
|
472
499
|
if (self.hour < 10) {
|
473
500
|
$element.setSelectionRange(5,7);
|
474
501
|
} else {
|
475
502
|
$element.setSelectionRange(6,8);
|
476
503
|
}
|
477
|
-
|
478
|
-
|
504
|
+
}, 0);
|
505
|
+
}
|
479
506
|
},
|
480
507
|
|
481
508
|
highlightMeridian: function() {
|
@@ -484,25 +511,25 @@
|
|
484
511
|
|
485
512
|
this.highlightedUnit = 'meridian';
|
486
513
|
|
487
|
-
|
488
|
-
|
489
|
-
|
514
|
+
if ($element.setSelectionRange) {
|
515
|
+
if (this.showSeconds) {
|
516
|
+
setTimeout(function() {
|
490
517
|
if (self.hour < 10) {
|
491
518
|
$element.setSelectionRange(8,10);
|
492
519
|
} else {
|
493
520
|
$element.setSelectionRange(9,11);
|
494
521
|
}
|
495
|
-
|
496
|
-
|
497
|
-
|
522
|
+
}, 0);
|
523
|
+
} else {
|
524
|
+
setTimeout(function() {
|
498
525
|
if (self.hour < 10) {
|
499
526
|
$element.setSelectionRange(5,7);
|
500
527
|
} else {
|
501
528
|
$element.setSelectionRange(6,8);
|
502
529
|
}
|
503
|
-
|
504
|
-
|
505
|
-
|
530
|
+
}, 0);
|
531
|
+
}
|
532
|
+
}
|
506
533
|
},
|
507
534
|
|
508
535
|
incrementHour: function() {
|
@@ -514,7 +541,7 @@
|
|
514
541
|
this.hour = 0;
|
515
542
|
}
|
516
543
|
}
|
517
|
-
if (this.hour === this.maxHours) {
|
544
|
+
if (this.hour === this.maxHours - 1) {
|
518
545
|
this.hour = 0;
|
519
546
|
|
520
547
|
return;
|
@@ -607,6 +634,23 @@
|
|
607
634
|
return false;
|
608
635
|
},
|
609
636
|
|
637
|
+
/**
|
638
|
+
* Given a segment value like 43, will round and snap the segment
|
639
|
+
* to the nearest "step", like 45 if step is 15. Segment will
|
640
|
+
* "overflow" to 0 if it's larger than 59 or would otherwise
|
641
|
+
* round up to 60.
|
642
|
+
*/
|
643
|
+
changeToNearestStep: function (segment, step) {
|
644
|
+
if (segment % step === 0) {
|
645
|
+
return segment;
|
646
|
+
}
|
647
|
+
if (Math.round((segment % step) / step)) {
|
648
|
+
return (segment + (step - segment % step)) % 60;
|
649
|
+
} else {
|
650
|
+
return segment - segment % step;
|
651
|
+
}
|
652
|
+
},
|
653
|
+
|
610
654
|
// This method was adapted from bootstrap-datepicker.
|
611
655
|
place : function() {
|
612
656
|
if (this.isInline) {
|
@@ -615,7 +659,7 @@
|
|
615
659
|
var widgetWidth = this.$widget.outerWidth(), widgetHeight = this.$widget.outerHeight(), visualPadding = 10, windowWidth =
|
616
660
|
$(window).width(), windowHeight = $(window).height(), scrollTop = $(window).scrollTop();
|
617
661
|
|
618
|
-
var zIndex = parseInt(this.$element.parents().filter(function() {}).first().css('z-index'), 10) + 10;
|
662
|
+
var zIndex = parseInt(this.$element.parents().filter(function() { return $(this).css('z-index') !== 'auto'; }).first().css('z-index'), 10) + 10;
|
619
663
|
var offset = this.component ? this.component.parent().offset() : this.$element.offset();
|
620
664
|
var height = this.component ? this.component.outerHeight(true) : this.$element.outerHeight(false);
|
621
665
|
var width = this.component ? this.component.outerWidth(true) : this.$element.outerWidth(false);
|
@@ -735,7 +779,8 @@
|
|
735
779
|
return;
|
736
780
|
}
|
737
781
|
|
738
|
-
var
|
782
|
+
var timeMode,
|
783
|
+
timeArray,
|
739
784
|
hour,
|
740
785
|
minute,
|
741
786
|
second,
|
@@ -759,34 +804,38 @@
|
|
759
804
|
}
|
760
805
|
}
|
761
806
|
} else {
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
807
|
+
timeMode = ((/a/i).test(time) ? 1 : 0) + ((/p/i).test(time) ? 2 : 0); // 0 = none, 1 = AM, 2 = PM, 3 = BOTH.
|
808
|
+
if (timeMode > 2) { // If both are present, fail.
|
809
|
+
this.clear();
|
810
|
+
return;
|
766
811
|
}
|
767
812
|
|
768
|
-
|
769
|
-
|
770
|
-
timeArray = time.split(':');
|
813
|
+
timeArray = time.replace(/[^0-9\:]/g, '').split(':');
|
771
814
|
|
772
815
|
hour = timeArray[0] ? timeArray[0].toString() : timeArray.toString();
|
816
|
+
|
817
|
+
if(this.explicitMode && hour.length > 2 && (hour.length % 2) !== 0 ) {
|
818
|
+
this.clear();
|
819
|
+
return;
|
820
|
+
}
|
821
|
+
|
773
822
|
minute = timeArray[1] ? timeArray[1].toString() : '';
|
774
823
|
second = timeArray[2] ? timeArray[2].toString() : '';
|
775
824
|
|
776
|
-
//
|
825
|
+
// adaptive time parsing
|
777
826
|
if (hour.length > 4) {
|
778
|
-
second = hour.
|
827
|
+
second = hour.slice(-2);
|
828
|
+
hour = hour.slice(0, -2);
|
779
829
|
}
|
830
|
+
|
780
831
|
if (hour.length > 2) {
|
781
|
-
minute = hour.
|
782
|
-
hour = hour.
|
832
|
+
minute = hour.slice(-2);
|
833
|
+
hour = hour.slice(0, -2);
|
783
834
|
}
|
835
|
+
|
784
836
|
if (minute.length > 2) {
|
785
|
-
second = minute.
|
786
|
-
minute = minute.
|
787
|
-
}
|
788
|
-
if (second.length > 2) {
|
789
|
-
second = second.substr(2, 2);
|
837
|
+
second = minute.slice(-2);
|
838
|
+
minute = minute.slice(0, -2);
|
790
839
|
}
|
791
840
|
|
792
841
|
hour = parseInt(hour, 10);
|
@@ -803,43 +852,53 @@
|
|
803
852
|
second = 0;
|
804
853
|
}
|
805
854
|
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
hour = 12;
|
811
|
-
}
|
812
|
-
} else {
|
813
|
-
if (hour > this.maxHours) {
|
814
|
-
hour = this.maxHours;
|
815
|
-
} else if (hour < 0) {
|
816
|
-
hour = 0;
|
817
|
-
}
|
818
|
-
if (hour < 13 && meridian === 'PM') {
|
819
|
-
hour = hour + 12;
|
820
|
-
}
|
855
|
+
// Adjust the time based upon unit boundary.
|
856
|
+
// NOTE: Negatives will never occur due to time.replace() above.
|
857
|
+
if (second > 59) {
|
858
|
+
second = 59;
|
821
859
|
}
|
822
860
|
|
823
|
-
if (minute
|
824
|
-
minute = 0;
|
825
|
-
} else if (minute >= 60) {
|
861
|
+
if (minute > 59) {
|
826
862
|
minute = 59;
|
827
863
|
}
|
828
864
|
|
829
|
-
if (this.
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
|
865
|
+
if (hour >= this.maxHours) {
|
866
|
+
// No day/date handling.
|
867
|
+
hour = this.maxHours - 1;
|
868
|
+
}
|
869
|
+
|
870
|
+
if (this.showMeridian) {
|
871
|
+
if (hour > 12) {
|
872
|
+
// Force PM.
|
873
|
+
timeMode = 2;
|
874
|
+
hour -= 12;
|
875
|
+
}
|
876
|
+
if (!timeMode) {
|
877
|
+
timeMode = 1;
|
878
|
+
}
|
879
|
+
if (hour === 0) {
|
880
|
+
hour = 12; // AM or PM, reset to 12. 0 AM = 12 AM. 0 PM = 12 PM, etc.
|
881
|
+
}
|
882
|
+
meridian = timeMode === 1 ? 'AM' : 'PM';
|
883
|
+
} else if (hour < 12 && timeMode === 2) {
|
884
|
+
hour += 12;
|
885
|
+
} else {
|
886
|
+
if (hour >= this.maxHours) {
|
887
|
+
hour = this.maxHours - 1;
|
888
|
+
} else if (hour < 0) {
|
889
|
+
hour = 0;
|
836
890
|
}
|
837
891
|
}
|
838
892
|
}
|
839
893
|
|
840
894
|
this.hour = hour;
|
841
|
-
this.
|
842
|
-
|
895
|
+
if (this.snapToStep) {
|
896
|
+
this.minute = this.changeToNearestStep(minute, this.minuteStep);
|
897
|
+
this.second = this.changeToNearestStep(second, this.secondStep);
|
898
|
+
} else {
|
899
|
+
this.minute = minute;
|
900
|
+
this.second = second;
|
901
|
+
}
|
843
902
|
this.meridian = meridian;
|
844
903
|
|
845
904
|
this.update(ignoreWidget);
|
@@ -856,16 +915,7 @@
|
|
856
915
|
|
857
916
|
// show/hide approach taken by datepicker
|
858
917
|
this.$widget.appendTo(this.appendWidgetTo);
|
859
|
-
|
860
|
-
$(document).on('mousedown.timepicker, touchend.timepicker', function (e) {
|
861
|
-
// This condition was inspired by bootstrap-datepicker.
|
862
|
-
// The element the timepicker is invoked on is the input but it has a sibling for addon/button.
|
863
|
-
if (!(self.$element.parent().find(e.target).length ||
|
864
|
-
self.$widget.is(e.target) ||
|
865
|
-
self.$widget.find(e.target).length)) {
|
866
|
-
self.hideWidget();
|
867
|
-
}
|
868
|
-
});
|
918
|
+
$(document).on('mousedown.timepicker, touchend.timepicker', {scope: this}, this.handleDocumentClick);
|
869
919
|
|
870
920
|
this.$element.trigger({
|
871
921
|
'type': 'show.timepicker',
|
@@ -1000,9 +1050,13 @@
|
|
1000
1050
|
var $input = $(e.target),
|
1001
1051
|
name = $input.attr('class').replace('bootstrap-timepicker-', '');
|
1002
1052
|
|
1003
|
-
switch (e.
|
1053
|
+
switch (e.which) {
|
1004
1054
|
case 9: //tab
|
1005
|
-
if (
|
1055
|
+
if (e.shiftKey) {
|
1056
|
+
if (name === 'hour') {
|
1057
|
+
return this.hideWidget();
|
1058
|
+
}
|
1059
|
+
} else if ((this.showMeridian && name === 'meridian') || (this.showSeconds && name === 'second') || (!this.showMeridian && !this.showSeconds && name === 'minute')) {
|
1006
1060
|
return this.hideWidget();
|
1007
1061
|
}
|
1008
1062
|
break;
|
@@ -1051,7 +1105,7 @@
|
|
1051
1105
|
},
|
1052
1106
|
|
1053
1107
|
widgetKeyup: function(e) {
|
1054
|
-
if ((e.
|
1108
|
+
if ((e.which === 65) || (e.which === 77) || (e.which === 80) || (e.which === 46) || (e.which === 8) || (e.which >= 48 && e.which <= 57) || (e.which >= 96 && e.which <= 105)) {
|
1055
1109
|
this.updateFromWidgetInputs();
|
1056
1110
|
}
|
1057
1111
|
}
|
@@ -1085,13 +1139,15 @@
|
|
1085
1139
|
modalBackdrop: false,
|
1086
1140
|
orientation: { x: 'auto', y: 'auto'},
|
1087
1141
|
secondStep: 15,
|
1142
|
+
snapToStep: false,
|
1088
1143
|
showSeconds: false,
|
1089
1144
|
showInputs: true,
|
1090
1145
|
showMeridian: true,
|
1091
1146
|
template: 'dropdown',
|
1092
1147
|
appendWidgetTo: 'body',
|
1093
1148
|
showWidgetOnAddonClick: true,
|
1094
|
-
maxHours: 24
|
1149
|
+
maxHours: 24,
|
1150
|
+
explicitMode: false
|
1095
1151
|
};
|
1096
1152
|
|
1097
1153
|
$.fn.timepicker.Constructor = Timepicker;
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bootstrap-timepicker-rails-addon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thomas Yang
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-08-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: railties
|