##// END OF EJS Templates
Support of default Active Record (I18n) transliteration paths (#22383)....
Jean-Philippe Lang -
r14948:223141a20b27
parent child
Show More
@@ -1,180 +1,194
1 1 require 'active_record'
2 2
3 3 module ActiveRecord
4 4 class Base
5 5 include Redmine::I18n
6 6 # Translate attribute names for validation errors display
7 def self.human_attribute_name(attr, *args)
8 attr = attr.to_s.sub(/_id$/, '').sub(/^.+\./, '')
9 l("field_#{name.underscore.gsub('/', '_')}_#{attr}", :default => ["field_#{attr}".to_sym, attr])
7 def self.human_attribute_name(attr, options = {})
8 prepared_attr = attr.to_s.sub(/_id$/, '').sub(/^.+\./, '')
9
10 redmine_default =
11 [
12 :"field_#{name.underscore.gsub('/', '_')}_#{prepared_attr}",
13 :"field_#{prepared_attr}"
14 ]
15
16 if options[:default].present?
17 options[:default] = [options[:default]] unless options[:default].is_a? Array
18 options[:default].unshift redmine_default
19 else
20 options[:default] = redmine_default
21 end
22
23 super
10 24 end
11 25 end
12 26
13 27 # Undefines private Kernel#open method to allow using `open` scopes in models.
14 28 # See Defect #11545 (http://www.redmine.org/issues/11545) for details.
15 29 class Base
16 30 class << self
17 31 undef open
18 32 end
19 33 end
20 34 class Relation ; undef open ; end
21 35 end
22 36
23 37 module ActionView
24 38 module Helpers
25 39 module DateHelper
26 40 # distance_of_time_in_words breaks when difference is greater than 30 years
27 41 def distance_of_date_in_words(from_date, to_date = 0, options = {})
28 42 from_date = from_date.to_date if from_date.respond_to?(:to_date)
29 43 to_date = to_date.to_date if to_date.respond_to?(:to_date)
30 44 distance_in_days = (to_date - from_date).abs
31 45
32 46 I18n.with_options :locale => options[:locale], :scope => :'datetime.distance_in_words' do |locale|
33 47 case distance_in_days
34 48 when 0..60 then locale.t :x_days, :count => distance_in_days.round
35 49 when 61..720 then locale.t :about_x_months, :count => (distance_in_days / 30).round
36 50 else locale.t :over_x_years, :count => (distance_in_days / 365).floor
37 51 end
38 52 end
39 53 end
40 54 end
41 55 end
42 56
43 57 class Resolver
44 58 def find_all(name, prefix=nil, partial=false, details={}, key=nil, locals=[])
45 59 cached(key, [name, prefix, partial], details, locals) do
46 60 if (details[:formats] & [:xml, :json]).any?
47 61 details = details.dup
48 62 details[:formats] = details[:formats].dup + [:api]
49 63 end
50 64 find_templates(name, prefix, partial, details)
51 65 end
52 66 end
53 67 end
54 68 end
55 69
56 70 ActionView::Base.field_error_proc = Proc.new{ |html_tag, instance| html_tag || ''.html_safe }
57 71
58 72 # HTML5: <option value=""></option> is invalid, use <option value="">&nbsp;</option> instead
59 73 module ActionView
60 74 module Helpers
61 75 module Tags
62 76 class Base
63 77 private
64 78 def add_options_with_non_empty_blank_option(option_tags, options, value = nil)
65 79 if options[:include_blank] == true
66 80 options = options.dup
67 81 options[:include_blank] = '&nbsp;'.html_safe
68 82 end
69 83 add_options_without_non_empty_blank_option(option_tags, options, value)
70 84 end
71 85 alias_method_chain :add_options, :non_empty_blank_option
72 86 end
73 87 end
74 88
75 89 module FormTagHelper
76 90 def select_tag_with_non_empty_blank_option(name, option_tags = nil, options = {})
77 91 if options.delete(:include_blank)
78 92 options[:prompt] = '&nbsp;'.html_safe
79 93 end
80 94 select_tag_without_non_empty_blank_option(name, option_tags, options)
81 95 end
82 96 alias_method_chain :select_tag, :non_empty_blank_option
83 97 end
84 98
85 99 module FormOptionsHelper
86 100 def options_for_select_with_non_empty_blank_option(container, selected = nil)
87 101 if container.is_a?(Array)
88 102 container = container.map {|element| element.blank? ? ["&nbsp;".html_safe, ""] : element}
89 103 end
90 104 options_for_select_without_non_empty_blank_option(container, selected)
91 105 end
92 106 alias_method_chain :options_for_select, :non_empty_blank_option
93 107 end
94 108 end
95 109 end
96 110
97 111 require 'mail'
98 112
99 113 module DeliveryMethods
100 114 class AsyncSMTP < ::Mail::SMTP
101 115 def deliver!(*args)
102 116 Thread.start do
103 117 super *args
104 118 end
105 119 end
106 120 end
107 121
108 122 class AsyncSendmail < ::Mail::Sendmail
109 123 def deliver!(*args)
110 124 Thread.start do
111 125 super *args
112 126 end
113 127 end
114 128 end
115 129
116 130 class TmpFile
117 131 def initialize(*args); end
118 132
119 133 def deliver!(mail)
120 134 dest_dir = File.join(Rails.root, 'tmp', 'emails')
121 135 Dir.mkdir(dest_dir) unless File.directory?(dest_dir)
122 136 File.open(File.join(dest_dir, mail.message_id.gsub(/[<>]/, '') + '.eml'), 'wb') {|f| f.write(mail.encoded) }
123 137 end
124 138 end
125 139 end
126 140
127 141 ActionMailer::Base.add_delivery_method :async_smtp, DeliveryMethods::AsyncSMTP
128 142 ActionMailer::Base.add_delivery_method :async_sendmail, DeliveryMethods::AsyncSendmail
129 143 ActionMailer::Base.add_delivery_method :tmp_file, DeliveryMethods::TmpFile
130 144
131 145 # Changes how sent emails are logged
132 146 # Rails doesn't log cc and bcc which is misleading when using bcc only (#12090)
133 147 module ActionMailer
134 148 class LogSubscriber < ActiveSupport::LogSubscriber
135 149 def deliver(event)
136 150 recipients = [:to, :cc, :bcc].inject("") do |s, header|
137 151 r = Array.wrap(event.payload[header])
138 152 if r.any?
139 153 s << "\n #{header}: #{r.join(', ')}"
140 154 end
141 155 s
142 156 end
143 157 info("\nSent email \"#{event.payload[:subject]}\" (%1.fms)#{recipients}" % event.duration)
144 158 debug(event.payload[:mail])
145 159 end
146 160 end
147 161 end
148 162
149 163 # #deliver is deprecated in Rails 4.2
150 164 # Prevents massive deprecation warnings
151 165 module ActionMailer
152 166 class MessageDelivery < Delegator
153 167 def deliver
154 168 deliver_now
155 169 end
156 170 end
157 171 end
158 172
159 173 module ActionController
160 174 module MimeResponds
161 175 class Collector
162 176 def api(&block)
163 177 any(:xml, :json, &block)
164 178 end
165 179 end
166 180 end
167 181 end
168 182
169 183 module ActionController
170 184 class Base
171 185 # Displays an explicit message instead of a NoMethodError exception
172 186 # when trying to start Redmine with an old session_store.rb
173 187 # TODO: remove it in a later version
174 188 def self.session=(*args)
175 189 $stderr.puts "Please remove config/initializers/session_store.rb and run `rake generate_secret_token`.\n" +
176 190 "Setting the session secret with ActionController.session= is no longer supported."
177 191 exit 1
178 192 end
179 193 end
180 194 end
@@ -1,80 +1,80
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2016 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require File.expand_path('../../../test_helper', __FILE__)
19 19
20 20 class Redmine::ApiTest::IssueRelationsTest < Redmine::ApiTest::Base
21 21 fixtures :projects, :trackers, :issue_statuses, :issues,
22 22 :enumerations, :users, :issue_categories,
23 23 :projects_trackers,
24 24 :roles,
25 25 :member_roles,
26 26 :members,
27 27 :enabled_modules,
28 28 :issue_relations
29 29
30 30 test "GET /issues/:issue_id/relations.xml should return issue relations" do
31 31 get '/issues/9/relations.xml', {}, credentials('jsmith')
32 32
33 33 assert_response :success
34 34 assert_equal 'application/xml', @response.content_type
35 35
36 36 assert_select 'relations[type=array] relation id', :text => '1'
37 37 end
38 38
39 39 test "POST /issues/:issue_id/relations.xml should create the relation" do
40 40 assert_difference('IssueRelation.count') do
41 41 post '/issues/2/relations.xml', {:relation => {:issue_to_id => 7, :relation_type => 'relates'}}, credentials('jsmith')
42 42 end
43 43
44 44 relation = IssueRelation.order('id DESC').first
45 45 assert_equal 2, relation.issue_from_id
46 46 assert_equal 7, relation.issue_to_id
47 47 assert_equal 'relates', relation.relation_type
48 48
49 49 assert_response :created
50 50 assert_equal 'application/xml', @response.content_type
51 51 assert_select 'relation id', :text => relation.id.to_s
52 52 end
53 53
54 54 test "POST /issues/:issue_id/relations.xml with failure should return errors" do
55 55 assert_no_difference('IssueRelation.count') do
56 56 post '/issues/2/relations.xml', {:relation => {:issue_to_id => 7, :relation_type => 'foo'}}, credentials('jsmith')
57 57 end
58 58
59 59 assert_response :unprocessable_entity
60 assert_select 'errors error', :text => /relation_type is not included in the list/
60 assert_select 'errors error', :text => /Relation type is not included in the list/
61 61 end
62 62
63 63 test "GET /relations/:id.xml should return the relation" do
64 64 get '/relations/2.xml', {}, credentials('jsmith')
65 65
66 66 assert_response :success
67 67 assert_equal 'application/xml', @response.content_type
68 68 assert_select 'relation id', :text => '2'
69 69 end
70 70
71 71 test "DELETE /relations/:id.xml should delete the relation" do
72 72 assert_difference('IssueRelation.count', -1) do
73 73 delete '/relations/2.xml', {}, credentials('jsmith')
74 74 end
75 75
76 76 assert_response :ok
77 77 assert_equal '', @response.body
78 78 assert_nil IssueRelation.find_by_id(2)
79 79 end
80 80 end
General Comments 0
You need to be logged in to leave comments. Login now