yeshua_crm 1.0.0
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 +7 -0
- data/Rakefile +11 -0
- data/lib/yeshoua_crm.rb +87 -0
- data/lib/yeshua_crm/acts_as_draftable/draft.rb +40 -0
- data/lib/yeshua_crm/acts_as_draftable/rcrm_acts_as_draftable.rb +154 -0
- data/lib/yeshua_crm/acts_as_list/list.rb +282 -0
- data/lib/yeshua_crm/acts_as_taggable/rcrm_acts_as_taggable.rb +350 -0
- data/lib/yeshua_crm/acts_as_taggable/tag.rb +81 -0
- data/lib/yeshua_crm/acts_as_taggable/tag_list.rb +111 -0
- data/lib/yeshua_crm/acts_as_taggable/tagging.rb +16 -0
- data/lib/yeshua_crm/acts_as_viewed/rcrm_acts_as_viewed.rb +274 -0
- data/lib/yeshua_crm/acts_as_votable/rcrm_acts_as_votable.rb +80 -0
- data/lib/yeshua_crm/acts_as_votable/rcrm_acts_as_voter.rb +20 -0
- data/lib/yeshua_crm/acts_as_votable/votable.rb +323 -0
- data/lib/yeshua_crm/acts_as_votable/vote.rb +28 -0
- data/lib/yeshua_crm/acts_as_votable/voter.rb +131 -0
- data/lib/yeshua_crm/assets_manager.rb +43 -0
- data/lib/yeshua_crm/currency/formatting.rb +224 -0
- data/lib/yeshua_crm/currency/heuristics.rb +151 -0
- data/lib/yeshua_crm/currency/loader.rb +24 -0
- data/lib/yeshua_crm/currency.rb +439 -0
- data/lib/yeshua_crm/helpers/external_assets_helper.rb +17 -0
- data/lib/yeshua_crm/helpers/form_tag_helper.rb +123 -0
- data/lib/yeshua_crm/helpers/tags_helper.rb +13 -0
- data/lib/yeshua_crm/helpers/vote_helper.rb +35 -0
- data/lib/yeshua_crm/liquid/drops/cells_drop.rb +86 -0
- data/lib/yeshua_crm/liquid/drops/issues_drop.rb +66 -0
- data/lib/yeshua_crm/liquid/drops/news_drop.rb +54 -0
- data/lib/yeshua_crm/liquid/drops/users_drop.rb +72 -0
- data/lib/yeshua_crm/liquid/filters/arrays.rb +177 -0
- data/lib/yeshua_crm/liquid/filters/base.rb +208 -0
- data/lib/yeshua_crm/money_helper.rb +65 -0
- data/lib/yeshua_crm/version.rb +3 -0
- data/test/acts_as_draftable/draft_test.rb +29 -0
- data/test/acts_as_draftable/rcrm_acts_as_draftable_test.rb +185 -0
- data/test/acts_as_taggable/rcrm_acts_as_taggable_test.rb +345 -0
- data/test/acts_as_taggable/tag_list_test.rb +34 -0
- data/test/acts_as_taggable/tag_test.rb +72 -0
- data/test/acts_as_taggable/tagging_test.rb +15 -0
- data/test/acts_as_viewed/rcrm_acts_as_viewed_test.rb +47 -0
- data/test/acts_as_votable/rcrm_acts_as_votable_test.rb +19 -0
- data/test/acts_as_votable/rcrm_acts_as_voter_test.rb +14 -0
- data/test/acts_as_votable/votable_test.rb +507 -0
- data/test/acts_as_votable/voter_test.rb +296 -0
- data/test/currency_test.rb +292 -0
- data/test/liquid/drops/issues_drop_test.rb +34 -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/models/issue.rb +14 -0
- data/test/models/news.rb +3 -0
- data/test/models/project.rb +8 -0
- data/test/models/user.rb +11 -0
- data/test/models/vote_classes.rb +33 -0
- data/test/money_helper_test.rb +12 -0
- data/test/schema.rb +121 -0
- data/test/tags_helper_test.rb +29 -0
- data/test/test_helper.rb +66 -0
- data/test/vote_helper_test.rb +28 -0
- data/yeshua_crm.gemspec +28 -0
- metadata +206 -0
|
@@ -0,0 +1,439 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
require "yeshua_crm/currency/loader"
|
|
3
|
+
require "yeshua_crm/currency/heuristics"
|
|
4
|
+
require "yeshua_crm/currency/formatting"
|
|
5
|
+
|
|
6
|
+
module YeshuaCrm
|
|
7
|
+
# Represents a specific currency unit.
|
|
8
|
+
#
|
|
9
|
+
# @see http://en.wikipedia.org/wiki/Currency
|
|
10
|
+
# @see http://iso4217.net/
|
|
11
|
+
class Currency
|
|
12
|
+
include Comparable
|
|
13
|
+
extend Enumerable
|
|
14
|
+
extend YeshuaCrm::Currency::Loader
|
|
15
|
+
extend YeshuaCrm::Currency::Heuristics
|
|
16
|
+
extend YeshuaCrm::Currency::Formatting
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
# Thrown when a Currency has been registered without all the attributes
|
|
20
|
+
# which are required for the current action.
|
|
21
|
+
class MissingAttributeError < StandardError
|
|
22
|
+
def initialize(method, currency, attribute)
|
|
23
|
+
super(
|
|
24
|
+
"Can't call Currency.#{method} - currency '#{currency}' is missing "\
|
|
25
|
+
"the attribute '#{attribute}'"
|
|
26
|
+
)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Thrown when an unknown currency is requested.
|
|
31
|
+
class UnknownCurrency < ArgumentError;
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
class << self
|
|
35
|
+
|
|
36
|
+
# Lookup a currency with given +id+ an returns a +Currency+ instance on
|
|
37
|
+
# success, +nil+ otherwise.
|
|
38
|
+
#
|
|
39
|
+
# @param [String, Symbol, #to_s] id Used to look into +table+ and
|
|
40
|
+
# retrieve the applicable attributes.
|
|
41
|
+
#
|
|
42
|
+
# @return [Money::Currency]
|
|
43
|
+
#
|
|
44
|
+
# @example
|
|
45
|
+
# Money::Currency.find(:eur) #=> #<Money::Currency id: eur ...>
|
|
46
|
+
# Money::Currency.find(:foo) #=> nil
|
|
47
|
+
def find(id)
|
|
48
|
+
return nil if id == ""
|
|
49
|
+
id = id.to_s.downcase.to_sym
|
|
50
|
+
new(id)
|
|
51
|
+
rescue UnknownCurrency
|
|
52
|
+
nil
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Lookup a currency with given +num+ as an ISO 4217 numeric and returns an
|
|
56
|
+
# +Currency+ instance on success, +nil+ otherwise.
|
|
57
|
+
#
|
|
58
|
+
# @param [#to_s] num used to look into +table+ in +iso_numeric+ and find
|
|
59
|
+
# the right currency id.
|
|
60
|
+
#
|
|
61
|
+
# @return [Money::Currency]
|
|
62
|
+
#
|
|
63
|
+
# @example
|
|
64
|
+
# Money::Currency.find_by_iso_numeric(978) #=> #<Money::Currency id: eur ...>
|
|
65
|
+
# Money::Currency.find_by_iso_numeric('001') #=> nil
|
|
66
|
+
def find_by_iso_numeric(num)
|
|
67
|
+
num = num.to_s
|
|
68
|
+
id, _ = self.table.find { |key, currency| currency[:iso_numeric] == num }
|
|
69
|
+
new(id)
|
|
70
|
+
rescue UnknownCurrency
|
|
71
|
+
nil
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Wraps the object in a +Currency+ unless it's already a +Currency+
|
|
75
|
+
# object.
|
|
76
|
+
#
|
|
77
|
+
# @param [Object] object The object to attempt and wrap as a +Currency+
|
|
78
|
+
# object.
|
|
79
|
+
#
|
|
80
|
+
# @return [Money::Currency]
|
|
81
|
+
#
|
|
82
|
+
# @example
|
|
83
|
+
# c1 = Money::Currency.new(:usd)
|
|
84
|
+
# Money::Currency.wrap(nil) #=> nil
|
|
85
|
+
# Money::Currency.wrap(c1) #=> #<Money::Currency id: usd ...>
|
|
86
|
+
# Money::Currency.wrap("usd") #=> #<Money::Currency id: usd ...>
|
|
87
|
+
def wrap(object)
|
|
88
|
+
if object.nil?
|
|
89
|
+
nil
|
|
90
|
+
elsif object.is_a?(Currency)
|
|
91
|
+
object
|
|
92
|
+
else
|
|
93
|
+
Currency.new(object)
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# List of known currencies.
|
|
98
|
+
#
|
|
99
|
+
# == monetary unit
|
|
100
|
+
# The standard unit of value of a currency, as the dollar in the United States or the peso in Mexico.
|
|
101
|
+
# http://www.answers.com/topic/monetary-unit
|
|
102
|
+
# == fractional monetary unit, subunit
|
|
103
|
+
# A monetary unit that is valued at a fraction (usually one hundredth) of the basic monetary unit
|
|
104
|
+
# http://www.answers.com/topic/fractional-monetary-unit-subunit
|
|
105
|
+
#
|
|
106
|
+
# See http://en.wikipedia.org/wiki/List_of_circulating_currencies and
|
|
107
|
+
# http://search.cpan.org/~tnguyen/Locale-Currency-Format-1.28/Format.pm
|
|
108
|
+
def table
|
|
109
|
+
@table ||= load_currencies
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# List the currencies imported and registered
|
|
113
|
+
# @return [Array]
|
|
114
|
+
#
|
|
115
|
+
# @example
|
|
116
|
+
# Money::Currency.iso_codes()
|
|
117
|
+
# [#<Currency ..USD>, 'CAD', 'EUR']...
|
|
118
|
+
def all
|
|
119
|
+
table.keys.map do |curr|
|
|
120
|
+
c = Currency.new(curr)
|
|
121
|
+
if c.priority.nil?
|
|
122
|
+
raise MissingAttributeError.new(:all, c.id, :priority)
|
|
123
|
+
end
|
|
124
|
+
c
|
|
125
|
+
end.sort_by(&:priority)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# We need a string-based validator before creating an unbounded number of
|
|
129
|
+
# symbols.
|
|
130
|
+
# http://www.randomhacks.net/articles/2007/01/20/13-ways-of-looking-at-a-ruby-symbol#11
|
|
131
|
+
# https://github.com/RubyMoney/money/issues/132
|
|
132
|
+
#
|
|
133
|
+
# @return [Set]
|
|
134
|
+
def stringified_keys
|
|
135
|
+
@stringified_keys ||= stringify_keys
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# Register a new currency
|
|
139
|
+
#
|
|
140
|
+
# @param curr [Hash] information about the currency
|
|
141
|
+
# @option priority [Numeric] a numerical value you can use to sort/group
|
|
142
|
+
# the currency list
|
|
143
|
+
# @option iso_code [String] the international 3-letter code as defined
|
|
144
|
+
# by the ISO 4217 standard
|
|
145
|
+
# @option iso_numeric [Integer] the international 3-digit code as
|
|
146
|
+
# defined by the ISO 4217 standard
|
|
147
|
+
# @option name [String] the currency name
|
|
148
|
+
# @option symbol [String] the currency symbol (UTF-8 encoded)
|
|
149
|
+
# @option subunit [String] the name of the fractional monetary unit
|
|
150
|
+
# @option subunit_to_unit [Numeric] the proportion between the unit and
|
|
151
|
+
# the subunit
|
|
152
|
+
# @option separator [String] character between the whole and fraction
|
|
153
|
+
# amounts
|
|
154
|
+
# @option delimiter [String] character between each thousands place
|
|
155
|
+
def register(curr)
|
|
156
|
+
key = curr.fetch(:iso_code).downcase.to_sym
|
|
157
|
+
table if !@table
|
|
158
|
+
@table[key] = curr
|
|
159
|
+
@stringified_keys = stringify_keys
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
# Unregister a currency.
|
|
164
|
+
#
|
|
165
|
+
# @param [Object] curr A Hash with the key `:iso_code`, or the ISO code
|
|
166
|
+
# as a String or Symbol.
|
|
167
|
+
#
|
|
168
|
+
# @return [Boolean] true if the currency previously existed, false
|
|
169
|
+
# if it didn't.
|
|
170
|
+
def unregister(curr)
|
|
171
|
+
if curr.is_a?(Hash)
|
|
172
|
+
key = curr.fetch(:iso_code).to_s.downcase.to_sym
|
|
173
|
+
else
|
|
174
|
+
key = curr.to_s.downcase.to_sym
|
|
175
|
+
end
|
|
176
|
+
existed = @table.delete(key)
|
|
177
|
+
@stringified_keys = stringify_keys
|
|
178
|
+
existed ? true : false
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def each
|
|
183
|
+
all.each { |c| yield(c) }
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
private
|
|
187
|
+
|
|
188
|
+
def stringify_keys
|
|
189
|
+
table.keys.each_with_object(Set.new) { |k, set| set.add(k.to_s.downcase) }
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
# @!attribute [r] id
|
|
194
|
+
# @return [Symbol] The symbol used to identify the currency, usually THE
|
|
195
|
+
# lowercase +iso_code+ attribute.
|
|
196
|
+
# @!attribute [r] priority
|
|
197
|
+
# @return [Integer] A numerical value you can use to sort/group the
|
|
198
|
+
# currency list.
|
|
199
|
+
# @!attribute [r] iso_code
|
|
200
|
+
# @return [String] The international 3-letter code as defined by the ISO
|
|
201
|
+
# 4217 standard.
|
|
202
|
+
# @!attribute [r] iso_numeric
|
|
203
|
+
# @return [String] The international 3-numeric code as defined by the ISO
|
|
204
|
+
# 4217 standard.
|
|
205
|
+
# @!attribute [r] name
|
|
206
|
+
# @return [String] The currency name.
|
|
207
|
+
# @!attribute [r] symbol
|
|
208
|
+
# @return [String] The currency symbol (UTF-8 encoded).
|
|
209
|
+
# @!attribute [r] disambiguate_symbol
|
|
210
|
+
# @return [String] Alternative currency used if symbol is ambiguous
|
|
211
|
+
# @!attribute [r] html_entity
|
|
212
|
+
# @return [String] The html entity for the currency symbol
|
|
213
|
+
# @!attribute [r] subunit
|
|
214
|
+
# @return [String] The name of the fractional monetary unit.
|
|
215
|
+
# @!attribute [r] subunit_to_unit
|
|
216
|
+
# @return [Integer] The proportion between the unit and the subunit
|
|
217
|
+
# @!attribute [r] decimal_mark
|
|
218
|
+
# @return [String] The decimal mark, or character used to separate the
|
|
219
|
+
# whole unit from the subunit.
|
|
220
|
+
# @!attribute [r] The
|
|
221
|
+
# @return [String] character used to separate thousands grouping of the
|
|
222
|
+
# whole unit.
|
|
223
|
+
# @!attribute [r] symbol_first
|
|
224
|
+
# @return [Boolean] Should the currency symbol precede the amount, or
|
|
225
|
+
# should it come after?
|
|
226
|
+
# @!attribute [r] smallest_denomination
|
|
227
|
+
# @return [Integer] Smallest amount of cash possible (in the subunit of
|
|
228
|
+
# this currency)
|
|
229
|
+
|
|
230
|
+
attr_reader :id, :priority, :iso_code, :iso_numeric, :name, :symbol,
|
|
231
|
+
:disambiguate_symbol, :html_entity, :subunit, :subunit_to_unit, :decimal_mark,
|
|
232
|
+
:thousands_separator, :symbol_first, :smallest_denomination
|
|
233
|
+
|
|
234
|
+
alias_method :separator, :decimal_mark
|
|
235
|
+
alias_method :delimiter, :thousands_separator
|
|
236
|
+
alias_method :eql?, :==
|
|
237
|
+
|
|
238
|
+
# Create a new +Currency+ object.
|
|
239
|
+
#
|
|
240
|
+
# @param [String, Symbol, #to_s] id Used to look into +table+ and retrieve
|
|
241
|
+
# the applicable attributes.
|
|
242
|
+
#
|
|
243
|
+
# @return [Money::Currency]
|
|
244
|
+
#
|
|
245
|
+
# @example
|
|
246
|
+
# Money::Currency.new(:usd) #=> #<Money::Currency id: usd ...>
|
|
247
|
+
def initialize(id)
|
|
248
|
+
id = id.to_s.downcase
|
|
249
|
+
unless self.class.stringified_keys.include?(id)
|
|
250
|
+
raise UnknownCurrency, "Unknown currency '#{id}'"
|
|
251
|
+
end
|
|
252
|
+
@id = id.to_sym
|
|
253
|
+
initialize_data!
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
# Compares +self+ with +other_currency+ against the value of +priority+
|
|
257
|
+
# attribute.
|
|
258
|
+
#
|
|
259
|
+
# @param [Money::Currency] other_currency The currency to compare to.
|
|
260
|
+
#
|
|
261
|
+
# @return [-1,0,1] -1 if less than, 0 is equal to, 1 if greater than
|
|
262
|
+
#
|
|
263
|
+
# @example
|
|
264
|
+
# c1 = Money::Currency.new(:usd)
|
|
265
|
+
# c2 = Money::Currency.new(:jpy)
|
|
266
|
+
# c1 <=> c2 #=> 1
|
|
267
|
+
# c2 <=> c1 #=> -1
|
|
268
|
+
# c1 <=> c1 #=> 0
|
|
269
|
+
def <=>(other_currency)
|
|
270
|
+
# <=> returns nil when one of the values is nil
|
|
271
|
+
comparison = (self.priority <=> other_currency.priority || 0) rescue 0
|
|
272
|
+
|
|
273
|
+
if comparison == 0
|
|
274
|
+
self.id.to_s <=> other_currency.id.to_s
|
|
275
|
+
else
|
|
276
|
+
comparison
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
# Compares +self+ with +other_currency+ and returns +true+ if the are the
|
|
281
|
+
# same or if their +id+ attributes match.
|
|
282
|
+
#
|
|
283
|
+
# @param [Money::Currency] other_currency The currency to compare to.
|
|
284
|
+
#
|
|
285
|
+
# @return [Boolean]
|
|
286
|
+
#
|
|
287
|
+
# @example
|
|
288
|
+
# c1 = Money::Currency.new(:usd)
|
|
289
|
+
# c2 = Money::Currency.new(:jpy)
|
|
290
|
+
# c1 == c1 #=> true
|
|
291
|
+
# c1 == c2 #=> false
|
|
292
|
+
def ==(other_currency)
|
|
293
|
+
self.equal?(other_currency) || compare_ids(other_currency)
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
def compare_ids(other_currency)
|
|
297
|
+
other_currency_id = if other_currency.is_a?(Currency)
|
|
298
|
+
other_currency.id.to_s.downcase
|
|
299
|
+
else
|
|
300
|
+
other_currency.to_s.downcase
|
|
301
|
+
end
|
|
302
|
+
self.id.to_s.downcase == other_currency_id
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
private :compare_ids
|
|
306
|
+
|
|
307
|
+
# Returns a Fixnum hash value based on the +id+ attribute in order to use
|
|
308
|
+
# functions like & (intersection), group_by, etc.
|
|
309
|
+
#
|
|
310
|
+
# @return [Fixnum]
|
|
311
|
+
#
|
|
312
|
+
# @example
|
|
313
|
+
# Money::Currency.new(:usd).hash #=> 428936
|
|
314
|
+
def hash
|
|
315
|
+
id.hash
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
# Returns a human readable representation.
|
|
319
|
+
#
|
|
320
|
+
# @return [String]
|
|
321
|
+
#
|
|
322
|
+
# @example
|
|
323
|
+
# Money::Currency.new(:usd) #=> #<Currency id: usd ...>
|
|
324
|
+
def inspect
|
|
325
|
+
"#<#{self.class.name} id: #{id}, priority: #{priority}, symbol_first: #{symbol_first}, thousands_separator: #{thousands_separator}, html_entity: #{html_entity}, decimal_mark: #{decimal_mark}, name: #{name}, symbol: #{symbol}, subunit_to_unit: #{subunit_to_unit}, exponent: #{exponent}, iso_code: #{iso_code}, iso_numeric: #{iso_numeric}, subunit: #{subunit}, smallest_denomination: #{smallest_denomination}>"
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
# Returns a string representation corresponding to the upcase +id+
|
|
329
|
+
# attribute.
|
|
330
|
+
#
|
|
331
|
+
# --
|
|
332
|
+
# DEV: id.to_s.upcase corresponds to iso_code but don't use ISO_CODE for consistency.
|
|
333
|
+
#
|
|
334
|
+
# @return [String]
|
|
335
|
+
#
|
|
336
|
+
# @example
|
|
337
|
+
# Money::Currency.new(:usd).to_s #=> "USD"
|
|
338
|
+
# Money::Currency.new(:eur).to_s #=> "EUR"
|
|
339
|
+
def to_s
|
|
340
|
+
id.to_s.upcase
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
# Returns a string representation corresponding to the upcase +id+
|
|
344
|
+
# attribute. Useful in cases where only implicit conversions are made.
|
|
345
|
+
#
|
|
346
|
+
# @return [String]
|
|
347
|
+
#
|
|
348
|
+
# @example
|
|
349
|
+
# Money::Currency.new(:usd).to_str #=> "USD"
|
|
350
|
+
# Money::Currency.new(:eur).to_str #=> "EUR"
|
|
351
|
+
def to_str
|
|
352
|
+
id.to_s.upcase
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
# Returns a symbol representation corresponding to the upcase +id+
|
|
356
|
+
# attribute.
|
|
357
|
+
#
|
|
358
|
+
# @return [Symbol]
|
|
359
|
+
#
|
|
360
|
+
# @example
|
|
361
|
+
# Money::Currency.new(:usd).to_sym #=> :USD
|
|
362
|
+
# Money::Currency.new(:eur).to_sym #=> :EUR
|
|
363
|
+
def to_sym
|
|
364
|
+
id.to_s.upcase.to_sym
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
# Conversation to +self+.
|
|
368
|
+
#
|
|
369
|
+
# @return [self]
|
|
370
|
+
def to_currency
|
|
371
|
+
self
|
|
372
|
+
end
|
|
373
|
+
|
|
374
|
+
# Returns currency symbol or iso code for currencies with no symbol.
|
|
375
|
+
#
|
|
376
|
+
# @return [String]
|
|
377
|
+
def code
|
|
378
|
+
symbol || iso_code
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
def symbol_first?
|
|
382
|
+
!!@symbol_first
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
# Returns the number of digits after the decimal separator.
|
|
386
|
+
#
|
|
387
|
+
# @return [Float]
|
|
388
|
+
def exponent
|
|
389
|
+
Math.log10(@subunit_to_unit) if @subunit_to_unit
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
# Cache decimal places for subunit_to_unit values. Common ones pre-cached.
|
|
393
|
+
def self.decimal_places_cache
|
|
394
|
+
@decimal_places_cache ||= {1 => 0, 10 => 1, 100 => 2, 1000 => 3}
|
|
395
|
+
end
|
|
396
|
+
|
|
397
|
+
# The number of decimal places needed.
|
|
398
|
+
#
|
|
399
|
+
# @return [Integer]
|
|
400
|
+
def decimal_places
|
|
401
|
+
cache[subunit_to_unit] ||= calculate_decimal_places(subunit_to_unit)
|
|
402
|
+
end
|
|
403
|
+
|
|
404
|
+
private
|
|
405
|
+
|
|
406
|
+
def cache
|
|
407
|
+
self.class.decimal_places_cache
|
|
408
|
+
end
|
|
409
|
+
|
|
410
|
+
# If we need to figure out how many decimal places we need we
|
|
411
|
+
# use repeated integer division.
|
|
412
|
+
def calculate_decimal_places(num)
|
|
413
|
+
i = 1
|
|
414
|
+
while num >= 10
|
|
415
|
+
num /= 10
|
|
416
|
+
i += 1 if num >= 10
|
|
417
|
+
end
|
|
418
|
+
i
|
|
419
|
+
end
|
|
420
|
+
|
|
421
|
+
def initialize_data!
|
|
422
|
+
data = self.class.table[@id]
|
|
423
|
+
@alternate_symbols = data[:alternate_symbols]
|
|
424
|
+
@decimal_mark = data[:decimal_mark]
|
|
425
|
+
@disambiguate_symbol = data[:disambiguate_symbol]
|
|
426
|
+
@html_entity = data[:html_entity]
|
|
427
|
+
@iso_code = data[:iso_code]
|
|
428
|
+
@iso_numeric = data[:iso_numeric]
|
|
429
|
+
@name = data[:name]
|
|
430
|
+
@priority = data[:priority]
|
|
431
|
+
@smallest_denomination = data[:smallest_denomination]
|
|
432
|
+
@subunit = data[:subunit]
|
|
433
|
+
@subunit_to_unit = data[:subunit_to_unit]
|
|
434
|
+
@symbol = data[:symbol]
|
|
435
|
+
@symbol_first = data[:symbol_first]
|
|
436
|
+
@thousands_separator = data[:thousands_separator]
|
|
437
|
+
end
|
|
438
|
+
end
|
|
439
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module YeshuaCrm
|
|
2
|
+
module ExternalAssetsHelper
|
|
3
|
+
include ActionView::Helpers::JavaScriptHelper
|
|
4
|
+
|
|
5
|
+
def select2_assets
|
|
6
|
+
return if @select2_tag_included
|
|
7
|
+
@select2_tag_included = true
|
|
8
|
+
javascript_include_tag('select2', :plugin => 'yeshua_crm') + stylesheet_link_tag('select2', :plugin => 'yeshua_crm')
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def chartjs_assets
|
|
12
|
+
return if @chartjs_tag_included
|
|
13
|
+
@chartjs_tag_included = true
|
|
14
|
+
javascript_include_tag('Chart.bundle.min', :plugin => 'yeshua_crm')
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
module YeshuaCrm
|
|
2
|
+
module FormTagHelper
|
|
3
|
+
# Allows include select2 into your views.
|
|
4
|
+
#
|
|
5
|
+
# ==== Examples
|
|
6
|
+
# select2_tag 'city_id', '<option value="1">Lisbon</option>...'
|
|
7
|
+
# select2_tag 'city_id', options_for_select(...)
|
|
8
|
+
# select2_tag 'tag_list', nil, :multiple => true, :data => [{ id: 0, text: 'deal' }, ...], :tags => true, :include_hidden => false %>
|
|
9
|
+
# select2_tag 'tag_list', options_for_select(...), :multiple => true, :style => 'width: 100%;', :url => '/tags', :placeholder => '+ add tag', :tags => true %>
|
|
10
|
+
#
|
|
11
|
+
# You may use select_tag options and additional options.
|
|
12
|
+
#
|
|
13
|
+
# ==== Additional options
|
|
14
|
+
# * <tt>:url</tt> Allows searches for remote data using the ajax.
|
|
15
|
+
# * <tt>:data</tt> Load dropdown options from a local array if +url+ option not set.
|
|
16
|
+
# * <tt>:placeholder</tt> Supports displaying a placeholder value.
|
|
17
|
+
# * <tt>:include_hidden</tt> Adds hidden field after select when +multiple+ option true. Default value true.
|
|
18
|
+
#
|
|
19
|
+
# <b>Note:</b> The HTML specification says when +multiple+ parameter passed to select and all options got deselected
|
|
20
|
+
# web browsers do not send any value to server.
|
|
21
|
+
#
|
|
22
|
+
# In case if you don't want the helper to generate this hidden field you can specify
|
|
23
|
+
# <tt>include_hidden: false</tt> option.
|
|
24
|
+
#
|
|
25
|
+
# Also aliased as: select2
|
|
26
|
+
#
|
|
27
|
+
# select2 'city_id', options_for_select(...)
|
|
28
|
+
#
|
|
29
|
+
def select2_tag(name, option_tags = nil, options = {})
|
|
30
|
+
id = sanitize_to_id(name)
|
|
31
|
+
placeholder = options[:placeholder] || 'Select ...'
|
|
32
|
+
|
|
33
|
+
content_for(:header_tags) { select2_assets }
|
|
34
|
+
result = select_tag(name, option_tags, options)
|
|
35
|
+
if options[:multiple] && options.fetch(:include_hidden, true)
|
|
36
|
+
result << hidden_field_tag("#{name}[]", '')
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
result << javascript_tag(<<-JS)
|
|
40
|
+
$(function () {
|
|
41
|
+
$('select#' + '#{id}').select2({
|
|
42
|
+
#{select2_data_source_options(options)},
|
|
43
|
+
#{select2_tags_options(options)},
|
|
44
|
+
placeholder: '#{placeholder}'
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
JS
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
alias select2 select2_tag
|
|
51
|
+
|
|
52
|
+
# Transforms select filter field into select2
|
|
53
|
+
#
|
|
54
|
+
# ==== Examples
|
|
55
|
+
# transform_to_select2 'issue_tags', url: auto_complete_tags_url
|
|
56
|
+
# transform_to_select2 'manager_id', format_state: 'formatStateWithAvatar', min_input_length: 1, url: '/managers'
|
|
57
|
+
#
|
|
58
|
+
# ==== Options
|
|
59
|
+
# * <tt>:url</tt> Defines URL to search remote data using the ajax.
|
|
60
|
+
# * <tt>:format_state</tt> Defines template of search results in the drop-down.
|
|
61
|
+
# * <tt>:min_input_length</tt> Minimum number of characters required to start a search. Default value 0.
|
|
62
|
+
# * <tt>:width</tt> Sets the width of the control. Default value '60%'.
|
|
63
|
+
#
|
|
64
|
+
def transform_to_select2(field, options = {})
|
|
65
|
+
return if field.empty?
|
|
66
|
+
|
|
67
|
+
result = ''.html_safe
|
|
68
|
+
unless @transform_to_select2_included
|
|
69
|
+
result << javascript_include_tag('select2_helpers', plugin: 'yeshua_crm')
|
|
70
|
+
@transform_to_select2_included = true
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
result << javascript_tag(<<-JS)
|
|
74
|
+
select2Filters['#{field}'] = {
|
|
75
|
+
url: '#{options[:url].to_s}',
|
|
76
|
+
formatState: #{options.fetch(:format_state, 'undefined')},
|
|
77
|
+
minimumInputLength: #{options.fetch(:min_input_length, 0)},
|
|
78
|
+
width: '#{options.fetch(:with, '60%')}'
|
|
79
|
+
};
|
|
80
|
+
JS
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
private
|
|
84
|
+
|
|
85
|
+
def select2_data_source_options(options = {})
|
|
86
|
+
if options[:url].to_s.empty?
|
|
87
|
+
"data: #{options.fetch(:data, []).to_json}"
|
|
88
|
+
else
|
|
89
|
+
"ajax: {
|
|
90
|
+
url: '#{options[:url]}',
|
|
91
|
+
dataType: 'json',
|
|
92
|
+
delay: 250,
|
|
93
|
+
data: function (params) {
|
|
94
|
+
return { q: params.term };
|
|
95
|
+
},
|
|
96
|
+
processResults: function (data, params) {
|
|
97
|
+
return { results: data };
|
|
98
|
+
},
|
|
99
|
+
cache: true
|
|
100
|
+
}"
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def select2_tags_options(options = {})
|
|
105
|
+
if options.fetch(:tags, false)
|
|
106
|
+
"tags: true,
|
|
107
|
+
tokenSeparators: [','],
|
|
108
|
+
createTag: function (params) {
|
|
109
|
+
var term = $.trim(params.term);
|
|
110
|
+
if (term === '' || term.indexOf(',') > -1) {
|
|
111
|
+
return null; // Return null to disable tag creation
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
id: term,
|
|
115
|
+
text: term
|
|
116
|
+
}
|
|
117
|
+
}"
|
|
118
|
+
else
|
|
119
|
+
'tags: false'
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module YeshuaCrm
|
|
2
|
+
module TagsHelper
|
|
3
|
+
# See the README for an example using tag_cloud.
|
|
4
|
+
def tag_cloud(tags, classes)
|
|
5
|
+
return if tags.empty?
|
|
6
|
+
max_count = tags.sort_by(&:count).last.count.to_f
|
|
7
|
+
tags.each do |tag|
|
|
8
|
+
index = ((tag.count / max_count) * (classes.size - 1)).round
|
|
9
|
+
yield tag, classes[index]
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module YeshuaCrm
|
|
2
|
+
module ActsAsVotable
|
|
3
|
+
module Helpers
|
|
4
|
+
# this helper provides methods that help find what words are
|
|
5
|
+
# up votes and what words are down votes
|
|
6
|
+
#
|
|
7
|
+
# It can be called
|
|
8
|
+
#
|
|
9
|
+
# votable_object.votable_words.that_mean_true
|
|
10
|
+
#
|
|
11
|
+
module Words
|
|
12
|
+
def votable_words
|
|
13
|
+
VotableWords
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
class VotableWords
|
|
18
|
+
def self.that_mean_true
|
|
19
|
+
['up', 'upvote', 'like', 'liked', 'positive', 'yes', 'good', 'true', 1, true]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def self.that_mean_false
|
|
23
|
+
['down', 'downvote', 'dislike', 'disliked', 'negative', 'no', 'bad', 'false', 0, false]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# check is word is a true or bad vote
|
|
27
|
+
# if the word is unknown, then it counts it as a true/good
|
|
28
|
+
# vote. this exists to allow all voting to be good by default
|
|
29
|
+
def self.meaning_of(word)
|
|
30
|
+
!that_mean_false.include?(word)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|