redmine_crm 0.0.23 → 0.0.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/doc/CHANGELOG +4 -0
- data/lib/redmine_crm.rb +28 -20
- data/lib/redmine_crm/{rcrm_acts_as_taggable.rb → acts_as_taggable/rcrm_acts_as_taggable.rb} +93 -87
- data/lib/redmine_crm/acts_as_taggable/tag.rb +81 -0
- data/lib/redmine_crm/acts_as_taggable/tag_list.rb +111 -0
- data/lib/redmine_crm/acts_as_taggable/tagging.rb +16 -0
- data/lib/redmine_crm/acts_as_viewed/rcrm_acts_as_viewed.rb +274 -0
- data/lib/redmine_crm/{rcrm_acts_as_votable.rb → acts_as_votable/rcrm_acts_as_votable.rb} +8 -11
- data/lib/redmine_crm/acts_as_votable/rcrm_acts_as_voter.rb +20 -0
- data/lib/redmine_crm/{votable.rb → acts_as_votable/votable.rb} +36 -47
- data/lib/redmine_crm/{vote.rb → acts_as_votable/vote.rb} +7 -10
- data/lib/redmine_crm/{voter.rb → acts_as_votable/voter.rb} +29 -34
- data/lib/redmine_crm/currency/formatting.rb +0 -3
- data/lib/redmine_crm/currency/heuristics.rb +1 -1
- data/lib/redmine_crm/currency/loader.rb +1 -1
- data/lib/redmine_crm/helpers/tags_helper.rb +1 -3
- data/lib/redmine_crm/helpers/vote_helper.rb +29 -32
- data/lib/redmine_crm/liquid/drops/issues_drop.rb +66 -0
- data/lib/redmine_crm/liquid/drops/news_drop.rb +54 -0
- data/lib/redmine_crm/liquid/drops/projects_drop.rb +86 -0
- data/lib/redmine_crm/liquid/drops/users_drop.rb +72 -0
- data/lib/redmine_crm/liquid/filters/arrays.rb +178 -0
- data/lib/redmine_crm/liquid/filters/base.rb +208 -0
- data/lib/redmine_crm/version.rb +1 -1
- data/redmine_crm.gemspec +1 -1
- data/test/{acts_as_taggable_test.rb → acts_as_taggable/rcrm_acts_as_taggable_test.rb} +114 -151
- data/test/acts_as_taggable/tag_list_test.rb +38 -0
- data/test/acts_as_taggable/tag_test.rb +74 -0
- data/test/acts_as_taggable/tagging_test.rb +15 -0
- data/test/{viewed_test.rb → acts_as_viewed/rcrm_acts_as_viewed_test.rb} +17 -15
- data/test/{votable_test.rb → acts_as_votable/rcrm_acts_as_votable_test.rb} +3 -3
- data/test/acts_as_votable/rcrm_acts_as_voter_test.rb +12 -0
- data/test/{votable_model_test.rb → acts_as_votable/votable_test.rb} +4 -4
- data/test/{voter_model_test.rb → acts_as_votable/voter_test.rb} +7 -7
- data/test/currency_test.rb +10 -10
- data/test/fixtures/issue.rb +6 -2
- data/test/fixtures/issues.yml +13 -1
- data/test/fixtures/news.rb +3 -0
- data/test/fixtures/news.yml +8 -0
- data/test/fixtures/project.rb +8 -0
- data/test/fixtures/projects.yml +10 -0
- data/test/fixtures/user.rb +5 -1
- data/test/fixtures/users.yml +3 -2
- data/test/fixtures/vote_classes.rb +2 -3
- data/test/liquid/drops/issues_drop_test.rb +34 -0
- data/test/liquid/drops/liquid_test.rb +52 -0
- data/test/liquid/drops/news_drop_test.rb +38 -0
- data/test/liquid/drops/projects_drop_test.rb +44 -0
- data/test/liquid/drops/uses_drop_test.rb +36 -0
- data/test/liquid/filters/arrays_filter_test.rb +24 -0
- data/test/liquid/filters/base_filter_test.rb +63 -0
- data/test/liquid/liquid_helper.rb +32 -0
- data/test/money_helper_test.rb +5 -5
- data/test/schema.rb +21 -9
- data/test/test_helper.rb +26 -25
- metadata +76 -28
- data/lib/redmine_crm/rcrm_acts_as_viewed.rb +0 -287
- data/lib/redmine_crm/rcrm_acts_as_voter.rb +0 -27
- data/lib/redmine_crm/tag.rb +0 -81
- data/lib/redmine_crm/tag_list.rb +0 -112
- data/lib/redmine_crm/tagging.rb +0 -20
- data/test/tag_test.rb +0 -64
- data/test/tagging_test.rb +0 -14
@@ -0,0 +1,208 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'rack'
|
3
|
+
require 'json'
|
4
|
+
require 'date'
|
5
|
+
require 'liquid'
|
6
|
+
|
7
|
+
module RedmineCrm
|
8
|
+
module Liquid
|
9
|
+
module Filters
|
10
|
+
module Base
|
11
|
+
include RedmineCrm::MoneyHelper
|
12
|
+
|
13
|
+
def textilize(input)
|
14
|
+
RedCloth3.new(input).to_html
|
15
|
+
end
|
16
|
+
|
17
|
+
def default(input, value)
|
18
|
+
input.blank? ? value : input
|
19
|
+
end
|
20
|
+
|
21
|
+
def underscore(input)
|
22
|
+
input.to_s.gsub(' ', '_').gsub('/', '_').underscore
|
23
|
+
end
|
24
|
+
|
25
|
+
def dasherize(input)
|
26
|
+
input.to_s.gsub(' ', '-').gsub('/', '-').dasherize
|
27
|
+
end
|
28
|
+
|
29
|
+
def shuffle(array)
|
30
|
+
array.to_a.shuffle
|
31
|
+
end
|
32
|
+
|
33
|
+
def random(input)
|
34
|
+
rand(input.to_i)
|
35
|
+
end
|
36
|
+
|
37
|
+
def md5(input)
|
38
|
+
Digest::MD5.hexdigest(input) unless input.blank?
|
39
|
+
end
|
40
|
+
|
41
|
+
# example:
|
42
|
+
# {{ "http:://www.example.com?key=hello world" | encode }}
|
43
|
+
#
|
44
|
+
# => http%3A%3A%2F%2Fwww.example.com%3Fkey%3Dhello+world
|
45
|
+
def encode(input)
|
46
|
+
::Rack::Utils.escape(input)
|
47
|
+
end
|
48
|
+
|
49
|
+
# example:
|
50
|
+
# {{ today | plus_days: 2 }}
|
51
|
+
def plus_days(input, distanse)
|
52
|
+
return '' if input.nil?
|
53
|
+
days = distanse.to_i
|
54
|
+
input.to_date + days.days rescue 'Invalid date'
|
55
|
+
end
|
56
|
+
|
57
|
+
# example:
|
58
|
+
# {{ today | date_range: '2015-12-12' }}
|
59
|
+
def date_range(input, distanse)
|
60
|
+
return '' if input.nil?
|
61
|
+
(input.to_date - distanse.to_date).to_i rescue 'Invalid date'
|
62
|
+
end
|
63
|
+
|
64
|
+
# example:
|
65
|
+
# {{ now | utc }}
|
66
|
+
def utc(input)
|
67
|
+
return '' if input.nil?
|
68
|
+
input.to_time.utc rescue 'Invalid date'
|
69
|
+
end
|
70
|
+
|
71
|
+
def modulo(input, operand)
|
72
|
+
apply_operation(input, operand, :%)
|
73
|
+
end
|
74
|
+
|
75
|
+
def round(input, n = 0)
|
76
|
+
result = to_number(input).round(to_number(n))
|
77
|
+
result = result.to_f if result.is_a?(BigDecimal)
|
78
|
+
result = result.to_i if n == 0
|
79
|
+
result
|
80
|
+
end
|
81
|
+
|
82
|
+
def ceil(input)
|
83
|
+
to_number(input).ceil.to_i
|
84
|
+
end
|
85
|
+
|
86
|
+
def floor(input)
|
87
|
+
to_number(input).floor.to_i
|
88
|
+
end
|
89
|
+
|
90
|
+
def currency(input, currency_code = 'USD')
|
91
|
+
price_to_currency(input, currency_code, :converted => false)
|
92
|
+
end
|
93
|
+
|
94
|
+
def call_method(input, method_name)
|
95
|
+
if input.respond_to?(method_name)
|
96
|
+
input.method(method_name).call
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def custom_field(input, field_name)
|
101
|
+
if input.respond_to?(:custom_fields)
|
102
|
+
input.custom_fields[field_name]
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def attachment(input, file_name)
|
107
|
+
if input.respond_to?(:attachments)
|
108
|
+
if input.attachments.is_a?(Hash)
|
109
|
+
attachment = input.attachments[file_name]
|
110
|
+
else
|
111
|
+
attachment = input.attachments.detect{|a| a.file_name == file_name}
|
112
|
+
end
|
113
|
+
AttachmentDrop.new attachment if attachment
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
protected
|
118
|
+
|
119
|
+
# Convert an array of properties ('key:value') into a hash
|
120
|
+
# Ex: ['width:50', 'height:100'] => { :width => '50', :height => '100' }
|
121
|
+
def args_to_options(*args)
|
122
|
+
options = {}
|
123
|
+
args.flatten.each do |a|
|
124
|
+
if (a =~ /^(.*):(.*)$/)
|
125
|
+
options[$1.to_sym] = $2
|
126
|
+
end
|
127
|
+
end
|
128
|
+
options
|
129
|
+
end
|
130
|
+
|
131
|
+
# Write options (Hash) into a string according to the following pattern:
|
132
|
+
# <key1>="<value1>", <key2>="<value2", ...etc
|
133
|
+
def inline_options(options = {})
|
134
|
+
return '' if options.empty?
|
135
|
+
(options.stringify_keys.sort.to_a.collect { |a, b| "#{a}=\"#{b}\"" }).join(' ') << ' '
|
136
|
+
end
|
137
|
+
|
138
|
+
def sort_input(input, property, order)
|
139
|
+
input.sort do |apple, orange|
|
140
|
+
apple_property = item_property(apple, property)
|
141
|
+
orange_property = item_property(orange, property)
|
142
|
+
|
143
|
+
if !apple_property.nil? && orange_property.nil?
|
144
|
+
- order
|
145
|
+
elsif apple_property.nil? && !orange_property.nil?
|
146
|
+
+ order
|
147
|
+
else
|
148
|
+
apple_property <=> orange_property
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def time(input)
|
154
|
+
case input
|
155
|
+
when Time
|
156
|
+
input.clone
|
157
|
+
when Date
|
158
|
+
input.to_time
|
159
|
+
when String
|
160
|
+
Time.parse(input) rescue Time.at(input.to_i)
|
161
|
+
when Numeric
|
162
|
+
Time.at(input)
|
163
|
+
else
|
164
|
+
raise Errors::InvalidDateError,
|
165
|
+
"Invalid Date: '#{input.inspect}' is not a valid datetime."
|
166
|
+
end.localtime
|
167
|
+
end
|
168
|
+
|
169
|
+
def groupable?(element)
|
170
|
+
element.respond_to?(:group_by)
|
171
|
+
end
|
172
|
+
|
173
|
+
def item_property(item, property)
|
174
|
+
if item.respond_to?(:to_liquid)
|
175
|
+
item.to_liquid[property.to_s]
|
176
|
+
elsif item.respond_to?(:data)
|
177
|
+
item.data[property.to_s]
|
178
|
+
else
|
179
|
+
item[property.to_s]
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def as_liquid(item)
|
184
|
+
case item
|
185
|
+
when Hash
|
186
|
+
pairs = item.map { |k, v| as_liquid([k, v]) }
|
187
|
+
Hash[pairs]
|
188
|
+
when Array
|
189
|
+
item.map { |i| as_liquid(i) }
|
190
|
+
else
|
191
|
+
if item.respond_to?(:to_liquid)
|
192
|
+
liquidated = item.to_liquid
|
193
|
+
# prevent infinite recursion for simple types (which return `self`)
|
194
|
+
if liquidated == item
|
195
|
+
item
|
196
|
+
else
|
197
|
+
as_liquid(liquidated)
|
198
|
+
end
|
199
|
+
else
|
200
|
+
item
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
::Liquid::Template.register_filter(RedmineCrm::Liquid::Filters::Base)
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
data/lib/redmine_crm/version.rb
CHANGED
data/redmine_crm.gemspec
CHANGED
@@ -1,278 +1,259 @@
|
|
1
|
-
require File.dirname(__FILE__) + '
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
|
3
|
+
class RcrmActsAsTaggableTest < ActiveSupport::TestCase
|
4
|
+
def test_available_tags
|
5
|
+
assert_equivalent [tags(:feature), tags(:bug), tags(:error), tags(:question)], Issue.available_tags(Project.first)
|
6
|
+
assert_equivalent [tags(:feature), tags(:bug)], Issue.available_tags(Project.first, 2)
|
7
|
+
end
|
2
8
|
|
3
|
-
class ActsAsTaggableTest < ActiveSupport::TestCase
|
4
9
|
def test_find_related_tags_with
|
5
10
|
assert_equivalent [tags(:feature), tags(:bug), tags(:question)], Issue.find_related_tags("error")
|
6
11
|
assert_equivalent [tags(:feature), tags(:error), tags(:question)], Issue.find_related_tags(tags(:bug))
|
7
|
-
assert_equivalent [tags(:error), tags(:question)], Issue.find_related_tags(["New feature", "bug"])
|
12
|
+
assert_equivalent [tags(:error), tags(:question)], Issue.find_related_tags(["New feature", "bug"])
|
8
13
|
assert_equivalent [tags(:feature), tags(:bug)], Issue.find_related_tags([tags(:error), tags(:question)])
|
9
14
|
end
|
10
|
-
|
15
|
+
|
11
16
|
def test_find_tagged_with_include_and_order
|
12
17
|
assert_equal issues(:third_issue, :first_issue, :second_issue), Issue.find_tagged_with("question", :order => "issues.description DESC", :include => :user).to_a
|
13
18
|
end
|
14
|
-
|
19
|
+
|
15
20
|
def test_find_related_tags_with_non_existent_tags
|
16
21
|
assert_equal [], Issue.find_related_tags("ABCDEFG")
|
17
22
|
assert_equal [], Issue.find_related_tags(['HIJKLM'])
|
18
23
|
end
|
19
|
-
|
24
|
+
|
20
25
|
def test_find_related_tags_with_nothing
|
21
26
|
assert_equal [], Issue.find_related_tags("")
|
22
|
-
assert_equal [], Issue.find_related_tags([])
|
27
|
+
assert_equal [], Issue.find_related_tags([])
|
23
28
|
end
|
24
|
-
|
29
|
+
|
25
30
|
def test_find_tagged_with
|
26
31
|
assert_equivalent [issues(:first_issue), issues(:second_issue), issues(:third_issue)], Issue.find_tagged_with('"error"')
|
27
32
|
assert_equal Issue.find_tagged_with('"error"'), Issue.find_tagged_with(['error'])
|
28
33
|
assert_equal Issue.find_tagged_with('"error"'), Issue.find_tagged_with([tags(:error)])
|
29
|
-
|
34
|
+
|
30
35
|
assert_equivalent [issues(:second_issue),], Issue.find_tagged_with('New feature')
|
31
36
|
assert_equal Issue.find_tagged_with('New feature'), Issue.find_tagged_with(['New feature'])
|
32
37
|
assert_equal Issue.find_tagged_with('New feature'), Issue.find_tagged_with([tags(:feature)])
|
33
|
-
|
34
|
-
# assert_equivalent [issues(:jonathan_bad_cat), issues(:jonathan_dog), issues(:second_issue)], Issue.find_tagged_with('"Crazy animal" Bad')
|
35
|
-
# assert_equal Issue.find_tagged_with('"Crazy animal" Bad'), Issue.find_tagged_with(['Crazy animal', 'Bad'])
|
36
|
-
# assert_equal Issue.find_tagged_with('"Crazy animal" Bad'), Issue.find_tagged_with([tags(:animal), tags(:bad)])
|
37
38
|
end
|
38
|
-
|
39
|
+
|
39
40
|
def test_find_tagged_with_nothing
|
40
41
|
assert_equal [], Issue.find_tagged_with("")
|
41
42
|
assert_equal [], Issue.find_tagged_with([])
|
42
43
|
end
|
43
|
-
|
44
|
+
|
44
45
|
def test_find_tagged_with_nonexistant_tags
|
45
46
|
assert_equal [], Issue.find_tagged_with('ABCDEFG')
|
46
47
|
assert_equal [], Issue.find_tagged_with(['HIJKLM'])
|
47
|
-
assert_equal [], Issue.find_tagged_with([RedmineCrm::Tag.new(:name => 'unsaved tag')])
|
48
|
+
assert_equal [], Issue.find_tagged_with([RedmineCrm::ActsAsTaggable::Tag.new(:name => 'unsaved tag')])
|
48
49
|
end
|
49
|
-
|
50
|
+
|
50
51
|
def test_find_tagged_with_match_all
|
51
|
-
assert_equivalent [issues(:second_issue)],
|
52
|
-
Issue.find_tagged_with('error, "bug", "New feature", "question"', :match_all => true)
|
52
|
+
assert_equivalent [issues(:second_issue)], Issue.find_tagged_with('error, "bug", "New feature", "question"', :match_all => true)
|
53
53
|
end
|
54
|
-
|
54
|
+
|
55
55
|
def test_find_tagged_with_match_all_and_include
|
56
56
|
assert_equivalent [issues(:first_issue), issues(:second_issue), issues(:third_issue)], Issue.find_tagged_with(['error', 'question'], :match_all => true, :include => :tags)
|
57
57
|
end
|
58
|
-
|
58
|
+
|
59
59
|
def test_find_tagged_with_conditions
|
60
60
|
assert_equal [], Issue.find_tagged_with('"error", bug', :conditions => '1=0')
|
61
61
|
end
|
62
|
-
|
62
|
+
|
63
63
|
def test_find_tagged_with_duplicates_options_hash
|
64
64
|
options = { :conditions => '1=1' }.freeze
|
65
65
|
assert_nothing_raised { Issue.find_tagged_with("error", options) }
|
66
66
|
end
|
67
|
-
|
67
|
+
|
68
68
|
def test_find_tagged_with_exclusions
|
69
69
|
assert_equivalent [issues(:first_issue), issues(:third_issue)], Issue.find_tagged_with("bug", :exclude => true)
|
70
70
|
assert_equivalent [issues(:first_issue), issues(:third_issue)], Issue.find_tagged_with("'bug', feature", :exclude => true)
|
71
71
|
end
|
72
|
-
|
72
|
+
|
73
73
|
def test_find_options_for_find_tagged_with_no_tags_returns_empty_hash
|
74
74
|
assert_equal Hash.new, Issue.find_options_for_find_tagged_with("")
|
75
75
|
assert_equal Hash.new, Issue.find_options_for_find_tagged_with([nil])
|
76
76
|
end
|
77
|
-
|
77
|
+
|
78
78
|
def test_find_options_for_find_tagged_with_leaves_arguments_unchanged
|
79
79
|
original_tags = issues(:second_issue).tags.dup
|
80
80
|
Issue.find_options_for_find_tagged_with(issues(:second_issue).tags)
|
81
81
|
assert_equal original_tags, issues(:second_issue).tags
|
82
82
|
end
|
83
|
-
|
83
|
+
|
84
84
|
def test_find_options_for_find_tagged_with_respects_custom_table_name
|
85
|
-
RedmineCrm::Tagging.table_name = "categorisations"
|
86
|
-
RedmineCrm::Tag.table_name = "categories"
|
87
|
-
|
85
|
+
RedmineCrm::ActsAsTaggable::Tagging.table_name = "categorisations"
|
86
|
+
RedmineCrm::ActsAsTaggable::Tag.table_name = "categories"
|
87
|
+
|
88
88
|
options = Issue.find_options_for_find_tagged_with("Hello")
|
89
|
-
|
89
|
+
|
90
90
|
assert_no_match(/ taggings /, options[:joins])
|
91
91
|
assert_no_match(/ tags /, options[:joins])
|
92
|
-
|
92
|
+
|
93
93
|
assert_match(/ categorisations /, options[:joins])
|
94
94
|
assert_match(/ categories /, options[:joins])
|
95
95
|
ensure
|
96
|
-
RedmineCrm::Tagging.table_name = "taggings"
|
97
|
-
RedmineCrm::Tag.table_name = "tags"
|
96
|
+
RedmineCrm::ActsAsTaggable::Tagging.table_name = "taggings"
|
97
|
+
RedmineCrm::ActsAsTaggable::Tag.table_name = "tags"
|
98
98
|
end
|
99
|
-
|
99
|
+
|
100
100
|
def test_include_tags_on_find_tagged_with
|
101
101
|
assert_nothing_raised do
|
102
102
|
Issue.find_tagged_with('error', :include => :tags)
|
103
103
|
Issue.find_tagged_with("error", :include => { :taggings => :tag })
|
104
104
|
end
|
105
105
|
end
|
106
|
-
|
106
|
+
|
107
107
|
def test_basic_tag_counts_on_class
|
108
108
|
assert_tag_counts Issue.tag_counts, :error => 3, :feature => 1, :question => 3, :bug => 1
|
109
|
-
# assert_tag_counts Issue.tag_counts, :good => 1, :question => 3, :question => 1, :bad => 1, :animal => 3
|
110
109
|
end
|
111
|
-
|
110
|
+
|
112
111
|
def test_tag_counts_on_class_with_date_conditions
|
113
112
|
assert_tag_counts Issue.tag_counts(:start_at => Date.new(2015, 1, 1)), :error => 2, :feature => 1, :question => 3, :bug => 1
|
114
113
|
assert_tag_counts Issue.tag_counts(:end_at => Date.new(2014, 12, 31)), :error => 1
|
115
114
|
assert_tag_counts Issue.tag_counts(:start_at => Date.new(2015, 1, 31), :end_at => Date.new(2015, 3, 1)), :question => 1
|
116
|
-
|
117
|
-
# assert_tag_counts Issue.tag_counts(:start_at => Date.new(2006, 8, 12), :end_at => Date.new(2006, 8, 19)), :good => 1, :question => 2, :bad => 1, :question => 1, :animal => 3
|
118
115
|
end
|
119
|
-
|
116
|
+
|
120
117
|
def test_tag_counts_on_class_with_frequencies
|
121
118
|
assert_tag_counts Issue.tag_counts(:at_least => 2), :question => 3, :error => 3
|
122
119
|
assert_tag_counts Issue.tag_counts(:at_most => 2), :bug => 1, :feature => 1
|
123
120
|
end
|
124
|
-
|
121
|
+
|
125
122
|
def test_tag_counts_on_class_with_frequencies_and_conditions
|
126
123
|
assert_tag_counts Issue.tag_counts(:at_least => 2, :conditions => '1=1'), :question => 3, :error => 3
|
127
124
|
end
|
128
|
-
|
125
|
+
|
129
126
|
def test_tag_counts_duplicates_options_hash
|
130
127
|
options = { :at_least => 2, :conditions => '1=1' }.freeze
|
131
128
|
assert_nothing_raised { Issue.tag_counts(options) }
|
132
129
|
end
|
133
|
-
|
130
|
+
|
134
131
|
def test_tag_counts_with_limit
|
135
132
|
assert_equal 2, Issue.tag_counts(:limit => 2).to_a.size
|
136
133
|
assert_equal 2, Issue.tag_counts(:at_least => 3, :limit => 2).to_a.size
|
137
134
|
end
|
138
|
-
|
135
|
+
|
139
136
|
def test_tag_counts_with_limit_and_order
|
140
|
-
assert_equivalent RedmineCrm::Tag.where(:id => [tags(:error), tags(:question)]), Issue.tag_counts(:order => 'count desc', :limit => 2)
|
137
|
+
assert_equivalent RedmineCrm::ActsAsTaggable::Tag.where(:id => [tags(:error), tags(:question)]), Issue.tag_counts(:order => 'count desc', :limit => 2)
|
141
138
|
end
|
142
|
-
|
139
|
+
|
143
140
|
def test_tag_counts_on_association
|
144
141
|
assert_tag_counts users(:jonathan).issues.tag_counts, :error => 2, :bug => 1, :question => 2, :feature => 1
|
145
142
|
assert_tag_counts users(:sam).issues.tag_counts, :error => 1, :question => 1
|
146
|
-
|
147
|
-
# assert_tag_counts users(:jonathan).issues.tag_counts, :animal => 3, :question => 1, :question => 1, :bad => 1
|
148
|
-
# assert_tag_counts users(:sam).issues.tag_counts, :question => 2, :good => 1
|
149
143
|
end
|
150
|
-
|
144
|
+
|
151
145
|
def test_tag_counts_on_association_with_options
|
152
146
|
assert_equal [], users(:jonathan).issues.tag_counts(:conditions => '1=0')
|
153
|
-
assert_tag_counts users(:jonathan).issues.tag_counts(:at_most => 2), :bug => 1,
|
147
|
+
assert_tag_counts users(:jonathan).issues.tag_counts(:at_most => 2), :bug => 1,
|
154
148
|
:feature => 1, :error => 2, :question => 2
|
155
149
|
end
|
156
|
-
|
157
|
-
# def test_tag_counts_on_has_many_through
|
158
|
-
# assert_tag_counts users(:jonathan).magazines.tag_counts, :good => 1
|
159
|
-
# end
|
160
|
-
|
150
|
+
|
161
151
|
def test_tag_counts_on_model_instance
|
162
152
|
assert_tag_counts issues(:third_issue).tag_counts, :error => 3, :question => 3
|
163
153
|
end
|
164
|
-
|
154
|
+
|
165
155
|
def test_tag_counts_on_model_instance_merges_conditions
|
166
156
|
assert_tag_counts issues(:first_issue).tag_counts(:conditions => "tags.name = 'error'"), :error => 3
|
167
157
|
end
|
168
|
-
|
158
|
+
|
169
159
|
def test_tag_counts_on_model_instance_with_no_tags
|
170
160
|
issue = Issue.create!(:description => "desc")
|
171
|
-
|
161
|
+
|
172
162
|
assert_tag_counts issue.tag_counts, {}
|
173
163
|
end
|
174
|
-
|
164
|
+
|
175
165
|
def test_tag_counts_should_sanitize_scope_conditions
|
176
166
|
Issue.send :where, { "tags.id = ?" => tags(:error).id } do
|
177
167
|
assert_tag_counts Issue.tag_counts, :error => 3
|
178
168
|
end
|
179
169
|
end
|
180
|
-
|
170
|
+
|
181
171
|
def test_tag_counts_respects_custom_table_names
|
182
|
-
RedmineCrm::Tagging.table_name = "categorisations"
|
183
|
-
RedmineCrm::Tag.table_name = "categories"
|
184
|
-
|
172
|
+
RedmineCrm::ActsAsTaggable::Tagging.table_name = "categorisations"
|
173
|
+
RedmineCrm::ActsAsTaggable::Tag.table_name = "categories"
|
174
|
+
|
185
175
|
options = Issue.find_options_for_tag_counts(:start_at => 2.weeks.ago, :end_at => Date.today)
|
186
176
|
sql = options.values.join(' ')
|
187
|
-
|
177
|
+
|
188
178
|
assert_no_match /taggings/, sql
|
189
179
|
assert_no_match /tags/, sql
|
190
|
-
|
180
|
+
|
191
181
|
assert_match /categorisations/, sql
|
192
182
|
assert_match /categories/, sql
|
193
183
|
ensure
|
194
|
-
RedmineCrm::Tagging.table_name = "taggings"
|
195
|
-
RedmineCrm::Tag.table_name = "tags"
|
184
|
+
RedmineCrm::ActsAsTaggable::Tagging.table_name = "taggings"
|
185
|
+
RedmineCrm::ActsAsTaggable::Tag.table_name = "tags"
|
196
186
|
end
|
197
|
-
|
187
|
+
|
198
188
|
def test_tag_list_reader
|
199
189
|
assert_equivalent ["error", "question"], issues(:first_issue).tag_list
|
200
190
|
assert_equivalent ["error", "New feature", "bug", "question"], issues(:second_issue).tag_list
|
201
191
|
end
|
202
|
-
|
192
|
+
|
203
193
|
def test_reassign_tag_list
|
204
194
|
assert_equivalent ["error", "question"], issues(:first_issue).tag_list
|
205
195
|
issues(:first_issue).taggings.reload
|
206
|
-
|
196
|
+
|
207
197
|
# Only an update of the issues table should be executed, the other two queries are for savepoints
|
208
198
|
# assert_queries 3 do
|
209
199
|
# issues(:first_issue).update_attributes!(:description => "new name", :tag_list => issues(:first_issue).tag_list.to_s)
|
210
200
|
# end
|
211
|
-
|
201
|
+
|
212
202
|
assert_equivalent ["error", "question"], issues(:first_issue).tag_list
|
213
203
|
end
|
214
|
-
|
204
|
+
|
215
205
|
def test_new_tags
|
216
206
|
assert_equivalent ["error", "question"], issues(:first_issue).tag_list
|
217
207
|
issues(:first_issue).update_attributes!(:tag_list => "#{issues(:first_issue).tag_list}, One, Two")
|
218
208
|
assert_equivalent ["error", "question", "One", "Two"], issues(:first_issue).tag_list
|
219
209
|
end
|
220
|
-
|
210
|
+
|
221
211
|
def test_remove_tag
|
222
212
|
assert_equivalent ["error", "question"], issues(:first_issue).tag_list
|
223
213
|
issues(:first_issue).update_attributes!(:tag_list => "error")
|
224
214
|
assert_equivalent ["error"], issues(:first_issue).tag_list
|
225
215
|
end
|
226
|
-
|
227
|
-
# def test_change_case_of_tags
|
228
|
-
# original_tag_names = issues(:second_issue).tag_list
|
229
|
-
# issues(:second_issue).update_attributes!(:tag_list => issues(:second_issue).tag_list.to_s.upcase)
|
230
|
-
|
231
|
-
# # The new tag list is not uppercase becuase the AR finders are not case-sensitive
|
232
|
-
# # and find the old tags when re-tagging with the uppercase tags.
|
233
|
-
# assert_equivalent original_tag_names, issues(:second_issue).reload.tag_list
|
234
|
-
# end
|
235
|
-
|
216
|
+
|
236
217
|
def test_remove_and_add_tag
|
237
218
|
assert_equivalent ["error", "question"], issues(:first_issue).tag_list
|
238
219
|
issues(:first_issue).update_attributes!(:tag_list => "question, Beautiful")
|
239
220
|
assert_equivalent ["question", "Beautiful"], issues(:first_issue).tag_list
|
240
221
|
end
|
241
|
-
|
222
|
+
|
242
223
|
def test_tags_not_saved_if_validation_fails
|
243
224
|
assert_equivalent ["error", "question"], issues(:first_issue).tag_list
|
244
225
|
assert !issues(:first_issue).update_attributes(:tag_list => "One, Two", :description => "")
|
245
226
|
assert_equivalent ["error", "question"], Issue.find(issues(:first_issue).id).tag_list
|
246
227
|
end
|
247
|
-
|
228
|
+
|
248
229
|
def test_tag_list_accessors_on_new_record
|
249
230
|
p = Issue.new(:description => 'Test')
|
250
|
-
|
231
|
+
|
251
232
|
assert p.tag_list.blank?
|
252
233
|
p.tag_list = "One, Two"
|
253
234
|
assert_equal "One, Two", p.tag_list.to_s
|
254
235
|
end
|
255
|
-
|
236
|
+
|
256
237
|
def test_clear_tag_list_with_nil
|
257
238
|
p = issues(:second_issue)
|
258
|
-
|
239
|
+
|
259
240
|
assert !p.tag_list.blank?
|
260
241
|
assert p.update_attributes(:tag_list => nil)
|
261
242
|
assert p.tag_list.blank?
|
262
|
-
|
243
|
+
|
263
244
|
assert p.reload.tag_list.blank?
|
264
245
|
end
|
265
|
-
|
246
|
+
|
266
247
|
def test_clear_tag_list_with_string
|
267
248
|
p = issues(:second_issue)
|
268
|
-
|
249
|
+
|
269
250
|
assert !p.tag_list.blank?
|
270
251
|
assert p.update_attributes(:tag_list => ' ')
|
271
252
|
assert p.tag_list.blank?
|
272
|
-
|
253
|
+
|
273
254
|
assert p.reload.tag_list.blank?
|
274
255
|
end
|
275
|
-
|
256
|
+
|
276
257
|
def test_tag_list_reset_on_reload
|
277
258
|
p = issues(:second_issue)
|
278
259
|
assert !p.tag_list.blank?
|
@@ -280,105 +261,87 @@ class ActsAsTaggableTest < ActiveSupport::TestCase
|
|
280
261
|
assert p.tag_list.blank?
|
281
262
|
assert !p.reload.tag_list.blank?
|
282
263
|
end
|
283
|
-
|
264
|
+
|
284
265
|
def test_instance_tag_counts
|
285
266
|
assert_tag_counts issues(:first_issue).tag_counts, :error => 3, :question => 3
|
286
267
|
end
|
287
|
-
|
268
|
+
|
288
269
|
def test_tag_list_populated_when_cache_nil
|
289
270
|
assert_nil issues(:first_issue).cached_tag_list
|
290
271
|
issues(:first_issue).save!
|
291
272
|
assert_equal issues(:first_issue).tag_list.to_s, issues(:first_issue).cached_tag_list
|
292
273
|
end
|
293
|
-
|
294
|
-
# def test_cached_tag_list_used
|
295
|
-
# issues(:first_issue).save!
|
296
|
-
# issues(:first_issue).reload
|
297
|
-
|
298
|
-
# assert_no_queries do
|
299
|
-
# assert_equivalent ["error", "question"], issues(:first_issue).tag_list
|
300
|
-
# end
|
301
|
-
# end
|
302
|
-
|
303
|
-
def test_cached_tag_list_not_used
|
304
|
-
# Load fixture and column information
|
305
|
-
issues(:first_issue).taggings(:reload)
|
306
|
-
|
307
|
-
# assert_queries 1 do
|
308
|
-
# # Tags association will be loaded
|
309
|
-
# issues(:first_issue).tag_list
|
310
|
-
# end
|
311
|
-
end
|
312
|
-
|
274
|
+
|
313
275
|
def test_cached_tag_list_updated
|
314
276
|
assert_nil issues(:first_issue).cached_tag_list
|
315
277
|
issues(:first_issue).save!
|
316
|
-
assert_equivalent ["question", "error"], RedmineCrm::TagList.from(issues(:first_issue).cached_tag_list)
|
278
|
+
assert_equivalent ["question", "error"], RedmineCrm::ActsAsTaggable::TagList.from(issues(:first_issue).cached_tag_list)
|
317
279
|
issues(:first_issue).update_attributes!(:tag_list => "None")
|
318
|
-
|
280
|
+
|
319
281
|
assert_equal 'None', issues(:first_issue).cached_tag_list
|
320
282
|
assert_equal 'None', issues(:first_issue).reload.cached_tag_list
|
321
283
|
end
|
322
|
-
|
284
|
+
|
323
285
|
def test_clearing_cached_tag_list
|
324
286
|
# Generate the cached tag list
|
325
287
|
issues(:first_issue).save!
|
326
|
-
|
288
|
+
|
327
289
|
issues(:first_issue).update_attributes!(:tag_list => "")
|
328
290
|
assert_equal "", issues(:first_issue).cached_tag_list
|
329
291
|
end
|
330
292
|
|
331
293
|
def test_find_tagged_with_using_sti
|
332
|
-
|
333
|
-
|
334
|
-
assert_equal [
|
335
|
-
assert SpecialIssue.find_tagged_with(
|
336
|
-
end
|
337
|
-
|
338
|
-
# def test_tag_counts_using_sti
|
339
|
-
# SpecialIssue.create!(:description => "Test", :tag_list => "question")
|
340
|
-
# assert_tag_counts SpecialIssue.tag_counts, :question => 1
|
341
|
-
# end
|
342
|
-
|
294
|
+
special_issue = SpecialIssue.create!(:description => 'Test', :tag_list => 'Random')
|
295
|
+
|
296
|
+
assert_equal [special_issue], SpecialIssue.find_tagged_with('Random')
|
297
|
+
assert SpecialIssue.find_tagged_with('Random').include?(special_issue)
|
298
|
+
end
|
299
|
+
|
343
300
|
def test_case_insensitivity
|
344
|
-
assert_difference "RedmineCrm::Tag.count", 1 do
|
301
|
+
assert_difference "RedmineCrm::ActsAsTaggable::Tag.count", 1 do
|
345
302
|
Issue.create!(:description => "Test", :tag_list => "one")
|
346
303
|
Issue.create!(:description => "Test", :tag_list => "One")
|
347
304
|
end
|
348
305
|
assert_equal Issue.find_tagged_with("question"), Issue.find_tagged_with("question")
|
349
306
|
end
|
350
|
-
|
307
|
+
|
351
308
|
def test_tag_not_destroyed_when_unused
|
352
309
|
issues(:first_issue).tag_list.add("Random")
|
353
310
|
issues(:first_issue).save!
|
354
|
-
|
355
|
-
assert_no_difference 'RedmineCrm::Tag.count' do
|
311
|
+
|
312
|
+
assert_no_difference 'RedmineCrm::ActsAsTaggable::Tag.count' do
|
356
313
|
issues(:first_issue).tag_list.remove("Random")
|
357
314
|
issues(:first_issue).save!
|
358
315
|
end
|
359
316
|
end
|
360
|
-
|
317
|
+
|
361
318
|
def test_tag_destroyed_when_unused
|
362
|
-
RedmineCrm::Tag.destroy_unused = true
|
363
|
-
|
319
|
+
RedmineCrm::ActsAsTaggable::Tag.destroy_unused = true
|
320
|
+
|
364
321
|
issues(:first_issue).tag_list.add("Random")
|
365
322
|
issues(:first_issue).save!
|
366
|
-
|
367
|
-
assert_difference 'RedmineCrm::Tag.count', -1 do
|
323
|
+
|
324
|
+
assert_difference 'RedmineCrm::ActsAsTaggable::Tag.count', -1 do
|
368
325
|
issues(:first_issue).tag_list.remove("Random")
|
369
326
|
issues(:first_issue).save!
|
370
327
|
end
|
371
328
|
ensure
|
372
|
-
RedmineCrm::Tag.destroy_unused = false
|
329
|
+
RedmineCrm::ActsAsTaggable::Tag.destroy_unused = false
|
330
|
+
end
|
331
|
+
|
332
|
+
def test_quote_value
|
333
|
+
assert_equal "'RedmineCrm::ActsAsTaggable::Tag'", Issue.send(:quote_value, RedmineCrm::ActsAsTaggable::Tag)
|
373
334
|
end
|
374
|
-
end
|
375
335
|
|
376
|
-
|
377
|
-
#
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
336
|
+
def test_tags_condition
|
337
|
+
assert_equal "(tags_TABLE.name LIKE #{tags(:feature).id} OR tags_TABLE.name LIKE #{tags(:bug).id})",
|
338
|
+
Issue.send(:tags_condition, [tags(:feature), tags(:bug)], 'tags_TABLE')
|
339
|
+
end
|
340
|
+
|
341
|
+
def test_all_tags_list
|
342
|
+
issues(:first_issue).tag_list.remove('error')
|
343
|
+
issues(:first_issue).tag_list.add('new')
|
344
|
+
issues(:first_issue).save!
|
345
|
+
assert_equal %w(question new), issues(:first_issue).all_tags_list
|
346
|
+
end
|
347
|
+
end
|