mongoid-sleeping_king_studios 0.5.0 → 0.6.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -0
- data/LICENSE +1 -1
- data/README.md +21 -3
- data/lib/mongoid/sleeping_king_studios.rb +11 -1
- data/lib/mongoid/sleeping_king_studios/concern.rb +69 -0
- data/lib/mongoid/sleeping_king_studios/concern/metadata.rb +61 -0
- data/lib/mongoid/sleeping_king_studios/ext/mongoid/document.rb +15 -0
- data/lib/mongoid/sleeping_king_studios/has_tree.rb +119 -68
- data/lib/mongoid/sleeping_king_studios/has_tree/cache_ancestry.rb +177 -113
- data/lib/mongoid/sleeping_king_studios/has_tree/cache_ancestry/metadata.rb +82 -0
- data/lib/mongoid/sleeping_king_studios/has_tree/children/metadata.rb +40 -0
- data/lib/mongoid/sleeping_king_studios/has_tree/errors.rb +6 -5
- data/lib/mongoid/sleeping_king_studios/has_tree/metadata.rb +64 -0
- data/lib/mongoid/sleeping_king_studios/has_tree/parent/metadata.rb +40 -0
- data/lib/mongoid/sleeping_king_studios/sluggable.rb +125 -46
- data/lib/mongoid/sleeping_king_studios/sluggable/metadata.rb +42 -0
- data/lib/mongoid/sleeping_king_studios/version.rb +2 -1
- metadata +32 -37
@@ -0,0 +1,64 @@
|
|
1
|
+
# lib/mongoid/sleeping_king_studios/has_tree/metadata.rb
|
2
|
+
|
3
|
+
require 'mongoid/sleeping_king_studios/concern/metadata'
|
4
|
+
require 'mongoid/sleeping_king_studios/has_tree/cache_ancestry/metadata'
|
5
|
+
require 'mongoid/sleeping_king_studios/has_tree/children/metadata'
|
6
|
+
require 'mongoid/sleeping_king_studios/has_tree/parent/metadata'
|
7
|
+
|
8
|
+
module Mongoid::SleepingKingStudios
|
9
|
+
module HasTree
|
10
|
+
# Stores information about a HasTree concern.
|
11
|
+
class Metadata < Mongoid::SleepingKingStudios::Concern::Metadata
|
12
|
+
# @param [Symbol, String] name The name of the concern or relation.
|
13
|
+
# @param [Hash] properties The properties of the concern or relation.
|
14
|
+
def initialize name, properties = {}
|
15
|
+
super
|
16
|
+
|
17
|
+
self[:parent] = characterize :parent, properties.fetch(:parent, {}), HasTree::Parent::Metadata
|
18
|
+
self[:children] = characterize :children, properties.fetch(:children, {}), HasTree::Children::Metadata
|
19
|
+
|
20
|
+
if properties.fetch(:cache_ancestry, false)
|
21
|
+
properties[:cache_ancestry] = {} unless Hash === properties[:cache_ancestry]
|
22
|
+
properties[:cache_ancestry][:children_name] = children.relation_name
|
23
|
+
properties[:cache_ancestry][:parent_name] = parent.relation_name
|
24
|
+
|
25
|
+
self[:cache_ancestry] = characterize :cache_ancestry, properties[:cache_ancestry], HasTree::CacheAncestry::Metadata
|
26
|
+
end # unless
|
27
|
+
end # constructor
|
28
|
+
|
29
|
+
# The metadata associated with the :cache_ancestry option.
|
30
|
+
#
|
31
|
+
# @return [Metadata] The :cache_ancestry metadata.
|
32
|
+
def cache_ancestry
|
33
|
+
self[:cache_ancestry]
|
34
|
+
end # method cache_ancestry
|
35
|
+
|
36
|
+
# @return [Boolean] True if the :cache_ancestry option is selected;
|
37
|
+
# otherwise false.
|
38
|
+
def cache_ancestry?
|
39
|
+
!!self[:cache_ancestry]
|
40
|
+
end # method cache_ancestry?
|
41
|
+
|
42
|
+
# The metadata associated with the #children relation.
|
43
|
+
#
|
44
|
+
# @return [Metadata] The children metadata.
|
45
|
+
def children
|
46
|
+
self[:children]
|
47
|
+
end # method children
|
48
|
+
|
49
|
+
# The foreign key for the parent relation.
|
50
|
+
#
|
51
|
+
# @return [Symbol] The foreign key.
|
52
|
+
def foreign_key
|
53
|
+
self[:foreign_key] || :"#{parent.relation_name}_id"
|
54
|
+
end # method foreign_key
|
55
|
+
|
56
|
+
# The metadata associated with the #parent relation.
|
57
|
+
#
|
58
|
+
# @return [Metadata] The parent metadata.
|
59
|
+
def parent
|
60
|
+
self[:parent]
|
61
|
+
end # method parent
|
62
|
+
end # class
|
63
|
+
end # module
|
64
|
+
end # module
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# lib/mongoid/sleeping_king_studios/has_tree/parent/metadata.rb
|
2
|
+
|
3
|
+
require 'mongoid/sleeping_king_studios/concern/metadata'
|
4
|
+
|
5
|
+
module Mongoid::SleepingKingStudios
|
6
|
+
module HasTree
|
7
|
+
module Parent
|
8
|
+
# Stores information about a HasTree concern's parent relation.
|
9
|
+
class Metadata < Mongoid::SleepingKingStudios::Concern::Metadata
|
10
|
+
# The name of the tree's children relation. If no relation name is set,
|
11
|
+
# defaults to :children.
|
12
|
+
#
|
13
|
+
# @return [Symbol] The relation name.
|
14
|
+
def inverse_of
|
15
|
+
fetch(:inverse_of, :children)
|
16
|
+
end # method inverse_of
|
17
|
+
|
18
|
+
# @return [Boolean] True if a custom inverse relation name is set;
|
19
|
+
# otherwise false.
|
20
|
+
def inverse_of?
|
21
|
+
!!self[:inverse_of]
|
22
|
+
end # method inverse_of?
|
23
|
+
|
24
|
+
# The name of the tree's parent relation. If no relation name is set,
|
25
|
+
# defaults to :parent.
|
26
|
+
#
|
27
|
+
# @return [Symbol] The relation name.
|
28
|
+
def relation_name
|
29
|
+
fetch(:relation_name, :parent)
|
30
|
+
end # method relation_name
|
31
|
+
|
32
|
+
# @return [Boolean] True if a custom relation name is set; otherwise
|
33
|
+
# false.
|
34
|
+
def relation_name?
|
35
|
+
!!self[:relation_name]
|
36
|
+
end # method relation_name?
|
37
|
+
end # class
|
38
|
+
end # module
|
39
|
+
end # module
|
40
|
+
end # module
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# lib/mongoid/sleeping_king_studios/sluggable.rb
|
2
2
|
|
3
|
-
require 'mongoid/sleeping_king_studios'
|
3
|
+
require 'mongoid/sleeping_king_studios/concern'
|
4
|
+
require 'mongoid/sleeping_king_studios/sluggable/metadata'
|
4
5
|
|
5
6
|
module Mongoid::SleepingKingStudios
|
6
7
|
# Adds a :slug field that stores a short, url-friendly reference string,
|
@@ -24,69 +25,147 @@ module Mongoid::SleepingKingStudios
|
|
24
25
|
# @since 0.1.0
|
25
26
|
module Sluggable
|
26
27
|
extend ActiveSupport::Concern
|
28
|
+
extend Mongoid::SleepingKingStudios::Concern
|
29
|
+
|
30
|
+
# @api private
|
31
|
+
#
|
32
|
+
# Sets up the sluggable relation, creating fields, accessors and
|
33
|
+
# validations.
|
34
|
+
#
|
35
|
+
# @param [Class] base The base class into which the concern is mixed in.
|
36
|
+
# @param [String, Symbol] attribute The base field used to determine
|
37
|
+
# the value of the slug. When this field is changed via its writer
|
38
|
+
# method, the slug will be updated.
|
39
|
+
# @param [Hash] options The options for the relation.
|
40
|
+
#
|
41
|
+
# @since 0.6.0
|
42
|
+
def self.apply base, attribute, options
|
43
|
+
name = :sluggable
|
44
|
+
validate_options name, options
|
45
|
+
meta = characterize name, options, Metadata
|
46
|
+
meta[:attribute] = attribute
|
47
|
+
|
48
|
+
relate base, name, meta
|
49
|
+
|
50
|
+
define_fields base, meta
|
51
|
+
define_accessors base, meta
|
52
|
+
define_validations base, meta
|
53
|
+
end # module method apply
|
54
|
+
|
55
|
+
# @api private
|
56
|
+
#
|
57
|
+
# Redefines the writer for the base attribute to overwrite the value of the
|
58
|
+
# slug field unless the slug is locked. If the Lockable option is selected,
|
59
|
+
# redefines the writer for the slug field to lock the slug when set
|
60
|
+
# manually; otherwise, makes the writer for the slug field private.
|
61
|
+
#
|
62
|
+
# @param [Class] base The base class into which the concern is mixed in.
|
63
|
+
# @param [Metadata] metadata The metadata for the relation.
|
64
|
+
#
|
65
|
+
# @since 0.6.0
|
66
|
+
def self.define_accessors base, metadata
|
67
|
+
base.re_define_method :"#{metadata.attribute}=" do |value|
|
68
|
+
self[metadata.attribute.to_s] = value
|
69
|
+
unless metadata.lockable? && self['slug_lock']
|
70
|
+
self['slug'] = metadata.value_to_slug value
|
71
|
+
end # unless
|
72
|
+
end # method
|
73
|
+
|
74
|
+
if metadata.lockable?
|
75
|
+
base.re_define_method :slug= do |value|
|
76
|
+
self['slug'] = value
|
77
|
+
self['slug_lock'] = true
|
78
|
+
end # method
|
79
|
+
else
|
80
|
+
base.send :private, :slug=
|
81
|
+
end # if
|
82
|
+
end # module method define_accessors
|
83
|
+
|
84
|
+
# @api private
|
85
|
+
#
|
86
|
+
# Creates a slug field of type String on the base class. If the Lockable
|
87
|
+
# option is selected, also creates a slug_lock field of type Boolean.
|
88
|
+
#
|
89
|
+
# @param [Class] base The base class into which the concern is mixed in.
|
90
|
+
# @param [Metadata] metadata The metadata for the relation.
|
91
|
+
#
|
92
|
+
# @since 0.6.0
|
93
|
+
def self.define_fields base, metadata
|
94
|
+
base.send :field, :slug, :type => String
|
95
|
+
|
96
|
+
if metadata.lockable?
|
97
|
+
base.send :field, :slug_lock, :type => Boolean, :default => false
|
98
|
+
end # if
|
99
|
+
end # module method define_fields
|
100
|
+
|
101
|
+
# @api private
|
102
|
+
#
|
103
|
+
# Sets a validation on the slug field that validates the presence of the
|
104
|
+
# slug, and that the value is of a valid format (lower-case characters a-z,
|
105
|
+
# digits 0-9, and hyphens "-").
|
106
|
+
#
|
107
|
+
# @param [Class] base The base class into which the concern is mixed in.
|
108
|
+
# @param [Metadata] metadata The metadata for the relation.
|
109
|
+
#
|
110
|
+
# @since 0.6.0
|
111
|
+
def self.define_validations base, metadata
|
112
|
+
base.validates :slug,
|
113
|
+
:presence => true,
|
114
|
+
:format => {
|
115
|
+
:with => /\A[a-z0-9\-]+\z/,
|
116
|
+
:message => 'must be lower-case characters a-z, digits 0-9, and hyphens "-"'
|
117
|
+
} # end format
|
118
|
+
end # module method define_validations
|
119
|
+
|
120
|
+
# Returns a list of options that are valid for this concern.
|
121
|
+
#
|
122
|
+
# @return [Array<Symbol>] The list of valid options.
|
123
|
+
#
|
124
|
+
# @since 0.6.0
|
125
|
+
def self.valid_options
|
126
|
+
super + %i(
|
127
|
+
lockable
|
128
|
+
) # end array
|
129
|
+
end # module method valid options
|
27
130
|
|
28
131
|
# @!attribute [r] slug
|
29
132
|
# A url-friendly short string version of the specified base attribute.
|
30
|
-
#
|
133
|
+
#
|
134
|
+
# (Lockable) The slug value can be set directly using the #slug= method.
|
135
|
+
# This will set the :slug_lock flag, preventing the slug from being
|
136
|
+
# updated by a change to the base field until :slug_lock is cleared.
|
137
|
+
#
|
138
|
+
# @return [String] The value of the stored slug.
|
139
|
+
|
140
|
+
# @!attribute [rw] slug_lock
|
141
|
+
# (Lockable) A flag that indicates whether or not the slug is locked.
|
142
|
+
# If the flag is set, updating the base field will not change the value
|
143
|
+
# of the slug.
|
31
144
|
#
|
32
|
-
# @return [
|
145
|
+
# @return [Boolean] True if the slug is locked; otherwise false.
|
33
146
|
|
34
147
|
# Class methods added to the base class via #extend.
|
35
148
|
module ClassMethods
|
36
|
-
# Returns the options passed into ::slugify, as well as an additional
|
37
|
-
# :attribute value for the attribute passed into ::slugify.
|
38
|
-
attr_reader :sluggable_options
|
39
|
-
|
40
149
|
# @overload slugify attribute, options = {}
|
41
150
|
# Creates the :slug field and sets up the callback and validations.
|
42
151
|
#
|
43
|
-
# @param [String, Symbol] attribute
|
152
|
+
# @param [String, Symbol] attribute The base field used to determine
|
153
|
+
# the value of the slug. When this field is changed via its writer
|
154
|
+
# method, the slug will be updated.
|
155
|
+
# @param [Hash] options The options for the relation.
|
44
156
|
# @option options [Boolean] :lockable
|
45
157
|
# The :lockable option allows the manual setting of the :slug field.
|
46
158
|
# To do so, it adds an additional :slug_lock field, which defaults to
|
47
159
|
# false but is set to true whenever #slug= is called. If the slug is
|
48
160
|
# locked, its value is not updated to track the base attribute. To
|
49
161
|
# resume tracking the base attribute, set :slug_lock to false.
|
162
|
+
#
|
163
|
+
# @raise [Mongoid::Errors::InvalidOptions] If any of the provided
|
164
|
+
# options are invalid.
|
50
165
|
def slugify attribute, **options
|
51
|
-
|
52
|
-
|
53
|
-
field :slug, :type => String
|
54
|
-
|
55
|
-
validates :slug,
|
56
|
-
:presence => true,
|
57
|
-
:format => {
|
58
|
-
:with => /\A[a-z0-9\-]+\z/,
|
59
|
-
:message => 'must be lower-case characters a-z, digits 0-9, and hyphens "-"'
|
60
|
-
} # end format
|
61
|
-
|
62
|
-
before_validation do
|
63
|
-
return if self.class.sluggable_options[:lockable] && self.slug_lock
|
64
|
-
self[:slug] = to_slug
|
65
|
-
end # before validation callback
|
66
|
-
|
67
|
-
# Lockable
|
68
|
-
if options.fetch(:lockable, false)
|
69
|
-
field :slug_lock, :type => Boolean, :default => false
|
70
|
-
|
71
|
-
self.class_eval do
|
72
|
-
def slug= value
|
73
|
-
super
|
74
|
-
self.slug_lock = true
|
75
|
-
end # method slug=
|
76
|
-
end # class eval
|
77
|
-
else
|
78
|
-
private :slug=
|
79
|
-
end # if
|
166
|
+
concern = Mongoid::SleepingKingStudios::Sluggable
|
167
|
+
concern.apply self, attribute, options
|
80
168
|
end # class method slugify
|
81
169
|
end # module
|
82
|
-
|
83
|
-
# Processes the specified base attribute and returns a valid slug value. By
|
84
|
-
# default, calls String#parameterize.
|
85
|
-
#
|
86
|
-
# @return [String] the processed value
|
87
|
-
def to_slug
|
88
|
-
raw = (self.send self.class.sluggable_options[:attribute]) || ""
|
89
|
-
raw.parameterize
|
90
|
-
end # method to_slug
|
91
170
|
end # module
|
92
171
|
end # module
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# lib/mongoid/sleeping_king_studios/sluggable/metadata.rb
|
2
|
+
|
3
|
+
require 'mongoid/sleeping_king_studios/concern/metadata'
|
4
|
+
|
5
|
+
module Mongoid::SleepingKingStudios
|
6
|
+
module Sluggable
|
7
|
+
# Stores information about a Sluggable concern.
|
8
|
+
class Metadata < Mongoid::SleepingKingStudios::Concern::Metadata
|
9
|
+
# The base attribute used to determine the slug value.
|
10
|
+
#
|
11
|
+
# @return [Symbol] The attribute name.
|
12
|
+
def attribute
|
13
|
+
self[:attribute].to_s.intern
|
14
|
+
end # method attribute
|
15
|
+
|
16
|
+
# @return [Boolean] True if the attribute is defined; otherwise false.
|
17
|
+
def attribute?
|
18
|
+
!!self[:attribute]
|
19
|
+
end # method attribute?
|
20
|
+
|
21
|
+
# If true, the slug can be "locked" by setting the slug value directly or
|
22
|
+
# by setting the value of the :slug_lock field to true. A locked slug is
|
23
|
+
# not overwritten when the base field is updated.
|
24
|
+
#
|
25
|
+
# @return [Boolean] True if the slug is lockable; otherwise false.
|
26
|
+
def lockable?
|
27
|
+
!!self[:lockable]
|
28
|
+
end # method lockable?
|
29
|
+
|
30
|
+
# Converts the given value to a valid slug string. Refactoring this into
|
31
|
+
# the metadata will permit customization of the value -> slug mapping in
|
32
|
+
# the future.
|
33
|
+
#
|
34
|
+
# @param [Object] value The value to convert into a slug.
|
35
|
+
#
|
36
|
+
# @return [String] The converted value.
|
37
|
+
def value_to_slug value
|
38
|
+
value.to_s.parameterize
|
39
|
+
end # method value_to_slug
|
40
|
+
end # class Metadata
|
41
|
+
end # module
|
42
|
+
end # module
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongoid-sleeping_king_studios
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rob "Merlin" Smith
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - ~>
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: 1.9.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: sleeping_king_studios-ext
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.1'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.1'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: rspec
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -56,16 +70,16 @@ dependencies:
|
|
56
70
|
name: rspec-sleeping_king_studios
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
58
72
|
requirements:
|
59
|
-
- -
|
73
|
+
- - ~>
|
60
74
|
- !ruby/object:Gem::Version
|
61
|
-
version: 1.0
|
75
|
+
version: '1.0'
|
62
76
|
type: :development
|
63
77
|
prerelease: false
|
64
78
|
version_requirements: !ruby/object:Gem::Requirement
|
65
79
|
requirements:
|
66
|
-
- -
|
80
|
+
- - ~>
|
67
81
|
- !ruby/object:Gem::Version
|
68
|
-
version: 1.0
|
82
|
+
version: '1.0'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: factory_girl
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -98,44 +112,16 @@ dependencies:
|
|
98
112
|
name: fuubar
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
100
114
|
requirements:
|
101
|
-
- -
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
version: '0'
|
104
|
-
type: :development
|
105
|
-
prerelease: false
|
106
|
-
version_requirements: !ruby/object:Gem::Requirement
|
107
|
-
requirements:
|
108
|
-
- - '>='
|
109
|
-
- !ruby/object:Gem::Version
|
110
|
-
version: '0'
|
111
|
-
- !ruby/object:Gem::Dependency
|
112
|
-
name: pry
|
113
|
-
requirement: !ruby/object:Gem::Requirement
|
114
|
-
requirements:
|
115
|
-
- - '>='
|
116
|
-
- !ruby/object:Gem::Version
|
117
|
-
version: '0'
|
118
|
-
type: :development
|
119
|
-
prerelease: false
|
120
|
-
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
requirements:
|
122
|
-
- - '>='
|
123
|
-
- !ruby/object:Gem::Version
|
124
|
-
version: '0'
|
125
|
-
- !ruby/object:Gem::Dependency
|
126
|
-
name: yard
|
127
|
-
requirement: !ruby/object:Gem::Requirement
|
128
|
-
requirements:
|
129
|
-
- - '>='
|
115
|
+
- - ~>
|
130
116
|
- !ruby/object:Gem::Version
|
131
|
-
version: '
|
117
|
+
version: '1.2'
|
132
118
|
type: :development
|
133
119
|
prerelease: false
|
134
120
|
version_requirements: !ruby/object:Gem::Requirement
|
135
121
|
requirements:
|
136
|
-
- -
|
122
|
+
- - ~>
|
137
123
|
- !ruby/object:Gem::Version
|
138
|
-
version: '
|
124
|
+
version: '1.2'
|
139
125
|
description: |2
|
140
126
|
A collection of concerns and extensions to add functionality to Mongoid
|
141
127
|
documents and collections. The features can be included individually or by
|
@@ -146,14 +132,23 @@ executables: []
|
|
146
132
|
extensions: []
|
147
133
|
extra_rdoc_files: []
|
148
134
|
files:
|
135
|
+
- lib/mongoid/sleeping_king_studios/concern/metadata.rb
|
136
|
+
- lib/mongoid/sleeping_king_studios/concern.rb
|
149
137
|
- lib/mongoid/sleeping_king_studios/error.rb
|
138
|
+
- lib/mongoid/sleeping_king_studios/ext/mongoid/document.rb
|
139
|
+
- lib/mongoid/sleeping_king_studios/has_tree/cache_ancestry/metadata.rb
|
150
140
|
- lib/mongoid/sleeping_king_studios/has_tree/cache_ancestry.rb
|
141
|
+
- lib/mongoid/sleeping_king_studios/has_tree/children/metadata.rb
|
151
142
|
- lib/mongoid/sleeping_king_studios/has_tree/errors.rb
|
143
|
+
- lib/mongoid/sleeping_king_studios/has_tree/metadata.rb
|
144
|
+
- lib/mongoid/sleeping_king_studios/has_tree/parent/metadata.rb
|
152
145
|
- lib/mongoid/sleeping_king_studios/has_tree.rb
|
146
|
+
- lib/mongoid/sleeping_king_studios/sluggable/metadata.rb
|
153
147
|
- lib/mongoid/sleeping_king_studios/sluggable.rb
|
154
148
|
- lib/mongoid/sleeping_king_studios/version.rb
|
155
149
|
- lib/mongoid/sleeping_king_studios.rb
|
156
150
|
- LICENSE
|
151
|
+
- CHANGELOG.md
|
157
152
|
- README.md
|
158
153
|
homepage: http://sleepingkingstudios.com
|
159
154
|
licenses:
|