ruby '>= 2.7.0', '< 3.3.0'
-gem 'rails', '6.1.7.6'
+gem 'rails', '7.1.2'
gem 'rouge', '~> 4.2.0'
gem 'mini_mime', '~> 1.1.0'
gem "actionpack-xml_parser"
warn("Please configure your config/database.yml first")
end
+group :development, :test do
+ gem 'debug'
+end
+
group :development do
gem 'listen', '~> 3.3'
gem 'yard', require: false
def upload
# Make sure that API users get used to set this content type
# as it won't trigger Rails' automatic parsing of the request body for parameters
- unless request.content_type == 'application/octet-stream'
+ unless request.media_type == 'application/octet-stream'
head 406
return
end
when Array
formatted_objects = object.map {|o| format_object(o, html)}
html ? safe_join(formatted_objects, ', ') : formatted_objects.join(', ')
- when Time
+ when Time, ActiveSupport::TimeWithZone
format_time(object)
when Date
format_date(object)
'span', nil,
:class => "name icon icon-#{principal.class.name.downcase}"
)
- ) + principal
+ ) + principal.to_s
)
end
s.html_safe
# })
#
def self.update_attachments(attachments, params)
- params = params.transform_keys {|key| key.to_i}
-
+ converted = {}
+ params.each {|key, val| converted[key.to_i] = val}
saved = true
transaction do
attachments.each do |attachment|
- if p = params[attachment.id]
- attachment.filename = p[:filename] if p.key?(:filename)
- attachment.description = p[:description] if p.key?(:description)
+ if file = converted[attachment.id]
+ attachment.filename = file[:filename] if file.key?(:filename)
+ attachment.description = file[:description] if file.key?(:description)
saved &&= attachment.save
end
end
has_and_belongs_to_many :roles, :join_table => "#{table_name_prefix}queries_roles#{table_name_suffix}", :foreign_key => "query_id"
serialize :filters
serialize :column_names
- serialize :sort_criteria, Array
- serialize :options, Hash
+ serialize :sort_criteria, type: Array
+ serialize :options, type: Hash
validates_presence_of :name
validates_length_of :name, :maximum => 255
else
from = from - 1 # second
end
- if self.class.default_timezone == :utc
+ if ActiveRecord.default_timezone == :utc
from = from.utc
end
s << ("#{table}.#{field} > '%s'" % [quoted_time(from, is_custom_filter)])
if to.is_a?(Date)
to = date_for_user_time_zone(to.year, to.month, to.day).end_of_day
end
- if self.class.default_timezone == :utc
+ if ActiveRecord.default_timezone == :utc
to = to.utc
end
s << ("#{table}.#{field} <= '%s'" % [quoted_time(to, is_custom_filter)])
has_many :members, :through => :member_roles
acts_as_positioned :scope => :builtin
- serialize :permissions, ::Role::PermissionsAttributeCoder
+ serialize :permissions, coder: ::Role::PermissionsAttributeCoder
store :settings, :accessors => [:permissions_all_trackers, :permissions_tracker_ids]
validates_presence_of :name
<div id="custom_field_project_ids">
<% project_ids = @custom_field.project_ids.to_a %>
<%= render_project_nested_lists(Project.all) do |p|
- content_tag('label', check_box_tag('custom_field[project_ids][]', p.id, project_ids.include?(p.id), :id => nil) + ' ' + p)
+ content_tag('label', check_box_tag('custom_field[project_ids][]', p.id, project_ids.include?(p.id), :id => nil) + ' ' + p.to_s)
end %>
<%= hidden_field_tag('custom_field[project_ids][]', '', :id => nil) %>
</div>
# Application configuration should go into files in config/initializers
# -- all .rb files in that directory are automatically loaded.
- # Custom directories with classes and modules you want to be autoloadable.
- config.autoloader = :zeitwerk
+ # Adds `lib` to `config.autoload_paths` and `config.eager_load_paths`.
+ config.autoload_lib(ignore: %w(tasks generators plugins))
# Only load the plugins named here, in the order given (default is alphabetical).
# :all can be used as a placeholder for all plugins not explicitly named.
# config.plugins = [ :exception_notification, :ssl_requirement, :all ]
+ config.active_support.remove_deprecated_time_with_zone_name = true
+ config.active_support.cache_format_version = 7.0
+
config.active_record.store_full_sti_class = true
config.active_record.default_timezone = :local
config.active_record.yaml_column_permitted_classes = [
config.cache_store = :null_store
# Raise exceptions instead of rendering exception templates.
- config.action_dispatch.show_exceptions = true
+ config.action_dispatch.show_exceptions = :all
# Disable request forgery protection in test environment.
config.action_controller.allow_forgery_protection = false
end
end
end
-
- class Resolver
- def find_all(name, prefix=nil, partial=false, details={}, key=nil, locals=[])
- locals = locals.map(&:to_s).sort!.freeze
-
- cached(key, [name, prefix, partial], details, locals) do
- if (details[:formats] & [:xml, :json]).any?
- details = details.dup
- details[:formats] = details[:formats].dup + [:api]
- end
- _find_all(name, prefix, partial, details, key, locals)
- end
- end
- end
end
ActionView::Base.field_error_proc = Proc.new{ |html_tag, instance| html_tag || ''.html_safe }
module ActionView
module Helpers
module Tags
- class Base
- private
- alias :add_options_without_non_empty_blank_option :add_options
+ SelectRenderer.prepend(Module.new do
def add_options(option_tags, options, value = nil)
- if options[:include_blank] == true
- options = options.dup
- options[:include_blank] = ' '.html_safe
+ if options.delete(:include_blank)
+ options[:prompt] = ' '.html_safe
end
- add_options_without_non_empty_blank_option(option_tags, options, value)
+ super
end
- end
+ end)
end
module FormHelper
end
end
+module ActionView
+ LookupContext.prepend(Module.new do
+ def formats=(values)
+ if (Array(values) & [:xml, :json]).any?
+ values << :api
+ end
+ super values
+ end
+ end)
+
+ Rendering.prepend(Module.new do
+ def rendered_format
+ if lookup_context.formats.first == :api
+ return request.format
+ end
+
+ super
+ end
+ end)
+end
+
+Mime::SET << 'api'
+
# Adds asset_id parameters to assets like Rails 3 to invalidate caches in browser
module ActionView
module Helpers
# frozen_string_literal: true
lib = Rails.root.join('lib/redmine')
-Rails.autoloaders.main.push_dir lib, namespace: Redmine
-Rails.application.config.watchable_dirs[lib] = [:rb]
-
IGNORE_LIST = [
'wiki_formatting/textile/redcloth3.rb',
'core_ext.rb',
else
migrations
end
- Migrator.new(:up, selected_migrations, schema_migration, target_version).migrate
+ Migrator.new(:up, selected_migrations, schema_migration, internal_metadata, target_version).migrate
end
def down(target_version = nil)
else
migrations
end
- Migrator.new(:down, selected_migrations, schema_migration, target_version).migrate
+ Migrator.new(:down, selected_migrations, schema_migration, internal_metadata, target_version).migrate
end
def run(direction, target_version)
- Migrator.new(direction, migrations, schema_migration, target_version).run
+ Migrator.new(direction, migrations, schema_migration, internal_metadata, target_version).run
end
def open
- Migrator.new(:up, migrations, schema_migration)
+ Migrator.new(:up, migrations, schema_migration, internal_metadata)
end
def current_version
# Delete migrations that don't match .. to_i will work because the number comes first
@all_versions ||= {}
@all_versions[plugin.id.to_s] ||= begin
- sm_table = ::ActiveRecord::SchemaMigration.table_name
+ sm_table = ::ActiveRecord::Base.connection.schema_migration.table_name
migration_versions = ActiveRecord::Base.connection.select_values("SELECT version FROM #{sm_table}")
versions_by_plugins = migration_versions.group_by {|version| version.match(/-(.*)$/).try(:[], 1)}
@all_versions = versions_by_plugins.transform_values! {|versions| versions.map!(&:to_i).sort!}
---
issues_001:
- created_on: <%= 3.days.ago.to_s(:db) %>
+ created_on: <%= 3.days.ago.to_fs(:db) %>
project_id: 1
- updated_on: <%= 1.day.ago.to_s(:db) %>
+ updated_on: <%= 1.day.ago.to_fs(:db) %>
priority_id: 4
subject: Cannot print recipes
id: 1
assigned_to_id:
author_id: 2
status_id: 1
- start_date: <%= 1.day.ago.to_date.to_s(:db) %>
- due_date: <%= 10.day.from_now.to_date.to_s(:db) %>
+ start_date: <%= 1.day.ago.to_date.to_fs(:db) %>
+ due_date: <%= 10.day.from_now.to_date.to_fs(:db) %>
estimated_hours: 200.0
root_id: 1
lft: 1
assigned_to_id: 3
author_id: 2
status_id: 2
- start_date: <%= 2.day.ago.to_date.to_s(:db) %>
+ start_date: <%= 2.day.ago.to_date.to_fs(:db) %>
due_date:
estimated_hours: 0.5
root_id: 2
assigned_to_id: 3
author_id: 2
status_id: 1
- start_date: <%= 15.day.ago.to_date.to_s(:db) %>
- due_date: <%= 5.day.ago.to_date.to_s(:db) %>
+ start_date: <%= 15.day.ago.to_date.to_fs(:db) %>
+ due_date: <%= 5.day.ago.to_date.to_fs(:db) %>
estimated_hours: 1.0
root_id: 3
lft: 1
rgt: 2
issues_004:
- created_on: <%= 5.days.ago.to_s(:db) %>
+ created_on: <%= 5.days.ago.to_fs(:db) %>
project_id: 2
- updated_on: <%= 2.days.ago.to_s(:db) %>
+ updated_on: <%= 2.days.ago.to_fs(:db) %>
priority_id: 4
subject: Issue on project 2
id: 4
lft: 1
rgt: 2
issues_005:
- created_on: <%= 5.days.ago.to_s(:db) %>
+ created_on: <%= 5.days.ago.to_fs(:db) %>
project_id: 3
- updated_on: <%= 2.days.ago.to_s(:db) %>
+ updated_on: <%= 2.days.ago.to_fs(:db) %>
priority_id: 4
subject: Subproject issue
id: 5
lft: 1
rgt: 2
issues_006:
- created_on: <%= 1.minute.ago.to_s(:db) %>
+ created_on: <%= 1.minute.ago.to_fs(:db) %>
project_id: 5
- updated_on: <%= 1.minute.ago.to_s(:db) %>
+ updated_on: <%= 1.minute.ago.to_fs(:db) %>
priority_id: 4
subject: Issue of a private subproject
id: 6
assigned_to_id:
author_id: 2
status_id: 1
- start_date: <%= Date.today.to_s(:db) %>
- due_date: <%= 1.days.from_now.to_date.to_s(:db) %>
+ start_date: <%= Date.today.to_fs(:db) %>
+ due_date: <%= 1.days.from_now.to_date.to_fs(:db) %>
root_id: 6
lft: 1
rgt: 2
issues_007:
- created_on: <%= 10.days.ago.to_s(:db) %>
+ created_on: <%= 10.days.ago.to_fs(:db) %>
project_id: 1
- updated_on: <%= 10.days.ago.to_s(:db) %>
+ updated_on: <%= 10.days.ago.to_fs(:db) %>
priority_id: 5
subject: Issue due today
id: 7
assigned_to_id:
author_id: 2
status_id: 1
- start_date: <%= 10.days.ago.to_s(:db) %>
- due_date: <%= Date.today.to_s(:db) %>
+ start_date: <%= 10.days.ago.to_fs(:db) %>
+ due_date: <%= Date.today.to_fs(:db) %>
lock_version: 0
root_id: 7
lft: 1
rgt: 2
issues_008:
- created_on: <%= 10.days.ago.to_s(:db) %>
+ created_on: <%= 10.days.ago.to_fs(:db) %>
project_id: 1
- updated_on: <%= 10.days.ago.to_s(:db) %>
+ updated_on: <%= 10.days.ago.to_fs(:db) %>
priority_id: 5
subject: Closed issue
id: 8
root_id: 8
lft: 1
rgt: 2
- closed_on: <%= 3.days.ago.to_s(:db) %>
+ closed_on: <%= 3.days.ago.to_fs(:db) %>
issues_009:
- created_on: <%= 1.minute.ago.to_s(:db) %>
+ created_on: <%= 1.minute.ago.to_fs(:db) %>
project_id: 5
- updated_on: <%= 1.minute.ago.to_s(:db) %>
+ updated_on: <%= 1.minute.ago.to_fs(:db) %>
priority_id: 5
subject: Blocked Issue
id: 9
assigned_to_id:
author_id: 2
status_id: 1
- start_date: <%= Date.today.to_s(:db) %>
- due_date: <%= 1.days.from_now.to_date.to_s(:db) %>
+ start_date: <%= Date.today.to_fs(:db) %>
+ due_date: <%= 1.days.from_now.to_date.to_fs(:db) %>
root_id: 9
lft: 1
rgt: 2
issues_010:
- created_on: <%= 1.minute.ago.to_s(:db) %>
+ created_on: <%= 1.minute.ago.to_fs(:db) %>
project_id: 5
- updated_on: <%= 1.minute.ago.to_s(:db) %>
+ updated_on: <%= 1.minute.ago.to_fs(:db) %>
priority_id: 5
subject: Issue Doing the Blocking
id: 10
assigned_to_id:
author_id: 2
status_id: 1
- start_date: <%= Date.today.to_s(:db) %>
- due_date: <%= 1.days.from_now.to_date.to_s(:db) %>
+ start_date: <%= Date.today.to_fs(:db) %>
+ due_date: <%= 1.days.from_now.to_date.to_fs(:db) %>
root_id: 10
lft: 1
rgt: 2
issues_011:
- created_on: <%= 3.days.ago.to_s(:db) %>
+ created_on: <%= 3.days.ago.to_fs(:db) %>
project_id: 1
- updated_on: <%= 1.day.ago.to_s(:db) %>
+ updated_on: <%= 1.day.ago.to_fs(:db) %>
priority_id: 5
subject: Closed issue on a closed version
id: 11
assigned_to_id:
author_id: 2
status_id: 5
- start_date: <%= 1.day.ago.to_date.to_s(:db) %>
+ start_date: <%= 1.day.ago.to_date.to_fs(:db) %>
due_date:
root_id: 11
lft: 1
rgt: 2
- closed_on: <%= 1.day.ago.to_s(:db) %>
+ closed_on: <%= 1.day.ago.to_fs(:db) %>
issues_012:
- created_on: <%= 3.days.ago.to_s(:db) %>
+ created_on: <%= 3.days.ago.to_fs(:db) %>
project_id: 1
- updated_on: <%= 1.day.ago.to_s(:db) %>
+ updated_on: <%= 1.day.ago.to_fs(:db) %>
priority_id: 5
subject: Closed issue on a locked version
id: 12
assigned_to_id:
author_id: 3
status_id: 5
- start_date: <%= 1.day.ago.to_date.to_s(:db) %>
+ start_date: <%= 1.day.ago.to_date.to_fs(:db) %>
due_date:
root_id: 12
lft: 1
rgt: 2
- closed_on: <%= 1.day.ago.to_s(:db) %>
+ closed_on: <%= 1.day.ago.to_fs(:db) %>
issues_013:
- created_on: <%= 5.days.ago.to_s(:db) %>
+ created_on: <%= 5.days.ago.to_fs(:db) %>
project_id: 3
- updated_on: <%= 2.days.ago.to_s(:db) %>
+ updated_on: <%= 2.days.ago.to_fs(:db) %>
priority_id: 4
subject: Subproject issue two
id: 13
rgt: 2
issues_014:
id: 14
- created_on: <%= 15.days.ago.to_s(:db) %>
+ created_on: <%= 15.days.ago.to_fs(:db) %>
project_id: 3
- updated_on: <%= 15.days.ago.to_s(:db) %>
+ updated_on: <%= 15.days.ago.to_fs(:db) %>
priority_id: 5
subject: Private issue on public project
fixed_version_id:
---
journals_001:
- created_on: <%= 2.days.ago.to_date.to_s(:db) %>
- updated_on: <%= 1.days.ago.to_date.to_s(:db) %>
+ created_on: <%= 2.days.ago.to_date.to_fs(:db) %>
+ updated_on: <%= 1.days.ago.to_date.to_fs(:db) %>
notes: "Journal notes"
id: 1
journalized_type: Issue
journalized_id: 1
updated_by_id: 1
journals_002:
- created_on: <%= 1.days.ago.to_date.to_s(:db) %>
- updated_on: <%= 1.days.ago.to_date.to_s(:db) %>
+ created_on: <%= 1.days.ago.to_date.to_fs(:db) %>
+ updated_on: <%= 1.days.ago.to_date.to_fs(:db) %>
notes: "Some notes with Redmine links: #2, r2."
id: 2
journalized_type: Issue
user_id: 2
journalized_id: 1
journals_003:
- created_on: <%= 1.days.ago.to_date.to_s(:db) %>
- updated_on: <%= 1.days.ago.to_date.to_s(:db) %>
+ created_on: <%= 1.days.ago.to_date.to_fs(:db) %>
+ updated_on: <%= 1.days.ago.to_date.to_fs(:db) %>
notes: "A comment with inline image: !picture.jpg! and a reference to #1 and r2."
id: 3
journalized_type: Issue
user_id: 2
journalized_id: 2
journals_004:
- created_on: <%= 1.days.ago.to_date.to_s(:db) %>
- updated_on: <%= 1.days.ago.to_date.to_s(:db) %>
+ created_on: <%= 1.days.ago.to_date.to_fs(:db) %>
+ updated_on: <%= 1.days.ago.to_date.to_fs(:db) %>
notes: "A comment with a private version."
id: 4
journalized_type: Issue
journalized_id: 6
journals_005:
id: 5
- created_on: <%= 1.days.ago.to_date.to_s(:db) %>
- updated_on: <%= 1.days.ago.to_date.to_s(:db) %>
+ created_on: <%= 1.days.ago.to_date.to_fs(:db) %>
+ updated_on: <%= 1.days.ago.to_date.to_fs(:db) %>
notes: "A comment on a private issue."
user_id: 2
journalized_type: Issue
parent_id:
board_id: 1
messages_005:
- created_on: <%= 3.days.ago.to_date.to_s(:db) %>
- updated_on: <%= 3.days.ago.to_date.to_s(:db) %>
+ created_on: <%= 3.days.ago.to_date.to_fs(:db) %>
+ updated_on: <%= 3.days.ago.to_date.to_fs(:db) %>
subject: 'RE: post 2'
id: 5
replies_count: 0
parent_id: 4
board_id: 1
messages_006:
- created_on: <%= 2.days.ago.to_date.to_s(:db) %>
- updated_on: <%= 2.days.ago.to_date.to_s(:db) %>
+ created_on: <%= 2.days.ago.to_date.to_fs(:db) %>
+ updated_on: <%= 2.days.ago.to_date.to_fs(:db) %>
subject: 'RE: post 2'
id: 6
replies_count: 0
parent_id: 4
board_id: 1
messages_007:
- created_on: <%= 2.days.ago.to_date.to_s(:db) %>
- updated_on: <%= 2.days.ago.to_date.to_s(:db) %>
+ created_on: <%= 2.days.ago.to_date.to_fs(:db) %>
+ updated_on: <%= 2.days.ago.to_date.to_fs(:db) %>
subject: 'Message on a private project'
id: 7
replies_count: 0
updated_on: 2006-07-19 21:00:33 +02:00
id: 2
description: Stable release
- effective_date: <%= 20.day.from_now.to_date.to_s(:db) %>
+ effective_date: <%= 20.day.from_now.to_date.to_fs(:db) %>
status: locked
sharing: 'none'
wiki_page_title: ECookBookV1
def test_top_menu_and_search_not_visible_when_login_required
with_settings :login_required => '1' do
get '/'
- assert_select "#top-menu > ul", 0
- assert_select "#quick-search", 0
+
+ assert_equal response.status, 302
end
end
query = IssueQuery.new(:name => '_')
filter_name = "fixed_version.due_date"
assert_include filter_name, query.available_filters.keys
- query.filters = {filter_name => {:operator => '=', :values => [20.day.from_now.to_date.to_s(:db)]}}
+ query.filters = {filter_name => {:operator => '=', :values => [20.day.from_now.to_date.to_fs(:db)]}}
issues = find_issues_with_query(query)
assert_equal [2], issues.map(&:fixed_version_id).uniq.sort
assert_equal [2, 12], issues.map(&:id).sort
query = IssueQuery.new(:name => '_')
- query.filters = {filter_name => {:operator => '>=', :values => [21.day.from_now.to_date.to_s(:db)]}}
+ query.filters = {filter_name => {:operator => '>=', :values => [21.day.from_now.to_date.to_fs(:db)]}}
assert_equal 0, find_issues_with_query(query).size
end
User.current.pref.update_attribute :time_zone, 'Hawaii'
# assume timestamps are stored as utc
- ActiveRecord::Base.default_timezone = :utc
+ ActiveRecord.default_timezone = :utc
from = Date.parse '2016-03-20'
to = Date.parse '2016-03-22'
t = Time.new(2016, 3, 23, 9, 59, 59, 0).end_of_hour
assert_equal "table.field > '#{Query.connection.quoted_date f}' AND table.field <= '#{Query.connection.quoted_date t}'", c
ensure
- ActiveRecord::Base.default_timezone = :local # restore Redmine default
+ ActiveRecord.default_timezone = :local # restore Redmine default
end
def test_project_statement_with_closed_subprojects
users = q.results_scope
assert_equal 2, users.size
- assert_equal [2, 1], users.ids
+ assert_equal [2, 1], users.pluck(:id)
end
def find_users_with_query(query)