diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index df3216ca6b..9c6a56f30f 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -440,7 +440,6 @@ Style/RescueStandardError:
Exclude:
- 'lib/rails_admin/adapters/mongoid.rb'
- 'lib/rails_admin/adapters/mongoid/bson.rb'
- - 'lib/rails_admin/support/i18n.rb'
# Offense count: 2
# Cop supports --auto-correct.
diff --git a/app/assets/javascripts/rails_admin/ra.filter-box.js b/app/assets/javascripts/rails_admin/ra.filter-box.js
index 41bd047293..aae15e99c1 100644
--- a/app/assets/javascripts/rails_admin/ra.filter-box.js
+++ b/app/assets/javascripts/rails_admin/ra.filter-box.js
@@ -34,33 +34,21 @@
}
break;
case 'date':
- additional_control =
- $('')
- .css('display', (!field_operator || field_operator == "default") ? 'inline-block' : 'none')
- .prop('name', value_name + '[]')
- .prop('value', field_value[0] || '')
- .add(
- $('')
- .css('display', (field_operator == "between") ? 'inline-block' : 'none')
- .prop('name', value_name + '[]')
- .prop('value', field_value[1] || '')
- )
- .add(
- $('')
- .css('display', (field_operator == "between") ? 'inline-block' : 'none')
- .prop('name', value_name + '[]')
- .prop('value', field_value[2] || '')
- );
case 'datetime':
case 'timestamp':
+ case 'time':
control = control || $('')
.prop('name', operator_name)
- .append($('').prop('selected', field_operator == "default").text(RailsAdmin.I18n.t("date")))
+ .append($('').prop('selected', field_operator == "default").text(RailsAdmin.I18n.t(field_type == "time" ? "time" : "date")))
.append($('').prop('selected', field_operator == "between").text(RailsAdmin.I18n.t("between_and_")))
- .append($('').prop('selected', field_operator == "today").text(RailsAdmin.I18n.t("today")))
- .append($('').prop('selected', field_operator == "yesterday").text(RailsAdmin.I18n.t("yesterday")))
- .append($('').prop('selected', field_operator == "this_week").text(RailsAdmin.I18n.t("this_week")))
- .append($('').prop('selected', field_operator == "last_week").text(RailsAdmin.I18n.t("last_week")))
+ if (field_type != 'time') {
+ control.append([
+ $('').prop('selected', field_operator == "today").text(RailsAdmin.I18n.t("today")),
+ $('').prop('selected', field_operator == "yesterday").text(RailsAdmin.I18n.t("yesterday")),
+ $('').prop('selected', field_operator == "this_week").text(RailsAdmin.I18n.t("this_week")),
+ $('').prop('selected', field_operator == "last_week").text(RailsAdmin.I18n.t("last_week")),
+ ])
+ }
if (!required) {
control.append([
'',
@@ -68,23 +56,24 @@
$('').prop('selected', field_operator == "_null").text(RailsAdmin.I18n.t("is_blank"))
])
}
- additional_control = additional_control ||
- $('')
- .css('display', (!field_operator || field_operator == "default") ? 'inline-block' : 'none')
- .prop('name', value_name + '[]')
- .prop('value', field_value[0] || '')
- .add(
- $('')
- .css('display', (field_operator == "between") ? 'inline-block' : 'none')
- .prop('name', value_name + '[]')
- .prop('value', field_value[1] || '')
- )
- .add(
- $('')
- .css('display', (field_operator == "between") ? 'inline-block' : 'none')
- .prop('name', value_name + '[]')
- .prop('value', field_value[2] || '')
- );
+ additional_control =
+ $.map([undefined, '-∞', '∞'], function(placeholder, index){
+ var visible = index == 0 ? (!field_operator || field_operator == "default") : (field_operator == "between");
+ return $('')
+ .addClass(index == 0 ? 'default' : 'between')
+ .css('display', visible ? 'inline-block' : 'none')
+ .html(
+ $('')
+ .prop('name', value_name + '[]')
+ .prop('value', field_value[index] || '')
+ .add(
+ $('')
+ .addClass(field_type == 'date' ? 'date' : 'datetime')
+ .prop('size', field_type == 'date' || field_type == 'time' ? 20 : 25)
+ .prop('placeholder', placeholder)
+ )
+ );
+ });
break;
case 'enum':
var multiple_values = ((field_value instanceof Array) ? true : false)
@@ -193,10 +182,18 @@
$('#filters_box').append($content);
- $content.find('.date, .datetime').datetimepicker({
- locale: RailsAdmin.I18n.locale,
- showTodayButton: true,
- format: options['datetimepicker_format']
+ $content.find('.date, .datetime').each(function() {
+ $(this).datetimepicker({
+ date: moment($(this).siblings('[type=hidden]').val()),
+ locale: RailsAdmin.I18n.locale,
+ showTodayButton: true,
+ format: options['datetimepicker_format']
+ });
+ $(this).on('dp.change', function(e) {
+ if (e.date) {
+ $(this).siblings('[type=hidden]').val(e.date.format('YYYY-MM-DD[T]HH:mm:ss'));
+ }
+ });
});
$("hr.filters_box:hidden").show('slow');
diff --git a/app/assets/javascripts/rails_admin/ra.widgets.js b/app/assets/javascripts/rails_admin/ra.widgets.js
index 534afeec54..9081149bfa 100644
--- a/app/assets/javascripts/rails_admin/ra.widgets.js
+++ b/app/assets/javascripts/rails_admin/ra.widgets.js
@@ -37,9 +37,15 @@
var options;
options = $(this).data('options');
$.extend(options, {
+ date: moment($(this).siblings('[type=hidden]').val()),
locale: RailsAdmin.I18n.locale
});
$(this).datetimepicker(options);
+ $(this).on('dp.change', function(e) {
+ if (e.date) {
+ $(this).siblings('[type=hidden]').val(e.date.format('YYYY-MM-DD[T]HH:mm:ss'));
+ }
+ });
});
content.find('[data-enumeration]').each(function() {
if ($(this).is('[multiple]')) {
diff --git a/app/helpers/rails_admin/application_helper.rb b/app/helpers/rails_admin/application_helper.rb
index 600b88989d..3a31d2832f 100644
--- a/app/helpers/rails_admin/application_helper.rb
+++ b/app/helpers/rails_admin/application_helper.rb
@@ -1,9 +1,5 @@
-require 'rails_admin/support/i18n'
-
module RailsAdmin
module ApplicationHelper
- include RailsAdmin::Support::I18n
-
def capitalize_first_letter(wording)
return nil unless wording.present? && wording.is_a?(String)
diff --git a/app/helpers/rails_admin/main_helper.rb b/app/helpers/rails_admin/main_helper.rb
index bc56285826..3ee56d664f 100644
--- a/app/helpers/rails_admin/main_helper.rb
+++ b/app/helpers/rails_admin/main_helper.rb
@@ -69,7 +69,7 @@ def ordered_filter_options
when :enum
options[:select_options] = options_for_select(field.with(object: @abstract_model.model.new).enum, filter_hash['v'])
when :date, :datetime, :time
- options[:datetimepicker_format] = field.parser.to_momentjs
+ options[:datetimepicker_format] = field.momentjs_format
end
options[:label] = field.label
options[:name] = field.name
diff --git a/app/views/rails_admin/main/_form_datetime.html.haml b/app/views/rails_admin/main/_form_datetime.html.haml
index 558c2c7fee..091688d1f2 100644
--- a/app/views/rails_admin/main/_form_datetime.html.haml
+++ b/app/views/rails_admin/main/_form_datetime.html.haml
@@ -1,5 +1,6 @@
.form-inline
.input-group
- = form.send field.view_helper, field.method_name, field.html_attributes.reverse_merge({value: field.form_value, class: 'form-control', data: {datetimepicker: true, options: field.datepicker_options.to_json}})
+ = form.hidden_field(field.method_name, id: nil, value: field.form_value)
+ = form.text_field field.method_name, field.html_attributes.reverse_merge({class: 'form-control', data: {datetimepicker: true, options: field.datepicker_options.to_json}, name: nil, value: nil})
= form.label(field.method_name, class: 'input-group-addon') do
%i.fa.fa-fw.fa-calendar
diff --git a/app/views/rails_admin/main/index.html.haml b/app/views/rails_admin/main/index.html.haml
index 21bd89d457..29a422ab6b 100644
--- a/app/views/rails_admin/main/index.html.haml
+++ b/app/views/rails_admin/main/index.html.haml
@@ -35,7 +35,7 @@
- else
- ''
%li
- %a{href: '#', :"data-field-label" => field.label, :"data-field-name" => field.name, :"data-field-operator" => field.default_filter_operator, :"data-field-options" => field_options.html_safe, :"data-field-required" => field.required.to_s, :"data-field-type" => field.type, :"data-field-value" => "", :"data-field-datetimepicker-format" => (field.try(:parser) && field.parser.to_momentjs)}= capitalize_first_letter(field.label)
+ %a{href: '#', :"data-field-label" => field.label, :"data-field-name" => field.name, :"data-field-operator" => field.default_filter_operator, :"data-field-options" => field_options.html_safe, :"data-field-required" => field.required.to_s, :"data-field-type" => field.type, :"data-field-value" => "", :"data-field-datetimepicker-format" => field.try(:momentjs_format)}= capitalize_first_letter(field.label)
%style
- properties.select{ |p| p.column_width.present? }.each do |property|
diff --git a/config/locales/rails_admin.en.yml b/config/locales/rails_admin.en.yml
index d7d641b9ca..31699ee0c4 100644
--- a/config/locales/rails_admin.en.yml
+++ b/config/locales/rails_admin.en.yml
@@ -11,6 +11,7 @@ en:
yesterday: Yesterday
this_week: This week
last_week: Last week
+ time: Time ...
number: Number ...
contains: Contains
is_exactly: Is exactly
diff --git a/lib/rails_admin/abstract_model.rb b/lib/rails_admin/abstract_model.rb
index 3929995b1a..61c7cdf062 100644
--- a/lib/rails_admin/abstract_model.rb
+++ b/lib/rails_admin/abstract_model.rb
@@ -139,7 +139,7 @@ def build_statement_for_type_generic
case @type
when :date
build_statement_for_date
- when :datetime, :timestamp
+ when :datetime, :timestamp, :time
build_statement_for_datetime_or_timestamp
end
end
@@ -178,8 +178,8 @@ def build_statement_for_date
def build_statement_for_datetime_or_timestamp
start_date, end_date = get_filtering_duration
- start_date = start_date.try(:beginning_of_day) if start_date
- end_date = end_date.try(:end_of_day) if end_date
+ start_date = start_date.beginning_of_day if start_date.is_a?(Date)
+ end_date = end_date.end_of_day if end_date.is_a?(Date)
range_filter(start_date, end_date)
end
diff --git a/lib/rails_admin/adapters/active_record.rb b/lib/rails_admin/adapters/active_record.rb
index 2defcb1ab9..6972a80c11 100644
--- a/lib/rails_admin/adapters/active_record.rb
+++ b/lib/rails_admin/adapters/active_record.rb
@@ -205,7 +205,9 @@ def boolean_unary_operators
alias_method :numeric_unary_operators, :boolean_unary_operators
def range_filter(min, max)
- if min && max
+ if min && max && min == max
+ ["(#{@column} = ?)", min]
+ elsif min && max
["(#{@column} BETWEEN ? AND ?)", min, max]
elsif min
["(#{@column} >= ?)", min]
diff --git a/lib/rails_admin/adapters/mongoid.rb b/lib/rails_admin/adapters/mongoid.rb
index 820cccd06a..f1643a6091 100644
--- a/lib/rails_admin/adapters/mongoid.rb
+++ b/lib/rails_admin/adapters/mongoid.rb
@@ -283,7 +283,9 @@ def build_statement_for_belongs_to_association_or_bson_object_id
end
def range_filter(min, max)
- if min && max
+ if min && max && min == max
+ {@column => min}
+ elsif min && max
{@column => {'$gte' => min, '$lte' => max}}
elsif min
{@column => {'$gte' => min}}
diff --git a/lib/rails_admin/config/fields/types/date.rb b/lib/rails_admin/config/fields/types/date.rb
index 825be17f5f..022fdf3f8c 100644
--- a/lib/rails_admin/config/fields/types/date.rb
+++ b/lib/rails_admin/config/fields/types/date.rb
@@ -7,6 +7,10 @@ module Types
class Date < RailsAdmin::Config::Fields::Types::Datetime
RailsAdmin::Config::Fields::Types.register(self)
+ def parse_value(value)
+ ::Date.parse(value) if value.present?
+ end
+
register_instance_option :date_format do
:long
end
@@ -15,13 +19,6 @@ class Date < RailsAdmin::Config::Fields::Types::Datetime
[:date, :formats]
end
- register_instance_option :datepicker_options do
- {
- showTodayButton: true,
- format: parser.to_momentjs,
- }
- end
-
register_instance_option :html_attributes do
{
required: required?,
diff --git a/lib/rails_admin/config/fields/types/datetime.rb b/lib/rails_admin/config/fields/types/datetime.rb
index d233a52b26..5e5c715c9c 100644
--- a/lib/rails_admin/config/fields/types/datetime.rb
+++ b/lib/rails_admin/config/fields/types/datetime.rb
@@ -8,27 +8,14 @@ module Types
class Datetime < RailsAdmin::Config::Fields::Base
RailsAdmin::Config::Fields::Types.register(self)
- def parser
- RailsAdmin::Support::Datetime.new(strftime_format)
- end
-
def parse_value(value)
- parser.parse_string(value)
+ ::Time.zone.parse(value)
end
def parse_input(params)
params[name] = parse_value(params[name]) if params[name]
end
- def value
- parent_value = super
- if %w(DateTime Date Time).include?(parent_value.class.name)
- parent_value.in_time_zone
- else
- parent_value
- end
- end
-
register_instance_option :date_format do
:long
end
@@ -43,10 +30,14 @@ def value
"%B %d, %Y %H:%M"
end
+ def momentjs_format
+ RailsAdmin::Support::Datetime.to_momentjs(strftime_format)
+ end
+
register_instance_option :datepicker_options do
{
showTodayButton: true,
- format: parser.to_momentjs,
+ format: momentjs_format,
}
end
@@ -61,6 +52,10 @@ def value
true
end
+ register_instance_option :queryable? do
+ false
+ end
+
register_instance_option :formatted_value do
if time = (value || default_value)
::I18n.l(time, format: strftime_format)
@@ -72,6 +67,10 @@ def value
register_instance_option :partial do
:form_datetime
end
+
+ def form_value
+ value&.in_time_zone&.strftime('%FT%T') || form_default_value
+ end
end
end
end
diff --git a/lib/rails_admin/config/fields/types/time.rb b/lib/rails_admin/config/fields/types/time.rb
index cc9a609bd6..c974539324 100644
--- a/lib/rails_admin/config/fields/types/time.rb
+++ b/lib/rails_admin/config/fields/types/time.rb
@@ -8,10 +8,7 @@ class Time < RailsAdmin::Config::Fields::Types::Datetime
RailsAdmin::Config::Fields::Types.register(self)
def parse_value(value)
- parent_value = super(value)
- return unless parent_value
- value_with_tz = parent_value.in_time_zone
- ::DateTime.parse(value_with_tz.strftime('%Y-%m-%d %H:%M:%S'))
+ abstract_model.model.type_for_attribute(name.to_s).serialize(super)&.change(year: 2000, month: 1, day: 1)
end
register_instance_option :strftime_format do
diff --git a/lib/rails_admin/config/fields/types/timestamp.rb b/lib/rails_admin/config/fields/types/timestamp.rb
index 8025e7ff7a..b9c63bb8b6 100644
--- a/lib/rails_admin/config/fields/types/timestamp.rb
+++ b/lib/rails_admin/config/fields/types/timestamp.rb
@@ -7,10 +7,6 @@ module Types
class Timestamp < RailsAdmin::Config::Fields::Types::Datetime
# Register field type for the type loader
RailsAdmin::Config::Fields::Types.register(self)
-
- @format = :long
- @i18n_scope = [:time, :formats]
- @js_plugin_options = {}
end
end
end
diff --git a/lib/rails_admin/support/datetime.rb b/lib/rails_admin/support/datetime.rb
index e175c1b66c..8e3bcb5436 100644
--- a/lib/rails_admin/support/datetime.rb
+++ b/lib/rails_admin/support/datetime.rb
@@ -1,5 +1,3 @@
-require 'rails_admin/support/i18n'
-
module RailsAdmin
module Support
class Datetime
@@ -26,73 +24,10 @@ class Datetime
}.freeze
class << self
- include RailsAdmin::Support::I18n
-
- def delocalize(date_string, format)
- return date_string if ::I18n.locale.to_s == 'en'
- format.to_s.scan(/%[AaBbp]/) do |match|
- case match
- when '%A'
- english = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
- day_names.each_with_index { |d, i| date_string = date_string.gsub(/#{d}/, english[i]) }
- when '%a'
- english = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]
- abbr_day_names.each_with_index { |d, i| date_string = date_string.gsub(/#{d}/, english[i]) }
- when '%B'
- english = [nil, "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"][1..-1]
- month_names.each_with_index { |m, i| date_string = date_string.gsub(/#{m}/, english[i]) }
- when '%b'
- english = [nil, "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"][1..-1]
- abbr_month_names.each_with_index { |m, i| date_string = date_string.gsub(/#{m}/, english[i]) }
- when '%p'
- date_string = date_string.gsub(/#{::I18n.t('date.time.am', default: "am")}/, 'am')
- date_string = date_string.gsub(/#{::I18n.t('date.time.pm', default: "pm")}/, 'pm')
- end
+ def to_momentjs(strftime_format)
+ strftime_format.gsub(/\w[^.(!?%)\W]{1,}/, '[\0]').gsub(/%(\w|\-\w)/) do |match|
+ MOMENTJS_TRANSLATIONS[match]
end
- date_string
- end
-
- def normalize(date_string, format)
- return unless date_string
- delocalize(date_string, format)
- parse_date_string(date_string)
- end
-
- # Parse normalized date strings using time zone
- def parse_date_string(date_string)
- ::Time.zone.parse(date_string)
- end
- end
-
- attr_reader :strftime_format
-
- def initialize(strftime_format)
- @strftime_format = strftime_format
- end
-
- # Ruby to javascript formatting options translator
- def to_momentjs
- strftime_format.gsub(/\w[^.(!?%)\W]{1,}/, '[\0]').gsub(/%(\w|\-\w)/) do |match|
- MOMENTJS_TRANSLATIONS[match]
- end
- end
-
- # Delocalize a l10n datetime strings
- def delocalize(value)
- self.class.delocalize(value, strftime_format)
- end
-
- def parse_string(value)
- return if value.blank?
- return value if %w(DateTime Date Time).include?(value.class.name)
- return if (delocalized_value = delocalize(value)).blank?
-
- begin
- # Adjust with the correct timezone and daylight savint time
- datetime_with_wrong_tz = ::DateTime.strptime(delocalized_value, strftime_format.gsub('%-d', '%d'))
- Time.zone.parse(datetime_with_wrong_tz.strftime('%Y-%m-%d %H:%M:%S'))
- rescue ArgumentError
- nil
end
end
end
diff --git a/lib/rails_admin/support/i18n.rb b/lib/rails_admin/support/i18n.rb
deleted file mode 100644
index d4d4480db7..0000000000
--- a/lib/rails_admin/support/i18n.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-require 'i18n'
-
-module RailsAdmin
- module Support
- module I18n
- def abbr_day_names
- ::I18n.t('date.abbr_day_names', raise: true)
- rescue ::I18n::ArgumentError
- ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]
- end
-
- def abbr_month_names
- begin
- names = ::I18n.t('date.abbr_month_names', raise: true)
- rescue ::I18n::ArgumentError
- names = [nil, "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
- end
- names[1..-1]
- end
-
- def date_format
- ::I18n.t('date.formats.default', raise: true)
- rescue
- "%Y-%m-%d"
- end
-
- def day_names
- ::I18n.t('date.day_names', raise: true)
- rescue ::I18n::ArgumentError
- ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
- end
-
- def month_names
- begin
- names = ::I18n.t('date.month_names', raise: true)
- rescue ::I18n::ArgumentError
- names = [nil, "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
- end
- names[1..-1]
- end
- end
- end
-end
diff --git a/spec/controllers/rails_admin/main_controller_spec.rb b/spec/controllers/rails_admin/main_controller_spec.rb
index e5c88e7513..1b18beb50f 100644
--- a/spec/controllers/rails_admin/main_controller_spec.rb
+++ b/spec/controllers/rails_admin/main_controller_spec.rb
@@ -245,27 +245,18 @@ def get(action, params)
end
describe 'sanitize_params_for!' do
- context 'in France' do
+ context 'with datetime' do
before do
- I18n.locale = :fr
ActionController::Parameters.permit_all_parameters = false
- RailsAdmin.config FieldTest do
- configure :datetime_field do
- date_format { :default }
- end
- end
-
RailsAdmin.config Comment do
configure :created_at do
- date_format { :default }
show
end
end
RailsAdmin.config NestedFieldTest do
configure :created_at do
- date_format { :default }
show
end
end
@@ -273,19 +264,19 @@ def get(action, params)
controller.params = ActionController::Parameters.new(
'field_test' => {
'unallowed_field' => "I shouldn't be here",
- 'datetime_field' => '1 août 2010 00:00:00',
+ 'datetime_field' => '2010-08-01T00:00:00',
'nested_field_tests_attributes' => {
'new_1330520162002' => {
'comment_attributes' => {
'unallowed_field' => "I shouldn't be here",
- 'created_at' => '2 août 2010 00:00:00',
+ 'created_at' => '2010-08-02T00:00:00',
},
- 'created_at' => '3 août 2010 00:00:00',
+ 'created_at' => '2010-08-03T00:00:00',
},
},
'comment_attributes' => {
'unallowed_field' => "I shouldn't be here",
- 'created_at' => '4 août 2010 00:00:00',
+ 'created_at' => '2010-08-04T00:00:00',
},
},
)
@@ -294,7 +285,6 @@ def get(action, params)
after do
ActionController::Parameters.permit_all_parameters = true
- I18n.locale = :en
end
it 'sanitize params recursively in nested forms' do
diff --git a/spec/integration/actions/edit_spec.rb b/spec/integration/actions/edit_spec.rb
index ed47d8db17..e6004a1bf6 100644
--- a/spec/integration/actions/edit_spec.rb
+++ b/spec/integration/actions/edit_spec.rb
@@ -695,39 +695,6 @@ class HelpTest < Tableless
end
end
- context 'on clicking save without changing anything' do
- before { @datetime = 'October 08, 2015 06:45' }
- context 'when config.time_zone set' do
- before do
- RailsAdmin.config Player do
- field :datetime_field
- end
- @old_timezone = Time.zone
- Time.zone = ActiveSupport::TimeZone.new('Central Time (US & Canada)')
- end
-
- after do
- Time.zone = @old_timezone
- end
-
- it 'does not alter datetime fields' do
- visit new_path(model_name: 'field_test')
- find('#field_test_datetime_field').set(@datetime)
- click_button 'Save and edit'
- expect(find('#field_test_datetime_field').value).to eq(@datetime)
- end
- end
-
- context 'without config.time_zone set (default)' do
- it 'does not alter datetime fields' do
- visit new_path(model_name: 'field_test')
- find('#field_test_datetime_field').set(@datetime)
- click_button 'Save and edit'
- expect(find('#field_test_datetime_field').value).to eq(@datetime)
- end
- end
- end
-
context 'with errors' do
before do
@player = FactoryBot.create :player
diff --git a/spec/integration/fields/base_spec.rb b/spec/integration/fields/base_spec.rb
index 5bfdc2bd53..0e6509a67c 100644
--- a/spec/integration/fields/base_spec.rb
+++ b/spec/integration/fields/base_spec.rb
@@ -30,7 +30,7 @@
# So we manually cut off first newline character as a workaround here.
expect(find_field('field_test[string_field]').value.gsub(/^\n/, '')).to eq('string_field default_value')
expect(find_field('field_test[text_field]').value.gsub(/^\n/, '')).to eq('string_field text_field')
- expect(find_field('field_test[date_field]').value).to eq(Date.today.to_s)
+ expect(find('[name="field_test[date_field]"]', visible: false).value).to eq(Date.today.to_s)
expect(has_checked_field?('field_test[boolean_field]')).to be_truthy
end
diff --git a/spec/integration/fields/date_spec.rb b/spec/integration/fields/date_spec.rb
new file mode 100644
index 0000000000..a95c19fc1a
--- /dev/null
+++ b/spec/integration/fields/date_spec.rb
@@ -0,0 +1,148 @@
+require 'spec_helper'
+
+RSpec.describe 'Date field', type: :request do
+ subject { page }
+ before do
+ RailsAdmin.config FieldTest do
+ field :id
+ field :date_field
+ end
+ end
+
+ describe 'Bootstrap Datetimepicker integration' do
+ describe 'for form' do
+ before { visit new_path({model_name: 'field_test'}.merge(params)) }
+ let(:params) { {} }
+
+ it 'is initially blank', js: true do
+ expect(find('[name="field_test[date_field]"]', visible: false).value).to be_blank
+ expect(find('#field_test_date_field').value).to be_blank
+ end
+
+ it 'populates the value selected by the Datetime picker into the hidden_field', js: true do
+ page.execute_script <<-JS
+ $('#field_test_date_field').data("DateTimePicker").date(moment('2015-10-08')).toggle();
+ JS
+ expect(find('#field_test_date_field').value).to eq 'October 08, 2015'
+ expect(find('[name="field_test[date_field]"]', visible: false).value).to eq '2015-10-08T00:00:00'
+ end
+
+ it 'ignores the time part', js: true do
+ page.execute_script <<-JS
+ $('#field_test_date_field').data("DateTimePicker").date(moment('2015-10-08 12:00:00')).toggle();
+ JS
+ expect(find('#field_test_date_field').value).to eq 'October 08, 2015'
+ end
+
+ it 'populates the value entered in the text field into the hidden_field', js: true do
+ fill_in 'Date field', with: 'January 2, 2021'
+ expect(find('[name="field_test[date_field]"]', visible: false).value).to eq '2021-01-02T00:00:00'
+ expect(find('#field_test_date_field').value).to eq 'January 02, 2021'
+ end
+
+ context 'with locale set' do
+ around(:each) do |example|
+ original = I18n.default_locale
+ I18n.default_locale = :fr
+ example.run
+ I18n.default_locale = original
+ end
+ let(:params) { {field_test: {date_field: '2021-01-02T00:00:00'}} }
+
+ it 'shows and accepts the value in the given locale', js: true do
+ expect(find('[name="field_test[date_field]"]', visible: false).value).to eq '2021-01-02T00:00:00'
+ expect(find('#field_test_date_field').value).to eq "2 janvier 2021"
+ fill_in 'Date field', with: '3 février 2021'
+ expect(find('[name="field_test[date_field]"]', visible: false).value).to eq '2021-02-03T00:00:00'
+ end
+ end
+ end
+
+ describe 'for filter' do
+ it 'populates the value selected by the Datetime picker into the hidden_field', js: true do
+ visit index_path(model_name: 'field_test')
+ click_link 'Add filter'
+ click_link 'Date field'
+ expect(find('[name^="f[date_field]"][name$="[v][]"]', match: :first, visible: false).value).to be_blank
+ page.execute_script <<-JS
+ $('.form-control.date').data("DateTimePicker").date(moment('2015-10-08')).toggle();
+ JS
+ expect(find('[name^="f[date_field]"][name$="[v][]"]', match: :first, visible: false).value).to eq '2015-10-08T00:00:00'
+ end
+ end
+ end
+
+ describe 'filtering' do
+ let!(:field_tests) do
+ [FactoryBot.create(:field_test, date_field: Date.new(2021, 1, 2)),
+ FactoryBot.create(:field_test, date_field: Date.new(2021, 1, 3))]
+ end
+
+ it 'correctly returns a record' do
+ visit index_path(model_name: 'field_test', f: {date_field: {'1' => {v: [nil, '2021-01-03T00:00:00', nil], o: 'between'}}})
+ is_expected.to have_content '1 field test'
+ is_expected.to have_content field_tests[1].id
+ end
+
+ it 'does not break when the condition is not filled' do
+ visit index_path(model_name: 'field_test', f: {date_field: {'1' => {v: [nil, '', ''], o: 'between'}}})
+ is_expected.to have_content '2 field test'
+ end
+
+ context 'with server timezone changed' do
+ around do |example|
+ original = Time.zone
+ Time.zone = ActiveSupport::TimeZone.new('Central Time (US & Canada)')
+ example.run
+ Time.zone = original
+ end
+
+ it 'correctly returns a record' do
+ visit index_path(model_name: 'field_test', f: {date_field: {'1' => {v: [nil, '2021-01-03T00:00:00', nil], o: 'between'}}})
+ is_expected.to have_content '1 field test'
+ is_expected.to have_content field_tests[1].id
+ end
+ end
+ end
+
+ context 'on create' do
+ it 'persists the value' do
+ visit new_path(model_name: 'field_test')
+ find('[name="field_test[date_field]"]', visible: false).set('2021-01-02T00:00:00')
+ click_button 'Save'
+ expect(FieldTest.count).to eq 1
+ expect(FieldTest.first.date_field).to eq Date.new(2021, 1, 2)
+ end
+ end
+
+ context 'on update' do
+ let(:field_test) { FactoryBot.create :field_test, date_field: Date.new(2021, 1, 2) }
+
+ it 'updates the value' do
+ visit edit_path(model_name: 'field_test', id: field_test.id)
+ expect(find('[name="field_test[date_field]"]', visible: false).value).to eq '2021-01-02T00:00:00'
+ find('[name="field_test[date_field]"]', visible: false).set('2021-02-03T00:00:00')
+ click_button 'Save'
+ field_test.reload
+ expect(field_test.date_field).to eq Date.new(2021, 2, 3)
+ end
+ end
+
+ context 'with server timezone changed' do
+ let(:field_test) { FactoryBot.create :field_test, date_field: Date.new(2015, 10, 8) }
+
+ around do |example|
+ original = Time.zone
+ Time.zone = ActiveSupport::TimeZone.new('Central Time (US & Canada)')
+ example.run
+ Time.zone = original
+ end
+
+ it 'is not altered by just saving untouched' do
+ visit edit_path(model_name: 'field_test', id: field_test.id)
+ expect(find('[name="field_test[date_field]"]', visible: false).value).to eq '2015-10-08T00:00:00'
+ click_button 'Save'
+ expect { field_test.reload }.not_to change(field_test, :date_field)
+ end
+ end
+end
diff --git a/spec/integration/fields/datetime_spec.rb b/spec/integration/fields/datetime_spec.rb
new file mode 100644
index 0000000000..2d91535f04
--- /dev/null
+++ b/spec/integration/fields/datetime_spec.rb
@@ -0,0 +1,150 @@
+require 'spec_helper'
+
+RSpec.describe 'Datetime field', type: :request do
+ subject { page }
+ before do
+ RailsAdmin.config FieldTest do
+ edit do
+ field :datetime_field
+ end
+ end
+ end
+
+ describe 'Bootstrap Datetimepicker integration' do
+ describe 'for form' do
+ before { visit new_path({model_name: 'field_test'}.merge(params)) }
+ let(:params) { {} }
+
+ it 'is initially blank', js: true do
+ expect(find('[name="field_test[datetime_field]"]', visible: false).value).to be_blank
+ expect(find('#field_test_datetime_field').value).to be_blank
+ end
+
+ it 'populates the value selected by the Datetime picker into the hidden_field', js: true do
+ page.execute_script <<-JS
+ $('#field_test_datetime_field').data("DateTimePicker").date(moment('2015-10-08 14:00:00')).toggle();
+ JS
+ expect(find('#field_test_datetime_field').value).to eq 'October 08, 2015 14:00'
+ expect(find('[name="field_test[datetime_field]"]', visible: false).value).to eq '2015-10-08T14:00:00'
+ end
+
+ it 'populates the value entered in the text field into the hidden_field', js: true do
+ fill_in 'Datetime field', with: 'January 2, 2021 03:45'
+ expect(find('[name="field_test[datetime_field]"]', visible: false).value).to eq '2021-01-02T03:45:00'
+ expect(find('#field_test_datetime_field').value).to eq 'January 02, 2021 03:45'
+ end
+
+ context 'with locale set' do
+ around(:each) do |example|
+ original = I18n.default_locale
+ I18n.default_locale = :fr
+ example.run
+ I18n.default_locale = original
+ end
+ let(:params) { {field_test: {datetime_field: '2021-01-02T03:45:00'}} }
+
+ it 'shows and accepts the value in the given locale', js: true do
+ expect(find('[name="field_test[datetime_field]"]', visible: false).value).to eq '2021-01-02T03:45:00'
+ expect(find('#field_test_datetime_field').value).to eq "samedi 02 janvier 2021 03:45"
+ fill_in 'Datetime field', with: 'mercredi 03 février 2021 04:55'
+ expect(find('[name="field_test[datetime_field]"]', visible: false).value).to eq '2021-02-03T04:55:00'
+ end
+ end
+ end
+
+ describe 'for filter' do
+ it 'populates the value selected by the Datetime picker into the hidden_field', js: true do
+ visit index_path(model_name: 'field_test')
+ click_link 'Add filter'
+ click_link 'Datetime field'
+ expect(find('[name^="f[datetime_field]"][name$="[v][]"]', match: :first, visible: false).value).to be_blank
+ page.execute_script <<-JS
+ $('.form-control.datetime').data("DateTimePicker").date(moment('2015-10-08 14:00:00')).toggle();
+ JS
+ expect(find('[name^="f[datetime_field]"][name$="[v][]"]', match: :first, visible: false).value).to eq '2015-10-08T14:00:00'
+ end
+ end
+ end
+
+ describe 'filtering' do
+ let!(:field_tests) do
+ [FactoryBot.create(:field_test, datetime_field: DateTime.new(2021, 1, 2, 3, 45)),
+ FactoryBot.create(:field_test, datetime_field: DateTime.new(2021, 1, 2, 4, 45))]
+ end
+
+ it 'correctly returns a record' do
+ visit index_path(model_name: 'field_test', f: {datetime_field: {'1' => {v: [nil, '2021-01-02T04:00:00', nil], o: 'between'}}})
+ is_expected.to have_content '1 field test'
+ is_expected.to have_content field_tests[1].id
+ end
+
+ it 'does not break when the condition is not filled' do
+ visit index_path(model_name: 'field_test', f: {datetime_field: {'1' => {v: [nil, '', ''], o: 'between'}}})
+ is_expected.to have_content '2 field test'
+ end
+
+ context 'with server timezone changed' do
+ around do |example|
+ original = Time.zone
+ Time.zone = ActiveSupport::TimeZone.new('Central Time (US & Canada)')
+ example.run
+ Time.zone = original
+ end
+
+ it 'correctly returns a record' do
+ visit index_path(model_name: 'field_test', f: {datetime_field: {'1' => {v: [nil, '2021-01-01T22:00:00', nil], o: 'between'}}})
+ is_expected.to have_content '1 field test'
+ is_expected.to have_content field_tests[1].id
+ end
+ end
+ end
+
+ context 'on create' do
+ it 'persists the value' do
+ visit new_path(model_name: 'field_test')
+ find('[name="field_test[datetime_field]"]', visible: false).set('2021-01-02T03:45:00')
+ click_button 'Save'
+ expect(FieldTest.count).to eq 1
+ expect(FieldTest.first.datetime_field).to eq DateTime.new(2021, 1, 2, 3, 45)
+ end
+ end
+
+ context 'on update' do
+ let(:field_test) { FactoryBot.create :field_test, datetime_field: DateTime.new(2021, 1, 2, 3, 45) }
+
+ it 'updates the value' do
+ visit edit_path(model_name: 'field_test', id: field_test.id)
+ expect(find('[name="field_test[datetime_field]"]', visible: false).value).to eq '2021-01-02T03:45:00'
+ find('[name="field_test[datetime_field]"]', visible: false).set('2021-02-03T04:55:00')
+ click_button 'Save'
+ field_test.reload
+ expect(field_test.datetime_field).to eq DateTime.new(2021, 2, 3, 4, 55)
+ end
+ end
+
+ context 'with server timezone changed' do
+ let(:field_test) { FactoryBot.create :field_test, datetime_field: DateTime.new(2015, 10, 8, 6, 45) }
+
+ around do |example|
+ original = Time.zone
+ Time.zone = ActiveSupport::TimeZone.new('Central Time (US & Canada)')
+ example.run
+ Time.zone = original
+ end
+
+ it 'treats the datetime set by the browser as local time' do
+ visit edit_path(model_name: 'field_test', id: field_test.id)
+ find('[name="field_test[datetime_field]"]', visible: false).set('2021-02-03T04:55:00')
+ click_button 'Save'
+ field_test.reload
+ expect(field_test.datetime_field.iso8601).to eq "2021-02-03T04:55:00-06:00"
+ end
+
+ it 'is not altered by just saving untouched' do
+ visit edit_path(model_name: 'field_test', id: field_test.id)
+ expect(find('[name="field_test[datetime_field]"]', visible: false).value).to eq '2015-10-08T01:45:00'
+ click_button 'Save'
+ expect { field_test.reload }.not_to change(field_test, :datetime_field)
+ end
+ end
+end
diff --git a/spec/integration/fields/time_spec.rb b/spec/integration/fields/time_spec.rb
new file mode 100644
index 0000000000..e7e273f537
--- /dev/null
+++ b/spec/integration/fields/time_spec.rb
@@ -0,0 +1,150 @@
+require 'spec_helper'
+
+RSpec.describe 'Time field', type: :request, active_record: true do
+ subject { page }
+ before do
+ RailsAdmin.config FieldTest do
+ edit do
+ field :time_field
+ end
+ end
+ end
+
+ describe 'Bootstrap Datetimepicker integration' do
+ describe 'for form' do
+ before { visit new_path({model_name: 'field_test'}.merge(params)) }
+ let(:params) { {} }
+
+ it 'is initially blank', js: true do
+ expect(find('[name="field_test[time_field]"]', visible: false).value).to be_blank
+ expect(find('#field_test_time_field').value).to be_blank
+ end
+
+ it 'populates the value selected by the Datetime picker into the hidden_field', js: true do
+ page.execute_script <<-JS
+ $('#field_test_time_field').data("DateTimePicker").date(moment('2000-01-01 14:00:00')).toggle();
+ JS
+ expect(find('#field_test_time_field').value).to eq '14:00'
+ expect(find('[name="field_test[time_field]"]', visible: false).value).to eq "#{Date.today}T14:00:00"
+ end
+
+ it 'populates the value entered in the text field into the hidden_field', js: true do
+ fill_in 'Time field', with: '03:45'
+ expect(find('[name="field_test[time_field]"]', visible: false).value).to eq "#{Date.today}T03:45:00"
+ expect(find('#field_test_time_field').value).to eq '03:45'
+ end
+
+ context 'with locale set' do
+ around(:each) do |example|
+ original = I18n.default_locale
+ I18n.default_locale = :fr
+ example.run
+ I18n.default_locale = original
+ end
+ let(:params) { {field_test: {time_field: '2000-01-01T03:45:00'}} }
+
+ it 'shows and accepts the value in the given locale', js: true do
+ expect(find('[name="field_test[time_field]"]', visible: false).value).to eq '2000-01-01T03:45:00'
+ expect(find('#field_test_time_field').value).to eq "03:45"
+ fill_in 'Time field', with: '04:55'
+ expect(find('[name="field_test[time_field]"]', visible: false).value).to eq "#{Date.today}T04:55:00"
+ end
+ end
+ end
+
+ describe 'for filter' do
+ it 'populates the value selected by the Datetime picker into the hidden_field', js: true do
+ visit index_path(model_name: 'field_test')
+ click_link 'Add filter'
+ click_link 'Time field'
+ expect(find('[name^="f[time_field]"][name$="[v][]"]', match: :first, visible: false).value).to be_blank
+ page.execute_script <<-JS
+ $('.form-control.datetime').data("DateTimePicker").date(moment('2000-01-01 14:00:00')).toggle();
+ JS
+ expect(find('[name^="f[time_field]"][name$="[v][]"]', match: :first, visible: false).value).to eq "#{Date.today}T14:00:00"
+ end
+ end
+ end
+
+ describe 'filtering' do
+ let!(:field_tests) do
+ [FactoryBot.create(:field_test, time_field: DateTime.new(2000, 1, 1, 3, 45)),
+ FactoryBot.create(:field_test, time_field: DateTime.new(2000, 1, 1, 4, 45))]
+ end
+
+ it 'correctly returns a record' do
+ visit index_path(model_name: 'field_test', f: {time_field: {'1' => {v: [nil, '2000-01-01T04:00:00', nil], o: 'between'}}})
+ is_expected.to have_content '1 field test'
+ is_expected.to have_content field_tests[1].id
+ end
+
+ it 'does not break when the condition is not filled' do
+ visit index_path(model_name: 'field_test', f: {time_field: {'1' => {v: [nil, '', ''], o: 'between'}}})
+ is_expected.to have_content '2 field test'
+ end
+
+ context 'with server timezone changed' do
+ around do |example|
+ original = Time.zone
+ Time.zone = ActiveSupport::TimeZone.new('Central Time (US & Canada)')
+ example.run
+ Time.zone = original
+ end
+
+ it 'correctly returns a record' do
+ visit index_path(model_name: 'field_test', f: {time_field: {'1' => {v: [nil, '2000-01-01T22:00:00', nil], o: 'between'}}})
+ is_expected.to have_content '1 field test'
+ is_expected.to have_content field_tests[1].id
+ end
+ end
+ end
+
+ context 'on create' do
+ it 'persists the value' do
+ visit new_path(model_name: 'field_test')
+ find('[name="field_test[time_field]"]', visible: false).set('2021-01-02T03:45:00')
+ click_button 'Save'
+ expect(FieldTest.count).to eq 1
+ expect(FieldTest.first.time_field).to eq DateTime.new(2000, 1, 1, 3, 45)
+ end
+ end
+
+ context 'on update' do
+ let(:field_test) { FactoryBot.create :field_test, time_field: DateTime.new(2021, 1, 2, 3, 45) }
+
+ it 'updates the value' do
+ visit edit_path(model_name: 'field_test', id: field_test.id)
+ expect(find('[name="field_test[time_field]"]', visible: false).value).to eq '2000-01-01T03:45:00'
+ find('[name="field_test[time_field]"]', visible: false).set('2021-02-03T04:55:00')
+ click_button 'Save'
+ field_test.reload
+ expect(field_test.time_field).to eq DateTime.new(2000, 1, 1, 4, 55)
+ end
+ end
+
+ context 'with server timezone changed' do
+ let(:field_test) { FactoryBot.create :field_test, time_field: DateTime.new(2000, 1, 1, 6, 45) }
+
+ around do |example|
+ original = Time.zone
+ Time.zone = ActiveSupport::TimeZone.new('Central Time (US & Canada)')
+ example.run
+ Time.zone = original
+ end
+
+ it 'treats the datetime set by the browser as local time' do
+ visit edit_path(model_name: 'field_test', id: field_test.id)
+ find('[name="field_test[time_field]"]', visible: false).set('2000-01-01T04:55:00')
+ click_button 'Save'
+ field_test.reload
+ expect(field_test.time_field.iso8601).to eq "2000-01-01T04:55:00-06:00"
+ end
+
+ it 'is not altered by just saving untouched' do
+ visit edit_path(model_name: 'field_test', id: field_test.id)
+ expect(find('[name="field_test[time_field]"]', visible: false).value).to eq '2000-01-01T00:45:00'
+ click_button 'Save'
+ expect { field_test.reload }.not_to change(field_test, :time_field)
+ end
+ end
+end
diff --git a/spec/rails_admin/abstract_model_spec.rb b/spec/rails_admin/abstract_model_spec.rb
index c44049032b..e4048b9f86 100644
--- a/spec/rails_admin/abstract_model_spec.rb
+++ b/spec/rails_admin/abstract_model_spec.rb
@@ -74,7 +74,7 @@
end
end
- context 'on dates with :en locale' do
+ context 'on dates' do
before do
[Date.new(2012, 1, 1), Date.new(2012, 1, 2), Date.new(2012, 1, 3), Date.new(2012, 1, 4)].each do |date|
FactoryBot.create(:field_test, date_field: date)
@@ -82,35 +82,30 @@
end
it 'lists elements within outbound limits' do
- expect(@abstract_model.all(filters: {'date_field' => {'1' => {v: ['', 'January 02, 2012', 'January 03, 2012'], o: 'between'}}}).count).to eq(2)
- expect(@abstract_model.all(filters: {'date_field' => {'1' => {v: ['', 'January 02, 2012', 'January 02, 2012'], o: 'between'}}}).count).to eq(1)
- expect(@abstract_model.all(filters: {'date_field' => {'1' => {v: ['', 'January 03, 2012', ''], o: 'between'}}}).count).to eq(2)
- expect(@abstract_model.all(filters: {'date_field' => {'1' => {v: ['', '', 'January 02, 2012'], o: 'between'}}}).count).to eq(2)
- expect(@abstract_model.all(filters: {'date_field' => {'1' => {v: ['January 02, 2012'], o: 'default'}}}).count).to eq(1)
+ expect(@abstract_model.all(filters: {'date_field' => {'1' => {v: ['', '2012-01-02', '2012-01-03'], o: 'between'}}}).count).to eq(2)
+ expect(@abstract_model.all(filters: {'date_field' => {'1' => {v: ['', '2012-01-02', '2012-01-02'], o: 'between'}}}).count).to eq(1)
+ expect(@abstract_model.all(filters: {'date_field' => {'1' => {v: ['', '2012-01-03', ''], o: 'between'}}}).count).to eq(2)
+ expect(@abstract_model.all(filters: {'date_field' => {'1' => {v: ['', '', '2012-01-02'], o: 'between'}}}).count).to eq(2)
+ expect(@abstract_model.all(filters: {'date_field' => {'1' => {v: ['2012-01-02'], o: 'default'}}}).count).to eq(1)
end
end
- context 'on datetimes with :en locale' do
+ context 'on datetimes' do
before do
I18n.locale = :en
FactoryBot.create(:field_test, datetime_field: Time.zone.local(2012, 1, 1, 23, 59, 59))
FactoryBot.create(:field_test, datetime_field: Time.zone.local(2012, 1, 2, 0, 0, 0))
FactoryBot.create(:field_test, datetime_field: Time.zone.local(2012, 1, 3, 23, 59, 59))
-
- # TODO: Mongoid 3.0.0 mysteriously expands the range of inclusion slightly...
- if defined?(Mongoid) && Mongoid::VERSION >= '3.0.0'
- FactoryBot.create(:field_test, datetime_field: Time.zone.local(2012, 1, 4, 0, 0, 1))
- else
- FactoryBot.create(:field_test, datetime_field: Time.zone.local(2012, 1, 4, 0, 0, 0))
- end
+ FactoryBot.create(:field_test, datetime_field: Time.zone.local(2012, 1, 4, 0, 0, 0))
end
it 'lists elements within outbound limits' do
- expect(@abstract_model.all(filters: {'datetime_field' => {'1' => {v: ['', 'January 02, 2012 12:00', 'January 03, 2012 12:00'], o: 'between'}}}).count).to eq(2)
- expect(@abstract_model.all(filters: {'datetime_field' => {'1' => {v: ['', 'January 02, 2012 12:00', 'January 02, 2012 12:00'], o: 'between'}}}).count).to eq(1)
- expect(@abstract_model.all(filters: {'datetime_field' => {'1' => {v: ['', 'January 03, 2012 12:00', ''], o: 'between'}}}).count).to eq(2)
- expect(@abstract_model.all(filters: {'datetime_field' => {'1' => {v: ['', '', 'January 02, 2012 12:00'], o: 'between'}}}).count).to eq(2)
- expect(@abstract_model.all(filters: {'datetime_field' => {'1' => {v: ['January 02, 2012 12:00'], o: 'default'}}}).count).to eq(1)
+ pending('Due to the JRuby SQLite3 datetime boundary issue') if RUBY_ENGINE == 'jruby' && CI_ORM == :active_record
+ expect(@abstract_model.all(filters: {'datetime_field' => {'1' => {v: ['', '2012-01-02T00:00:00', '2012-01-03T23:59:59'], o: 'between'}}}).count).to eq(2)
+ expect(@abstract_model.all(filters: {'datetime_field' => {'1' => {v: ['', '2012-01-02T00:00:00', '2012-01-03T12:00:00'], o: 'between'}}}).count).to eq(1)
+ expect(@abstract_model.all(filters: {'datetime_field' => {'1' => {v: ['', '2012-01-03T12:00:00', ''], o: 'between'}}}).count).to eq(2)
+ expect(@abstract_model.all(filters: {'datetime_field' => {'1' => {v: ['', '', '2012-01-02T12:00:00'], o: 'between'}}}).count).to eq(2)
+ expect(@abstract_model.all(filters: {'datetime_field' => {'1' => {v: ['2012-01-02T00:00:00'], o: 'default'}}}).count).to eq(1)
end
end
end
diff --git a/spec/rails_admin/adapters/active_record_spec.rb b/spec/rails_admin/adapters/active_record_spec.rb
index 59227edc7f..df7d14ddee 100644
--- a/spec/rails_admin/adapters/active_record_spec.rb
+++ b/spec/rails_admin/adapters/active_record_spec.rb
@@ -503,21 +503,37 @@ def build_statement(type, value, operator)
end
end
- describe 'date type queries' do
+ describe 'date/time type queries' do
let(:scope) { FieldTest.all }
it 'supports date type query' do
- expect(predicates_for(abstract_model.send(:filter_scope, scope, 'date_field' => {'1' => {v: ['', 'February 01, 2012', 'March 01, 2012'], o: 'between'}}))).to eq(["(field_tests.date_field BETWEEN '2012-02-01' AND '2012-03-01')"])
- expect(predicates_for(abstract_model.send(:filter_scope, scope, 'date_field' => {'1' => {v: ['', 'March 01, 2012', ''], o: 'between'}}))).to eq(["(field_tests.date_field >= '2012-03-01')"])
- expect(predicates_for(abstract_model.send(:filter_scope, scope, 'date_field' => {'1' => {v: ['', '', 'February 01, 2012'], o: 'between'}}))).to eq(["(field_tests.date_field <= '2012-02-01')"])
- expect(predicates_for(abstract_model.send(:filter_scope, scope, 'date_field' => {'1' => {v: ['February 01, 2012'], o: 'default'}}))).to eq(["(field_tests.date_field BETWEEN '2012-02-01' AND '2012-02-01')"])
+ expect(predicates_for(abstract_model.send(:filter_scope, scope, 'date_field' => {'1' => {v: ['', '2012-02-01', '2012-03-01'], o: 'between'}}))).to eq(["(field_tests.date_field BETWEEN '2012-02-01' AND '2012-03-01')"])
+ expect(predicates_for(abstract_model.send(:filter_scope, scope, 'date_field' => {'1' => {v: ['', '2012-03-01', ''], o: 'between'}}))).to eq(["(field_tests.date_field >= '2012-03-01')"])
+ expect(predicates_for(abstract_model.send(:filter_scope, scope, 'date_field' => {'1' => {v: ['', '', '2012-02-01'], o: 'between'}}))).to eq(["(field_tests.date_field <= '2012-02-01')"])
+ expect(predicates_for(abstract_model.send(:filter_scope, scope, 'date_field' => {'1' => {v: ['2012-02-01'], o: 'default'}}))).to eq(["(field_tests.date_field = '2012-02-01')"])
+ expect(predicates_for(abstract_model.send(:filter_scope, scope, 'date_field' => {'1' => {v: [], o: 'today'}}))).to eq(["(field_tests.date_field = '#{Date.today}')"])
+ expect(predicates_for(abstract_model.send(:filter_scope, scope, 'date_field' => {'1' => {v: [], o: 'yesterday'}}))).to eq(["(field_tests.date_field = '#{Date.yesterday}')"])
+ expect(predicates_for(abstract_model.send(:filter_scope, scope, 'date_field' => {'1' => {v: [], o: 'this_week'}}))).to eq(["(field_tests.date_field BETWEEN '#{Date.today.beginning_of_week}' AND '#{Date.today.end_of_week}')"])
+ expect(predicates_for(abstract_model.send(:filter_scope, scope, 'date_field' => {'1' => {v: [], o: 'last_week'}}))).to eq(["(field_tests.date_field BETWEEN '#{1.week.ago.to_date.beginning_of_week}' AND '#{1.week.ago.to_date.end_of_week}')"])
end
it 'supports datetime type query' do
- expect(predicates_for(abstract_model.send(:filter_scope, scope, 'datetime_field' => {'1' => {v: ['', 'February 01, 2012 12:00', 'March 01, 2012 12:00'], o: 'between'}}))).to eq(predicates_for(scope.where(['(field_tests.datetime_field BETWEEN ? AND ?)', Time.utc(2012, 2, 1), Time.utc(2012, 3, 1).end_of_day])))
- expect(predicates_for(abstract_model.send(:filter_scope, scope, 'datetime_field' => {'1' => {v: ['', 'March 01, 2012 12:00', ''], o: 'between'}}))).to eq(predicates_for(scope.where(['(field_tests.datetime_field >= ?)', Time.utc(2012, 3, 1)])))
- expect(predicates_for(abstract_model.send(:filter_scope, scope, 'datetime_field' => {'1' => {v: ['', '', 'February 01, 2012 12:00'], o: 'between'}}))).to eq(predicates_for(scope.where(['(field_tests.datetime_field <= ?)', Time.utc(2012, 2, 1).end_of_day])))
- expect(predicates_for(abstract_model.send(:filter_scope, scope, 'datetime_field' => {'1' => {v: ['February 01, 2012 12:00'], o: 'default'}}))).to eq(predicates_for(scope.where(['(field_tests.datetime_field BETWEEN ? AND ?)', Time.utc(2012, 2, 1), Time.utc(2012, 2, 1).end_of_day])))
+ expect(predicates_for(abstract_model.send(:filter_scope, scope, 'datetime_field' => {'1' => {v: ['', '2012-02-01T12:00:00', '2012-03-01T12:00:00'], o: 'between'}}))).to eq(["(field_tests.datetime_field BETWEEN '2012-02-01 12:00:00' AND '2012-03-01 12:00:00')"])
+ expect(predicates_for(abstract_model.send(:filter_scope, scope, 'datetime_field' => {'1' => {v: ['', '2012-03-01T12:00:00', ''], o: 'between'}}))).to eq(["(field_tests.datetime_field >= '2012-03-01 12:00:00')"])
+ expect(predicates_for(abstract_model.send(:filter_scope, scope, 'datetime_field' => {'1' => {v: ['', '', '2012-02-01T12:00:00'], o: 'between'}}))).to eq(["(field_tests.datetime_field <= '2012-02-01 12:00:00')"])
+ expect(predicates_for(abstract_model.send(:filter_scope, scope, 'datetime_field' => {'1' => {v: ['2012-02-01T12:00:00'], o: 'default'}}))).to eq(["(field_tests.datetime_field = '2012-02-01 12:00:00')"])
+ expect(predicates_for(abstract_model.send(:filter_scope, scope, 'datetime_field' => {'1' => {v: [], o: 'today'}}))).to eq(["(field_tests.datetime_field BETWEEN '#{Date.today} 00:00:00' AND '#{Date.today} 23:59:59.999999')"])
+ expect(predicates_for(abstract_model.send(:filter_scope, scope, 'datetime_field' => {'1' => {v: [], o: 'yesterday'}}))).to eq(["(field_tests.datetime_field BETWEEN '#{Date.yesterday} 00:00:00' AND '#{Date.yesterday} 23:59:59.999999')"])
+ expect(predicates_for(abstract_model.send(:filter_scope, scope, 'datetime_field' => {'1' => {v: [], o: 'this_week'}}))).to eq(["(field_tests.datetime_field BETWEEN '#{Date.today.beginning_of_week} 00:00:00' AND '#{Date.today.end_of_week} 23:59:59.999999')"])
+ expect(predicates_for(abstract_model.send(:filter_scope, scope, 'datetime_field' => {'1' => {v: [], o: 'last_week'}}))).to eq(["(field_tests.datetime_field BETWEEN '#{1.week.ago.to_date.beginning_of_week} 00:00:00' AND '#{1.week.ago.to_date.end_of_week} 23:59:59.999999')"])
+ end
+
+ it 'supports time type query' do
+ expect(predicates_for(abstract_model.send(:filter_scope, scope, 'time_field' => {'1' => {v: ['', '2000-01-01T12:00:00', '2000-01-01T14:00:00'], o: 'between'}}))).to eq(["(field_tests.time_field BETWEEN '2000-01-01 12:00:00' AND '2000-01-01 14:00:00')"])
+ expect(predicates_for(abstract_model.send(:filter_scope, scope, 'time_field' => {'1' => {v: ['', '2000-01-01T14:00:00', ''], o: 'between'}}))).to eq(["(field_tests.time_field >= '2000-01-01 14:00:00')"])
+ expect(predicates_for(abstract_model.send(:filter_scope, scope, 'time_field' => {'1' => {v: ['', '', '2000-01-01T12:00:00'], o: 'between'}}))).to eq(["(field_tests.time_field <= '2000-01-01 12:00:00')"])
+ expect(predicates_for(abstract_model.send(:filter_scope, scope, 'time_field' => {'1' => {v: ['2000-01-01T12:00:00'], o: 'default'}}))).to eq(["(field_tests.time_field = '2000-01-01 12:00:00')"])
+ expect(predicates_for(abstract_model.send(:filter_scope, scope, 'time_field' => {'1' => {v: ['2021-02-03T12:00:00'], o: 'default'}}))).to eq(["(field_tests.time_field = '2000-01-01 12:00:00')"])
end
end
diff --git a/spec/rails_admin/adapters/mongoid_spec.rb b/spec/rails_admin/adapters/mongoid_spec.rb
index f9f9fe8518..3a72e00085 100644
--- a/spec/rails_admin/adapters/mongoid_spec.rb
+++ b/spec/rails_admin/adapters/mongoid_spec.rb
@@ -127,7 +127,7 @@
RailsAdmin.config Team do
field :players do
queryable true
- searchable :all
+ searchable :name
end
end
@teams = FactoryBot.create_list(:team, 3)
@@ -151,7 +151,7 @@
RailsAdmin.config Team do
field :fans do
queryable true
- searchable :all
+ searchable :name
end
end
@teams = FactoryBot.create_list(:team, 3)
@@ -383,17 +383,25 @@ def parse_value(value)
end
it 'supports date type query' do
- expect(@abstract_model.send(:filter_scope, FieldTest, 'date_field' => {'1' => {v: ['', 'January 02, 2012', 'January 03, 2012'], o: 'between'}}).selector).to eq('$and' => [{'date_field' => {'$gte' => Date.new(2012, 1, 2), '$lte' => Date.new(2012, 1, 3)}}])
- expect(@abstract_model.send(:filter_scope, FieldTest, 'date_field' => {'1' => {v: ['', 'January 03, 2012', ''], o: 'between'}}).selector).to eq('$and' => [{'date_field' => {'$gte' => Date.new(2012, 1, 3)}}])
- expect(@abstract_model.send(:filter_scope, FieldTest, 'date_field' => {'1' => {v: ['', '', 'January 02, 2012'], o: 'between'}}).selector).to eq('$and' => [{'date_field' => {'$lte' => Date.new(2012, 1, 2)}}])
- expect(@abstract_model.send(:filter_scope, FieldTest, 'date_field' => {'1' => {v: ['January 02, 2012'], o: 'default'}}).selector).to eq('$and' => [{'date_field' => {'$gte' => Date.new(2012, 1, 2), '$lte' => Date.new(2012, 1, 2)}}])
+ expect(@abstract_model.send(:filter_scope, FieldTest, 'date_field' => {'1' => {v: ['', '2012-01-02', '2012-01-03'], o: 'between'}}).selector).to eq('$and' => [{'date_field' => {'$gte' => Date.new(2012, 1, 2), '$lte' => Date.new(2012, 1, 3)}}])
+ expect(@abstract_model.send(:filter_scope, FieldTest, 'date_field' => {'1' => {v: ['', '2012-01-03', ''], o: 'between'}}).selector).to eq('$and' => [{'date_field' => {'$gte' => Date.new(2012, 1, 3)}}])
+ expect(@abstract_model.send(:filter_scope, FieldTest, 'date_field' => {'1' => {v: ['', '', '2012-01-02'], o: 'between'}}).selector).to eq('$and' => [{'date_field' => {'$lte' => Date.new(2012, 1, 2)}}])
+ expect(@abstract_model.send(:filter_scope, FieldTest, 'date_field' => {'1' => {v: ['2012-01-02'], o: 'default'}}).selector).to eq('$and' => [{'date_field' => Date.new(2012, 1, 2)}])
+ expect(@abstract_model.send(:filter_scope, FieldTest, 'date_field' => {'1' => {v: [], o: 'today'}}).selector).to eq('$and' => [{'date_field' => Date.today}])
+ expect(@abstract_model.send(:filter_scope, FieldTest, 'date_field' => {'1' => {v: [], o: 'yesterday'}}).selector).to eq('$and' => [{'date_field' => Date.yesterday}])
+ expect(@abstract_model.send(:filter_scope, FieldTest, 'date_field' => {'1' => {v: [], o: 'this_week'}}).selector).to eq('$and' => [{'date_field' => {'$gte' => Date.today.beginning_of_week, '$lte' => Date.today.end_of_week}}])
+ expect(@abstract_model.send(:filter_scope, FieldTest, 'date_field' => {'1' => {v: [], o: 'last_week'}}).selector).to eq('$and' => [{'date_field' => {'$gte' => 1.week.ago.to_date.beginning_of_week, '$lte' => 1.week.ago.to_date.end_of_week}}])
end
it 'supports datetime type query' do
- expect(@abstract_model.send(:filter_scope, FieldTest, 'datetime_field' => {'1' => {v: ['', 'January 02, 2012 00:00', 'January 03, 2012 00:00'], o: 'between'}}).selector).to eq('$and' => [{'datetime_field' => {'$gte' => Time.zone.local(2012, 1, 2), '$lte' => Time.zone.local(2012, 1, 3).end_of_day}}])
- expect(@abstract_model.send(:filter_scope, FieldTest, 'datetime_field' => {'1' => {v: ['', 'January 03, 2012 00:00', ''], o: 'between'}}).selector).to eq('$and' => [{'datetime_field' => {'$gte' => Time.zone.local(2012, 1, 3)}}])
- expect(@abstract_model.send(:filter_scope, FieldTest, 'datetime_field' => {'1' => {v: ['', '', 'January 02, 2012 00:00'], o: 'between'}}).selector).to eq('$and' => [{'datetime_field' => {'$lte' => Time.zone.local(2012, 1, 2).end_of_day}}])
- expect(@abstract_model.send(:filter_scope, FieldTest, 'datetime_field' => {'1' => {v: ['January 02, 2012 00:00'], o: 'default'}}).selector).to eq('$and' => [{'datetime_field' => {'$gte' => Time.zone.local(2012, 1, 2), '$lte' => Time.zone.local(2012, 1, 2).end_of_day}}])
+ expect(@abstract_model.send(:filter_scope, FieldTest, 'datetime_field' => {'1' => {v: ['', '2012-01-02T12:00:00', '2012-01-03T12:00:00'], o: 'between'}}).selector).to eq('$and' => [{'datetime_field' => {'$gte' => Time.zone.local(2012, 1, 2, 12), '$lte' => Time.zone.local(2012, 1, 3, 12)}}])
+ expect(@abstract_model.send(:filter_scope, FieldTest, 'datetime_field' => {'1' => {v: ['', '2012-01-03T12:00:00', ''], o: 'between'}}).selector).to eq('$and' => [{'datetime_field' => {'$gte' => Time.zone.local(2012, 1, 3, 12)}}])
+ expect(@abstract_model.send(:filter_scope, FieldTest, 'datetime_field' => {'1' => {v: ['', '', '2012-01-02T12:00:00'], o: 'between'}}).selector).to eq('$and' => [{'datetime_field' => {'$lte' => Time.zone.local(2012, 1, 2, 12)}}])
+ expect(@abstract_model.send(:filter_scope, FieldTest, 'datetime_field' => {'1' => {v: ['2012-01-02T12:00:00'], o: 'default'}}).selector).to eq('$and' => [{'datetime_field' => Time.zone.local(2012, 1, 2, 12)}])
+ expect(@abstract_model.send(:filter_scope, FieldTest, 'datetime_field' => {'1' => {v: [], o: 'today'}}).selector).to eq('$and' => [{'datetime_field' => {'$gte' => Date.today.beginning_of_day, '$lte' => Date.today.end_of_day}}])
+ expect(@abstract_model.send(:filter_scope, FieldTest, 'datetime_field' => {'1' => {v: [], o: 'yesterday'}}).selector).to eq('$and' => [{'datetime_field' => {'$gte' => Date.yesterday.beginning_of_day, '$lte' => Date.yesterday.end_of_day}}])
+ expect(@abstract_model.send(:filter_scope, FieldTest, 'datetime_field' => {'1' => {v: [], o: 'this_week'}}).selector).to eq('$and' => [{'datetime_field' => {'$gte' => Date.today.beginning_of_week.beginning_of_day, '$lte' => Date.today.end_of_week.end_of_day}}])
+ expect(@abstract_model.send(:filter_scope, FieldTest, 'datetime_field' => {'1' => {v: [], o: 'last_week'}}).selector).to eq('$and' => [{'datetime_field' => {'$gte' => 1.week.ago.to_date.beginning_of_week.beginning_of_day, '$lte' => 1.week.ago.to_date.end_of_week.end_of_day}}])
end
it 'supports enum type query' do
diff --git a/spec/rails_admin/config/fields/types/time_spec.rb b/spec/rails_admin/config/fields/types/time_spec.rb
index ceb0ec5746..3ba6a6420e 100644
--- a/spec/rails_admin/config/fields/types/time_spec.rb
+++ b/spec/rails_admin/config/fields/types/time_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-RSpec.describe RailsAdmin::Config::Fields::Types::Time do
+RSpec.describe RailsAdmin::Config::Fields::Types::Time, active_record: true do
it_behaves_like 'a generic field type', :time_field, :time
describe '#parse_input' do
@@ -18,7 +18,7 @@
before :each do
@object = FactoryBot.create(:field_test)
- @time = ::Time.now.getutc
+ @time = ::Time.new(2000, 1, 1, 3, 45)
end
after :each do
@@ -30,10 +30,10 @@
expect(@object.time_field.strftime('%H:%M')).to eq(@time.strftime('%H:%M'))
end
- it 'interprets time value as UTC when timezone is specified' do
+ it 'interprets time value as local time when timezone is specified' do
Time.zone = 'Eastern Time (US & Canada)' # -05:00
- @object.time_field = field.parse_input(time_field: @time.strftime('%H:%M'))
- expect(@object.time_field.utc.strftime('%H:%M')).to eq(@time.strftime('%H:%M'))
+ @object.time_field = field.parse_input(time_field: '2000-01-01T03:45:00')
+ expect(@object.time_field.strftime('%H:%M')).to eq('03:45')
end
context 'with a custom strftime_format' do
diff --git a/spec/rails_admin/support/datetime_spec.rb b/spec/rails_admin/support/datetime_spec.rb
index cc404d74f3..c36ce3ef38 100644
--- a/spec/rails_admin/support/datetime_spec.rb
+++ b/spec/rails_admin/support/datetime_spec.rb
@@ -11,8 +11,7 @@
'%-d %B %Y' => 'D MMMM YYYY',
}.each do |strftime_format, momentjs_format|
it "convert strftime_format to momentjs_format - example #{strftime_format}" do
- strftime_format = RailsAdmin::Support::Datetime.new(strftime_format)
- expect(strftime_format.to_momentjs).to eq momentjs_format
+ expect(RailsAdmin::Support::Datetime.to_momentjs(strftime_format)).to eq momentjs_format
end
end
end