orbital_fields 0.0.14
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +8 -0
- data/Gemfile +14 -0
- data/Gemfile.lock +97 -0
- data/README.md +28 -0
- data/Rakefile +2 -0
- data/lib/orbital_fields.rb +9 -0
- data/lib/orbital_fields/attribute_security.rb +15 -0
- data/lib/orbital_fields/engine.rb +5 -0
- data/lib/orbital_fields/kaminari_proxy.rb +11 -0
- data/lib/orbital_fields/markdown.rb +90 -0
- data/lib/orbital_fields/short_id.rb +24 -0
- data/lib/orbital_fields/tokenize.rb +126 -0
- data/lib/orbital_fields/url_lookup.rb +73 -0
- data/lib/orbital_fields/version.rb +3 -0
- data/orbital-fields.gemspec +27 -0
- data/test/orbital-fields_test.rb +7 -0
- data/test/test_helper.rb +15 -0
- data/vendor/assets/flash/orbital_fields/clippy.swf +0 -0
- data/vendor/assets/stylesheets/orbital_fields/pygments.css.erb +39 -0
- metadata +130 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
|
3
|
+
# Declare your gem's dependencies in orbital-fields.gemspec.
|
4
|
+
# Bundler will treat runtime dependencies like base dependencies, and
|
5
|
+
# development dependencies will be added by default to the :development group.
|
6
|
+
gemspec
|
7
|
+
|
8
|
+
# Declare any dependencies that are still in development here instead of in
|
9
|
+
# your gemspec. These might include edge Rails or gems from your path or
|
10
|
+
# Git. Remember to move these dependencies to your gemspec before releasing
|
11
|
+
# your gem to rubygems.org.
|
12
|
+
|
13
|
+
# To use debugger
|
14
|
+
# gem 'ruby-debug19', :require => 'ruby-debug'
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
orbital-fields (0.0.1)
|
5
|
+
rails (~> 3.2.3)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: http://rubygems.org/
|
9
|
+
specs:
|
10
|
+
actionmailer (3.2.3)
|
11
|
+
actionpack (= 3.2.3)
|
12
|
+
mail (~> 2.4.4)
|
13
|
+
actionpack (3.2.3)
|
14
|
+
activemodel (= 3.2.3)
|
15
|
+
activesupport (= 3.2.3)
|
16
|
+
builder (~> 3.0.0)
|
17
|
+
erubis (~> 2.7.0)
|
18
|
+
journey (~> 1.0.1)
|
19
|
+
rack (~> 1.4.0)
|
20
|
+
rack-cache (~> 1.2)
|
21
|
+
rack-test (~> 0.6.1)
|
22
|
+
sprockets (~> 2.1.2)
|
23
|
+
activemodel (3.2.3)
|
24
|
+
activesupport (= 3.2.3)
|
25
|
+
builder (~> 3.0.0)
|
26
|
+
activerecord (3.2.3)
|
27
|
+
activemodel (= 3.2.3)
|
28
|
+
activesupport (= 3.2.3)
|
29
|
+
arel (~> 3.0.2)
|
30
|
+
tzinfo (~> 0.3.29)
|
31
|
+
activeresource (3.2.3)
|
32
|
+
activemodel (= 3.2.3)
|
33
|
+
activesupport (= 3.2.3)
|
34
|
+
activesupport (3.2.3)
|
35
|
+
i18n (~> 0.6)
|
36
|
+
multi_json (~> 1.0)
|
37
|
+
arel (3.0.2)
|
38
|
+
builder (3.0.0)
|
39
|
+
erubis (2.7.0)
|
40
|
+
hike (1.2.1)
|
41
|
+
i18n (0.6.0)
|
42
|
+
journey (1.0.3)
|
43
|
+
jquery-rails (2.0.2)
|
44
|
+
railties (>= 3.2.0, < 5.0)
|
45
|
+
thor (~> 0.14)
|
46
|
+
json (1.7.3)
|
47
|
+
mail (2.4.4)
|
48
|
+
i18n (>= 0.4.0)
|
49
|
+
mime-types (~> 1.16)
|
50
|
+
treetop (~> 1.4.8)
|
51
|
+
mime-types (1.18)
|
52
|
+
multi_json (1.3.5)
|
53
|
+
polyglot (0.3.3)
|
54
|
+
rack (1.4.1)
|
55
|
+
rack-cache (1.2)
|
56
|
+
rack (>= 0.4)
|
57
|
+
rack-ssl (1.3.2)
|
58
|
+
rack
|
59
|
+
rack-test (0.6.1)
|
60
|
+
rack (>= 1.0)
|
61
|
+
rails (3.2.3)
|
62
|
+
actionmailer (= 3.2.3)
|
63
|
+
actionpack (= 3.2.3)
|
64
|
+
activerecord (= 3.2.3)
|
65
|
+
activeresource (= 3.2.3)
|
66
|
+
activesupport (= 3.2.3)
|
67
|
+
bundler (~> 1.0)
|
68
|
+
railties (= 3.2.3)
|
69
|
+
railties (3.2.3)
|
70
|
+
actionpack (= 3.2.3)
|
71
|
+
activesupport (= 3.2.3)
|
72
|
+
rack-ssl (~> 1.3.2)
|
73
|
+
rake (>= 0.8.7)
|
74
|
+
rdoc (~> 3.4)
|
75
|
+
thor (~> 0.14.6)
|
76
|
+
rake (0.9.2.2)
|
77
|
+
rdoc (3.12)
|
78
|
+
json (~> 1.4)
|
79
|
+
sprockets (2.1.3)
|
80
|
+
hike (~> 1.2)
|
81
|
+
rack (~> 1.0)
|
82
|
+
tilt (~> 1.1, != 1.3.0)
|
83
|
+
sqlite3 (1.3.6)
|
84
|
+
thor (0.14.6)
|
85
|
+
tilt (1.3.3)
|
86
|
+
treetop (1.4.10)
|
87
|
+
polyglot
|
88
|
+
polyglot (>= 0.3.1)
|
89
|
+
tzinfo (0.3.33)
|
90
|
+
|
91
|
+
PLATFORMS
|
92
|
+
ruby
|
93
|
+
|
94
|
+
DEPENDENCIES
|
95
|
+
jquery-rails
|
96
|
+
orbital-fields!
|
97
|
+
sqlite3
|
data/README.md
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# Orbital-Fields
|
2
|
+
|
3
|
+
The (possibly) reusable parts of Orbital.
|
4
|
+
|
5
|
+
### Contributing
|
6
|
+
By contributing code, documentation or media files ("The Material") to the project ("Orbital"),
|
7
|
+
you hereby atest to owning the copyright on the material, or having the right to sublicense the
|
8
|
+
material. You hereby agree to provide the material to the project under the "MIT" license.
|
9
|
+
This license is located below.
|
10
|
+
|
11
|
+
### License & Copyright
|
12
|
+
|
13
|
+
Copyright (C) 2012 Kaz Walker
|
14
|
+
|
15
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
16
|
+
associated documentation files (the "Software"), to deal in the Software without restriction,
|
17
|
+
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
18
|
+
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
|
19
|
+
subject to the following conditions:
|
20
|
+
|
21
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial
|
22
|
+
portions of the Software.
|
23
|
+
|
24
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
25
|
+
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
26
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
27
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
28
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
module OrbitalFields
|
2
|
+
require "orbital_fields/attribute_security"
|
3
|
+
require "orbital_fields/engine"
|
4
|
+
require "orbital_fields/kaminari_proxy"
|
5
|
+
require "orbital_fields/markdown"
|
6
|
+
require "orbital_fields/short_id"
|
7
|
+
require "orbital_fields/tokenize"
|
8
|
+
require "orbital_fields/url_lookup"
|
9
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module OrbitalFields
|
2
|
+
module AttributeSecurity
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
included do
|
5
|
+
attr_accessible as: :none
|
6
|
+
attr_accessor :access_role
|
7
|
+
attr_accessor :accessing_user
|
8
|
+
end
|
9
|
+
private
|
10
|
+
def mass_assignment_authorizer(role=:none)
|
11
|
+
access_role ||= role
|
12
|
+
self.class.active_authorizer[access_role]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'redcarpet'
|
2
|
+
require 'redcarpet/render_strip'
|
3
|
+
require 'pygments'
|
4
|
+
module OrbitalFields
|
5
|
+
module Markdown
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
included do
|
8
|
+
class_attribute :current_class
|
9
|
+
self.current_class = Kernel.const_get(self.name)
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
def markdown_fields(*fields)
|
14
|
+
fields.each do |md_field|
|
15
|
+
raise TypeError, "Argument is not a symbol" unless md_field.class == Symbol
|
16
|
+
raise NoMethodError, "Argument '#{md_field.to_s}' is not a defined field in the #{self.current_class.to_s} class" unless self.current_class.fields.include?(md_field.to_s)
|
17
|
+
clean_method_name = "clean_#{md_field.to_s}".to_sym
|
18
|
+
formatted_method_name = "formatted_#{md_field.to_s}".to_sym
|
19
|
+
define_method clean_method_name do
|
20
|
+
strip_markdown(send(md_field))
|
21
|
+
end unless method_defined? clean_method_name
|
22
|
+
define_method formatted_method_name do
|
23
|
+
markdown(send(md_field))
|
24
|
+
end unless method_defined? formatted_method_name
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def markdown(text)
|
30
|
+
renderer = HTMLwithPygments.new(hard_wrap: true, filter_html: true)
|
31
|
+
options = {
|
32
|
+
autolink: true,
|
33
|
+
no_intra_emphasis: true,
|
34
|
+
fenced_code_blocks: true,
|
35
|
+
lax_html_blocks: true,
|
36
|
+
strikethrough: true,
|
37
|
+
superscript: true
|
38
|
+
}
|
39
|
+
Redcarpet::Markdown.new(renderer, options).render(text).html_safe
|
40
|
+
end
|
41
|
+
|
42
|
+
def strip_markdown(text)
|
43
|
+
renderer = Redcarpet::Render::StripDown.new
|
44
|
+
|
45
|
+
redcarpet = Redcarpet::Markdown.new(renderer)
|
46
|
+
|
47
|
+
redcarpet.render(text)
|
48
|
+
end
|
49
|
+
|
50
|
+
class HTMLwithPygments < Redcarpet::Render::HTML
|
51
|
+
def block_code(code, language)
|
52
|
+
input_name = language.to_s
|
53
|
+
input_name = input_name.slice(0..19)+"..."+input_name.slice(-1..-20) if input_name.length > 40
|
54
|
+
language = language.match(/\.([^\.]*)$/i)[1].downcase if language =~ /\.([^\.]*)$/i
|
55
|
+
language = "rhtml" if language == "erb"
|
56
|
+
lexer = Pygments::Lexer.find_by_alias(language)
|
57
|
+
lexer_name = lexer.name.downcase unless lexer.nil?
|
58
|
+
lexer_name ||= "text"
|
59
|
+
lexer ||= Pygments::Lexer.find_by_alias(lexer_name)
|
60
|
+
<<-EOS
|
61
|
+
<div class="code_block">
|
62
|
+
<div class="code_header">
|
63
|
+
#{CGI.escapeHTML(input_name)} rendered as #{CGI.escapeHTML(lexer.name)}
|
64
|
+
#{clippy(code)}
|
65
|
+
</div>
|
66
|
+
#{Pygments.highlight(code, lexer: lexer_name)}
|
67
|
+
</div>
|
68
|
+
EOS
|
69
|
+
end
|
70
|
+
|
71
|
+
def clippy(text)
|
72
|
+
id = "clippy_#{rand(10000000)}"
|
73
|
+
<<-EOS
|
74
|
+
<div id="#{id}" class="clippy">
|
75
|
+
<span style="display:none;visibility:hidden" class="clippy_code">#{CGI.escapeHTML(text)}</span>
|
76
|
+
<span class="clippy_label"></span>
|
77
|
+
<object type="application/x-shockwave-flash" data="/assets/orbital_fields/clippy.swf" width="14" height="14" id="#{id}_flash">
|
78
|
+
<param name="movie" value="/assets/orbital_fields/clippy.swf" />
|
79
|
+
<param name="allowScriptAccess" value="always" />
|
80
|
+
<param name="quality" value="high" />
|
81
|
+
<param name="scale" value="noscale" />
|
82
|
+
<param name="FlashVars" value="target=#{CGI.escape('#' + id)}" />
|
83
|
+
<param name="bgcolor" value="#E0E0E0" />
|
84
|
+
</object>
|
85
|
+
</div>
|
86
|
+
EOS
|
87
|
+
end
|
88
|
+
end # HTMLwithPygments
|
89
|
+
end # Markdown
|
90
|
+
end # SlipFields
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require "all_your_base/are/belong_to_us"
|
2
|
+
module OrbitalFields
|
3
|
+
module ShortId
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
module ClassMethods
|
7
|
+
def find_by_short_id(input)
|
8
|
+
return nil unless input =~ /[a-z0-9]{1,19}/i
|
9
|
+
id = input.upcase.from_base_36.to_base_16.downcase
|
10
|
+
return nil if id.length > 24
|
11
|
+
id = id.rjust(24, "0") if id.length < 24
|
12
|
+
find(id)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def short_id
|
17
|
+
id.to_s.hex.to_base_36.downcase
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_param
|
21
|
+
short_id
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
module OrbitalFields
|
2
|
+
module Tokenize
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
included do
|
5
|
+
class_attribute :current_class
|
6
|
+
class_attribute :token_associations
|
7
|
+
self.current_class = Kernel.const_get(self.name)
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
|
12
|
+
def tokenize_associations(*args)
|
13
|
+
set_callback :save, :after, :tokenize_callback
|
14
|
+
association_symbols = []
|
15
|
+
tokenize = args.extract_options!
|
16
|
+
tokenize.each do |key, val|
|
17
|
+
args << {key => val}
|
18
|
+
end
|
19
|
+
args.each do |association|
|
20
|
+
raise TypeError, "Argument is not a symbol or hash" unless association.class == Symbol || association.class == Hash
|
21
|
+
if association.class == Hash
|
22
|
+
association_hash = association
|
23
|
+
association = association.keys[0]
|
24
|
+
raise ArgumentError, "If an argument is a hash, it must have a key named 'display'" unless association_hash[association].has_key?(:display)
|
25
|
+
association_display = association_hash[association][:display]
|
26
|
+
raise TypeError, "Display argument is not a symbol" unless association_display.class == Symbol
|
27
|
+
end
|
28
|
+
|
29
|
+
unless self.current_class.associations.include?(association.to_s)
|
30
|
+
raise NoMethodError, "Argument '#{association.to_s}' is not a defined association in the #{self.current_class} class"
|
31
|
+
end
|
32
|
+
|
33
|
+
association_symbols << association
|
34
|
+
|
35
|
+
association_display ||= :name
|
36
|
+
|
37
|
+
association_class = Kernel.const_get(self.current_class.associations[association.to_s].class_name)
|
38
|
+
|
39
|
+
unless association_class.attribute_method?(association_display)
|
40
|
+
raise ArgumentError, "The #{association_class} class does not have a '#{association_display}' attribute"
|
41
|
+
end
|
42
|
+
|
43
|
+
setter_method_name = "#{association.to_s.singularize}_tokens="
|
44
|
+
getter_method_name = "#{association.to_s.singularize}_tokens"
|
45
|
+
json_method_name = "#{association.to_s.singularize}_tokens_json"
|
46
|
+
|
47
|
+
define_method(setter_method_name) do |tokens|
|
48
|
+
if tokens.blank?
|
49
|
+
eval("@#{getter_method_name} = []")
|
50
|
+
else
|
51
|
+
id_array = tokens.split(",")
|
52
|
+
id_array = id_array.uniq
|
53
|
+
instance_variable_set("@#{getter_method_name}", id_array)
|
54
|
+
end
|
55
|
+
end unless method_defined? setter_method_name
|
56
|
+
|
57
|
+
define_method(getter_method_name) do
|
58
|
+
eval("@#{getter_method_name} ||= []")
|
59
|
+
return eval("@#{getter_method_name}.join(',')") unless eval("@#{getter_method_name}.blank?")
|
60
|
+
return "" if eval("#{association.to_s}.blank?")
|
61
|
+
eval("#{association.to_s}.map(&:id).join(',')")
|
62
|
+
end unless method_defined? getter_method_name
|
63
|
+
|
64
|
+
define_method(json_method_name) do
|
65
|
+
eval("@#{getter_method_name} ||= []")
|
66
|
+
return association_class.where(:_id.in => eval("@#{getter_method_name}")).only(:id,association_display).map(&:attributes).to_json unless eval("@#{getter_method_name}.blank?")
|
67
|
+
eval("#{association.to_s}.only(:id, :#{association_display.to_s}).map(&:attributes).to_json")
|
68
|
+
end unless method_defined? json_method_name
|
69
|
+
end # args.each
|
70
|
+
self.token_associations = association_symbols
|
71
|
+
end # tokenize_associations
|
72
|
+
end # ClassMethods
|
73
|
+
|
74
|
+
def tokenize_callback
|
75
|
+
self.token_associations.each do |association|
|
76
|
+
association_class = Kernel.const_get(associations[association.to_s].class_name)
|
77
|
+
getter_method_name = "#{association.to_s.singularize}_tokens"
|
78
|
+
if eval("@#{getter_method_name}.blank?")
|
79
|
+
eval("#{association.to_s}.clear") unless eval("#{association.to_s}.blank?")
|
80
|
+
else
|
81
|
+
eval("self.#{association.to_s} = association_class.find(@#{getter_method_name})")
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
class TokenFieldValidator < ActiveModel::EachValidator
|
87
|
+
def validate_each(record, attribute, value)
|
88
|
+
return if value.blank? && !options[:allow_blank].nil? && options[:allow_blank] == true
|
89
|
+
|
90
|
+
minimum = options[:minimum].to_i unless options[:minimum].nil?
|
91
|
+
minimum ||= 1
|
92
|
+
maximum = options[:maximum].to_i unless options[:maximum].nil?
|
93
|
+
maximum ||= 0
|
94
|
+
seperator = options[:seperator] unless options[:seperator].nil?
|
95
|
+
seperator ||= ","
|
96
|
+
exclude = nil
|
97
|
+
unless options[:exclude].nil?
|
98
|
+
exclude = options[:exclude]
|
99
|
+
raise ArgumentError, "The exclude option must be the name of an association" unless record.associations.include?(exclude)
|
100
|
+
exclude_assoc = record.send(exclude)
|
101
|
+
raise "The association given by the exclude_assoc_id option cannot be nil if it is given" if exclude_assoc.nil?
|
102
|
+
end
|
103
|
+
exclude_assoc ||= nil
|
104
|
+
id_regex = options[:id_regex] unless options[:id_regex].nil?
|
105
|
+
id_regex = /^[a-f0-9]{24}$/i
|
106
|
+
raise ArgumentError, "The id_regex option must be a regular expression" unless id_regex.class == Regexp
|
107
|
+
raise ArgumentError, "The id_regex option doesn't match the id of the exclude_assoc_id option" if !exclude_assoc.nil? && exclude_assoc.id.to_s !~ id_regex
|
108
|
+
|
109
|
+
# Setup the array
|
110
|
+
token_field_array = value.split(seperator)
|
111
|
+
|
112
|
+
# Length validations
|
113
|
+
record.errors[attribute] << (options[:message] || I18n.t("mongoid.errors.models.#{record.class.to_s.downcase}.attributes.#{attribute.to_s}.too_few_tokens", default: "requires at least #{minimum} #{"entry".pluralize(minimum)}")) if token_field_array.length < minimum
|
114
|
+
record.errors[attribute] << (options[:message] || I18n.t("mongoid.errors.models.#{record.class.to_s.downcase}.attributes.#{attribute.to_s}.too_many_tokens", default: "can't have more than #{maximum} #{"entry".pluralize(maximum)}")) if maximum != 0 && token_field_array.length > maximum
|
115
|
+
|
116
|
+
# Format validation
|
117
|
+
token_field_array.each do |token|
|
118
|
+
record.errors[attribute] << (options[:message] || I18n.t("mongoid.errors.models.#{record.class.to_s.downcase}.attributes.#{attribute.to_s}.bad_token", default: "contains an invalid entry")) if token !~ id_regex
|
119
|
+
end
|
120
|
+
|
121
|
+
# Exclusion validation
|
122
|
+
record.errors[attribute] << (options[:message] || I18n.t("mongoid.errors.models.#{record.class.to_s.downcase}.attributes.#{attribute.to_s}.exclude_token", default: "can't include the #{record.class.to_s.downcase}'s #{exclude}")) if !exclude_assoc.nil? && token_field_array.include?(exclude_assoc.id.to_s)
|
123
|
+
end # validate_each
|
124
|
+
end # TokenFieldValidator
|
125
|
+
end # Tokenize
|
126
|
+
end # OrbitalFields
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module OrbitalFields
|
2
|
+
module UrlLookup
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
included do
|
5
|
+
class_attribute :lookup_field
|
6
|
+
end
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
def find_by_url_lookup(input,single_result=true)
|
10
|
+
input = input.strip
|
11
|
+
return nil unless input =~ /^[a-z0-9\-]*$/i
|
12
|
+
if single_result
|
13
|
+
where(url_lookup: /^#{input}$/i).first
|
14
|
+
else
|
15
|
+
where(url_lookup: /^#{input}$/i)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def url_lookup_field(lookup_field)
|
20
|
+
raise ArgumentError, "Argument must be a symbol" unless lookup_field.class == Symbol
|
21
|
+
raise NoMethodError, "The field '#{lookup_field.to_s}' is not defined" unless fields.include?(lookup_field.to_s)
|
22
|
+
self.lookup_field = lookup_field
|
23
|
+
field :url_lookup, type: String, default: ""
|
24
|
+
validates self.lookup_field, url_lookup_field: true
|
25
|
+
set_callback :save, :before, :url_lookup_callback
|
26
|
+
end
|
27
|
+
end # ClassMethods
|
28
|
+
|
29
|
+
def find_by_url_lookup(input)
|
30
|
+
self.class.find_by_url_lookup(input)
|
31
|
+
end
|
32
|
+
|
33
|
+
def make_url_safe(input)
|
34
|
+
return nil unless input.class == String
|
35
|
+
input = input.strip
|
36
|
+
input.downcase!
|
37
|
+
input = input.gsub(/'|"/, "")
|
38
|
+
input = input.gsub(/!|\?/, "_")
|
39
|
+
input = input.gsub(/[\W]{1,}/, "_")
|
40
|
+
input = input.gsub(/_{2,}/, "_")
|
41
|
+
input = input.dasherize
|
42
|
+
input = input.gsub(/^(-{1,})?([a-z0-9][a-z0-9\-]*[a-z0-9])(-{1,})?$/, '\2')
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_param
|
46
|
+
url_lookup
|
47
|
+
end
|
48
|
+
|
49
|
+
def url_lookup_field
|
50
|
+
self.lookup_field
|
51
|
+
end
|
52
|
+
|
53
|
+
def url_lookup_callback
|
54
|
+
if new_record? || send("#{self.lookup_field.to_s}_changed?") || url_lookup.blank?
|
55
|
+
self.url_lookup = make_url_safe(send(self.lookup_field.to_s))
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
class UrlLookupFieldValidator < ActiveModel::EachValidator
|
60
|
+
def validate_each(record,attribute,value)
|
61
|
+
# Return if value is blank
|
62
|
+
return if value.blank?
|
63
|
+
url_lookup = record.make_url_safe(value)
|
64
|
+
matching_record = record.find_by_url_lookup(url_lookup)
|
65
|
+
if !matching_record.nil? && matching_record != record
|
66
|
+
record.errors[record.lookup_field] << (options[:message] || "already exists")
|
67
|
+
return
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end # UrlLookupFieldValidator
|
71
|
+
end # UrlLookup
|
72
|
+
end # OrbitalFields
|
73
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
lib = File.expand_path('../lib/', __FILE__)
|
2
|
+
$:.unshift lib unless $:.include?(lib)
|
3
|
+
#$:.push File.expand_path("../lib", __FILE__)
|
4
|
+
|
5
|
+
# Maintain your gem's version:
|
6
|
+
require "orbital_fields/version"
|
7
|
+
|
8
|
+
# Describe your gem and declare its dependencies:
|
9
|
+
Gem::Specification.new do |gem|
|
10
|
+
gem.authors = ["Kaz Walker"]
|
11
|
+
gem.email = ["kaz.walker@slipline.ca"]
|
12
|
+
gem.description = %q{The (possibly) reusable partrs of Orbital.}
|
13
|
+
gem.summary = gem.summary
|
14
|
+
gem.homepage = "http://www.orbitalsoft.org"
|
15
|
+
|
16
|
+
gem.add_dependency "rails", "~> 3.2.3"
|
17
|
+
gem.add_dependency "all-your-base", "~> 0.3.0"
|
18
|
+
gem.add_dependency "redcarpet", "~> 2.1.0"
|
19
|
+
gem.add_dependency "pygments.rb", "~> 0.2.12"
|
20
|
+
|
21
|
+
gem.files = `git ls-files`.split($\)
|
22
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
23
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
24
|
+
gem.name = "orbital_fields"
|
25
|
+
gem.require_paths = ["lib"]
|
26
|
+
gem.version = OrbitalFields::VERSION
|
27
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# Configure Rails Environment
|
2
|
+
ENV["RAILS_ENV"] = "test"
|
3
|
+
|
4
|
+
require File.expand_path("../dummy/config/environment.rb", __FILE__)
|
5
|
+
require "rails/test_help"
|
6
|
+
|
7
|
+
Rails.backtrace_cleaner.remove_silencers!
|
8
|
+
|
9
|
+
# Load support files
|
10
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
11
|
+
|
12
|
+
# Load fixtures from the engine
|
13
|
+
if ActiveSupport::TestCase.method_defined?(:fixture_path=)
|
14
|
+
ActiveSupport::TestCase.fixture_path = File.expand_path("../fixtures", __FILE__)
|
15
|
+
end
|
Binary file
|
@@ -0,0 +1,39 @@
|
|
1
|
+
/*** Pygments Style ****/
|
2
|
+
<%= Pygments.css(style: "colorful") %>
|
3
|
+
|
4
|
+
/*** CODE BLOCKS ***/
|
5
|
+
|
6
|
+
.code_block {
|
7
|
+
margin: 20px 0;
|
8
|
+
border: solid 1px #B6B6B6;
|
9
|
+
}
|
10
|
+
|
11
|
+
.code_header {
|
12
|
+
position: relative;
|
13
|
+
background-color: #E0E0E0;
|
14
|
+
font-size: 12px;
|
15
|
+
padding: 4px 7px;
|
16
|
+
}
|
17
|
+
|
18
|
+
.code_header .clippy {
|
19
|
+
position: absolute;
|
20
|
+
top: 4px;
|
21
|
+
right: 7px;
|
22
|
+
}
|
23
|
+
|
24
|
+
.clippy_label {
|
25
|
+
position: absolute;
|
26
|
+
right: 20px;
|
27
|
+
top: 1px;
|
28
|
+
text-align: right;
|
29
|
+
width: 200px;
|
30
|
+
font-size: 10px;
|
31
|
+
color: #555;
|
32
|
+
}
|
33
|
+
|
34
|
+
.highlight {
|
35
|
+
padding: 5px;
|
36
|
+
pre {
|
37
|
+
margin: 0px;
|
38
|
+
}
|
39
|
+
}
|
metadata
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: orbital_fields
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.14
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Kaz Walker
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-05-16 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rails
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 3.2.3
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 3.2.3
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: all-your-base
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 0.3.0
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 0.3.0
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: redcarpet
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 2.1.0
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 2.1.0
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: pygments.rb
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 0.2.12
|
70
|
+
type: :runtime
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 0.2.12
|
78
|
+
description: The (possibly) reusable partrs of Orbital.
|
79
|
+
email:
|
80
|
+
- kaz.walker@slipline.ca
|
81
|
+
executables: []
|
82
|
+
extensions: []
|
83
|
+
extra_rdoc_files: []
|
84
|
+
files:
|
85
|
+
- .gitignore
|
86
|
+
- Gemfile
|
87
|
+
- Gemfile.lock
|
88
|
+
- README.md
|
89
|
+
- Rakefile
|
90
|
+
- lib/orbital_fields.rb
|
91
|
+
- lib/orbital_fields/attribute_security.rb
|
92
|
+
- lib/orbital_fields/engine.rb
|
93
|
+
- lib/orbital_fields/kaminari_proxy.rb
|
94
|
+
- lib/orbital_fields/markdown.rb
|
95
|
+
- lib/orbital_fields/short_id.rb
|
96
|
+
- lib/orbital_fields/tokenize.rb
|
97
|
+
- lib/orbital_fields/url_lookup.rb
|
98
|
+
- lib/orbital_fields/version.rb
|
99
|
+
- orbital-fields.gemspec
|
100
|
+
- test/orbital-fields_test.rb
|
101
|
+
- test/test_helper.rb
|
102
|
+
- vendor/assets/flash/orbital_fields/clippy.swf
|
103
|
+
- vendor/assets/stylesheets/orbital_fields/pygments.css.erb
|
104
|
+
homepage: http://www.orbitalsoft.org
|
105
|
+
licenses: []
|
106
|
+
post_install_message:
|
107
|
+
rdoc_options: []
|
108
|
+
require_paths:
|
109
|
+
- lib
|
110
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
111
|
+
none: false
|
112
|
+
requirements:
|
113
|
+
- - ! '>='
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: '0'
|
116
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
117
|
+
none: false
|
118
|
+
requirements:
|
119
|
+
- - ! '>='
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
version: '0'
|
122
|
+
requirements: []
|
123
|
+
rubyforge_project:
|
124
|
+
rubygems_version: 1.8.21
|
125
|
+
signing_key:
|
126
|
+
specification_version: 3
|
127
|
+
summary: ''
|
128
|
+
test_files:
|
129
|
+
- test/orbital-fields_test.rb
|
130
|
+
- test/test_helper.rb
|