easy_mongoid_tag 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +18 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +89 -0
- data/Guardfile +22 -0
- data/LICENSE +191 -0
- data/README.textile +34 -0
- data/easy_mongoid_tag.gemspec +29 -0
- data/lib/easy_mongoid_tag.rb +5 -0
- data/lib/easy_mongoid_tag/tag.rb +151 -0
- data/lib/easy_mongoid_tag/version.rb +4 -0
- data/lib/mongoid_extensions/extension_field.rb +14 -0
- data/prototype/book.rb +119 -0
- data/prototype/mongodb.yml +6 -0
- data/spec/function_spec.rb +43 -0
- data/spec/mongodb.yml +6 -0
- data/spec/spec_helper.rb +54 -0
- data/spec/tag_spec.rb +98 -0
- data/test/read_book/.gitignore +15 -0
- data/test/read_book/Gemfile +39 -0
- data/test/read_book/Gemfile.lock +119 -0
- data/test/read_book/README.rdoc +261 -0
- data/test/read_book/Rakefile +7 -0
- data/test/read_book/app/assets/images/rails.png +0 -0
- data/test/read_book/app/assets/javascripts/application.js +15 -0
- data/test/read_book/app/assets/stylesheets/application.css +13 -0
- data/test/read_book/app/controllers/application_controller.rb +3 -0
- data/test/read_book/app/helpers/application_helper.rb +2 -0
- data/test/read_book/app/mailers/.gitkeep +0 -0
- data/test/read_book/app/models/.gitkeep +0 -0
- data/test/read_book/app/models/book.rb +11 -0
- data/test/read_book/app/views/layouts/application.html.erb +14 -0
- data/test/read_book/config.ru +4 -0
- data/test/read_book/config/application.rb +68 -0
- data/test/read_book/config/boot.rb +6 -0
- data/test/read_book/config/environment.rb +5 -0
- data/test/read_book/config/environments/development.rb +31 -0
- data/test/read_book/config/environments/production.rb +64 -0
- data/test/read_book/config/environments/test.rb +35 -0
- data/test/read_book/config/initializers/backtrace_silencers.rb +7 -0
- data/test/read_book/config/initializers/inflections.rb +15 -0
- data/test/read_book/config/initializers/mime_types.rb +5 -0
- data/test/read_book/config/initializers/secret_token.rb +7 -0
- data/test/read_book/config/initializers/session_store.rb +8 -0
- data/test/read_book/config/initializers/wrap_parameters.rb +10 -0
- data/test/read_book/config/locales/en.yml +5 -0
- data/test/read_book/config/mongoid.yml +80 -0
- data/test/read_book/config/routes.rb +58 -0
- data/test/read_book/db/seeds.rb +7 -0
- data/test/read_book/lib/assets/.gitkeep +0 -0
- data/test/read_book/lib/tasks/.gitkeep +0 -0
- data/test/read_book/log/.gitkeep +0 -0
- data/test/read_book/public/404.html +26 -0
- data/test/read_book/public/422.html +26 -0
- data/test/read_book/public/500.html +25 -0
- data/test/read_book/public/favicon.ico +0 -0
- data/test/read_book/public/index.html +241 -0
- data/test/read_book/public/robots.txt +5 -0
- data/test/read_book/script/rails +6 -0
- data/test/read_book/test/fixtures/.gitkeep +0 -0
- data/test/read_book/test/fixtures/books.yml +11 -0
- data/test/read_book/test/functional/.gitkeep +0 -0
- data/test/read_book/test/integration/.gitkeep +0 -0
- data/test/read_book/test/performance/browsing_test.rb +12 -0
- data/test/read_book/test/test_helper.rb +7 -0
- data/test/read_book/test/unit/.gitkeep +0 -0
- data/test/read_book/test/unit/book_test.rb +7 -0
- data/test/read_book/vendor/assets/javascripts/.gitkeep +0 -0
- data/test/read_book/vendor/assets/stylesheets/.gitkeep +0 -0
- data/test/read_book/vendor/plugins/.gitkeep +0 -0
- metadata +282 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
easy_mongoid_tag (0.0.1)
|
5
|
+
mongoid (~> 3.1.0)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: http://ruby.taobao.org/
|
9
|
+
specs:
|
10
|
+
activemodel (3.2.14)
|
11
|
+
activesupport (= 3.2.14)
|
12
|
+
builder (~> 3.0.0)
|
13
|
+
activesupport (3.2.14)
|
14
|
+
i18n (~> 0.6, >= 0.6.4)
|
15
|
+
multi_json (~> 1.0)
|
16
|
+
builder (3.0.4)
|
17
|
+
childprocess (0.3.9)
|
18
|
+
ffi (~> 1.0, >= 1.0.11)
|
19
|
+
coderay (1.0.9)
|
20
|
+
diff-lcs (1.2.4)
|
21
|
+
ffi (1.9.0)
|
22
|
+
formatador (0.2.4)
|
23
|
+
guard (1.8.2)
|
24
|
+
formatador (>= 0.2.4)
|
25
|
+
listen (>= 1.0.0)
|
26
|
+
lumberjack (>= 1.0.2)
|
27
|
+
pry (>= 0.9.10)
|
28
|
+
thor (>= 0.14.6)
|
29
|
+
guard-rspec (3.0.2)
|
30
|
+
guard (>= 1.8)
|
31
|
+
rspec (~> 2.13)
|
32
|
+
guard-spork (1.5.1)
|
33
|
+
childprocess (>= 0.2.3)
|
34
|
+
guard (>= 1.1)
|
35
|
+
spork (>= 0.8.4)
|
36
|
+
i18n (0.6.5)
|
37
|
+
listen (1.3.0)
|
38
|
+
rb-fsevent (>= 0.9.3)
|
39
|
+
rb-inotify (>= 0.9)
|
40
|
+
rb-kqueue (>= 0.2)
|
41
|
+
lumberjack (1.0.4)
|
42
|
+
method_source (0.8.2)
|
43
|
+
mongoid (3.1.4)
|
44
|
+
activemodel (~> 3.2)
|
45
|
+
moped (~> 1.4)
|
46
|
+
origin (~> 1.0)
|
47
|
+
tzinfo (~> 0.3.22)
|
48
|
+
mongoid-rspec (1.9.0)
|
49
|
+
mongoid (>= 3.0.1)
|
50
|
+
rake
|
51
|
+
rspec (>= 2.14)
|
52
|
+
moped (1.5.1)
|
53
|
+
multi_json (1.7.9)
|
54
|
+
origin (1.1.0)
|
55
|
+
pry (0.9.12.2)
|
56
|
+
coderay (~> 1.0.5)
|
57
|
+
method_source (~> 0.8)
|
58
|
+
slop (~> 3.4)
|
59
|
+
rake (10.1.0)
|
60
|
+
rb-fsevent (0.9.3)
|
61
|
+
rb-inotify (0.9.1)
|
62
|
+
ffi (>= 0.5.0)
|
63
|
+
rb-kqueue (0.2.0)
|
64
|
+
ffi (>= 0.5.0)
|
65
|
+
rspec (2.14.1)
|
66
|
+
rspec-core (~> 2.14.0)
|
67
|
+
rspec-expectations (~> 2.14.0)
|
68
|
+
rspec-mocks (~> 2.14.0)
|
69
|
+
rspec-core (2.14.5)
|
70
|
+
rspec-expectations (2.14.2)
|
71
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
72
|
+
rspec-mocks (2.14.3)
|
73
|
+
slop (3.4.6)
|
74
|
+
spork (0.9.2)
|
75
|
+
terminal-notifier-guard (1.5.3)
|
76
|
+
thor (0.18.1)
|
77
|
+
tzinfo (0.3.37)
|
78
|
+
|
79
|
+
PLATFORMS
|
80
|
+
ruby
|
81
|
+
|
82
|
+
DEPENDENCIES
|
83
|
+
easy_mongoid_tag!
|
84
|
+
guard (~> 1.8.0)
|
85
|
+
guard-rspec (~> 3.0.0)
|
86
|
+
guard-spork (~> 1.5.1)
|
87
|
+
mongoid-rspec (~> 1.9.0)
|
88
|
+
rspec (~> 2.14.1)
|
89
|
+
terminal-notifier-guard (~> 1.5.3)
|
data/Guardfile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
guard :rspec, :cli => "--color -f nested" do
|
5
|
+
watch(%r{^spec/.+_spec\.rb$})
|
6
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
7
|
+
watch('spec/spec_helper.rb') { "spec" }
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
guard 'spork', :cucumber_env => { 'RAILS_ENV' => 'test' }, :rspec_env => { 'RAILS_ENV' => 'test' } do
|
12
|
+
watch('config/application.rb')
|
13
|
+
watch('config/environment.rb')
|
14
|
+
watch('config/environments/test.rb')
|
15
|
+
watch(%r{^config/initializers/.+\.rb$})
|
16
|
+
watch('Gemfile.lock')
|
17
|
+
watch('spec/spec_helper.rb') { :rspec }
|
18
|
+
watch('test/test_helper.rb') { :test_unit }
|
19
|
+
watch(%r{features/support/}) { :cucumber }
|
20
|
+
end
|
21
|
+
|
22
|
+
notification :terminal_notifier
|
data/LICENSE
ADDED
@@ -0,0 +1,191 @@
|
|
1
|
+
Apache License
|
2
|
+
Version 2.0, January 2004
|
3
|
+
http://www.apache.org/licenses/
|
4
|
+
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
6
|
+
|
7
|
+
1. Definitions.
|
8
|
+
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction, and
|
10
|
+
distribution as defined by Sections 1 through 9 of this document.
|
11
|
+
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by the copyright
|
13
|
+
owner that is granting the License.
|
14
|
+
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all other entities
|
16
|
+
that control, are controlled by, or are under common control with that entity.
|
17
|
+
For the purposes of this definition, "control" means (i) the power, direct or
|
18
|
+
indirect, to cause the direction or management of such entity, whether by
|
19
|
+
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
20
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
21
|
+
|
22
|
+
"You" (or "Your") shall mean an individual or Legal Entity exercising
|
23
|
+
permissions granted by this License.
|
24
|
+
|
25
|
+
"Source" form shall mean the preferred form for making modifications, including
|
26
|
+
but not limited to software source code, documentation source, and configuration
|
27
|
+
files.
|
28
|
+
|
29
|
+
"Object" form shall mean any form resulting from mechanical transformation or
|
30
|
+
translation of a Source form, including but not limited to compiled object code,
|
31
|
+
generated documentation, and conversions to other media types.
|
32
|
+
|
33
|
+
"Work" shall mean the work of authorship, whether in Source or Object form, made
|
34
|
+
available under the License, as indicated by a copyright notice that is included
|
35
|
+
in or attached to the work (an example is provided in the Appendix below).
|
36
|
+
|
37
|
+
"Derivative Works" shall mean any work, whether in Source or Object form, that
|
38
|
+
is based on (or derived from) the Work and for which the editorial revisions,
|
39
|
+
annotations, elaborations, or other modifications represent, as a whole, an
|
40
|
+
original work of authorship. For the purposes of this License, Derivative Works
|
41
|
+
shall not include works that remain separable from, or merely link (or bind by
|
42
|
+
name) to the interfaces of, the Work and Derivative Works thereof.
|
43
|
+
|
44
|
+
"Contribution" shall mean any work of authorship, including the original version
|
45
|
+
of the Work and any modifications or additions to that Work or Derivative Works
|
46
|
+
thereof, that is intentionally submitted to Licensor for inclusion in the Work
|
47
|
+
by the copyright owner or by an individual or Legal Entity authorized to submit
|
48
|
+
on behalf of the copyright owner. For the purposes of this definition,
|
49
|
+
"submitted" means any form of electronic, verbal, or written communication sent
|
50
|
+
to the Licensor or its representatives, including but not limited to
|
51
|
+
communication on electronic mailing lists, source code control systems, and
|
52
|
+
issue tracking systems that are managed by, or on behalf of, the Licensor for
|
53
|
+
the purpose of discussing and improving the Work, but excluding communication
|
54
|
+
that is conspicuously marked or otherwise designated in writing by the copyright
|
55
|
+
owner as "Not a Contribution."
|
56
|
+
|
57
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
|
58
|
+
of whom a Contribution has been received by Licensor and subsequently
|
59
|
+
incorporated within the Work.
|
60
|
+
|
61
|
+
2. Grant of Copyright License.
|
62
|
+
|
63
|
+
Subject to the terms and conditions of this License, each Contributor hereby
|
64
|
+
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
|
65
|
+
irrevocable copyright license to reproduce, prepare Derivative Works of,
|
66
|
+
publicly display, publicly perform, sublicense, and distribute the Work and such
|
67
|
+
Derivative Works in Source or Object form.
|
68
|
+
|
69
|
+
3. Grant of Patent License.
|
70
|
+
|
71
|
+
Subject to the terms and conditions of this License, each Contributor hereby
|
72
|
+
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
|
73
|
+
irrevocable (except as stated in this section) patent license to make, have
|
74
|
+
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
|
75
|
+
such license applies only to those patent claims licensable by such Contributor
|
76
|
+
that are necessarily infringed by their Contribution(s) alone or by combination
|
77
|
+
of their Contribution(s) with the Work to which such Contribution(s) was
|
78
|
+
submitted. If You institute patent litigation against any entity (including a
|
79
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
|
80
|
+
Contribution incorporated within the Work constitutes direct or contributory
|
81
|
+
patent infringement, then any patent licenses granted to You under this License
|
82
|
+
for that Work shall terminate as of the date such litigation is filed.
|
83
|
+
|
84
|
+
4. Redistribution.
|
85
|
+
|
86
|
+
You may reproduce and distribute copies of the Work or Derivative Works thereof
|
87
|
+
in any medium, with or without modifications, and in Source or Object form,
|
88
|
+
provided that You meet the following conditions:
|
89
|
+
|
90
|
+
You must give any other recipients of the Work or Derivative Works a copy of
|
91
|
+
this License; and
|
92
|
+
You must cause any modified files to carry prominent notices stating that You
|
93
|
+
changed the files; and
|
94
|
+
You must retain, in the Source form of any Derivative Works that You distribute,
|
95
|
+
all copyright, patent, trademark, and attribution notices from the Source form
|
96
|
+
of the Work, excluding those notices that do not pertain to any part of the
|
97
|
+
Derivative Works; and
|
98
|
+
If the Work includes a "NOTICE" text file as part of its distribution, then any
|
99
|
+
Derivative Works that You distribute must include a readable copy of the
|
100
|
+
attribution notices contained within such NOTICE file, excluding those notices
|
101
|
+
that do not pertain to any part of the Derivative Works, in at least one of the
|
102
|
+
following places: within a NOTICE text file distributed as part of the
|
103
|
+
Derivative Works; within the Source form or documentation, if provided along
|
104
|
+
with the Derivative Works; or, within a display generated by the Derivative
|
105
|
+
Works, if and wherever such third-party notices normally appear. The contents of
|
106
|
+
the NOTICE file are for informational purposes only and do not modify the
|
107
|
+
License. You may add Your own attribution notices within Derivative Works that
|
108
|
+
You distribute, alongside or as an addendum to the NOTICE text from the Work,
|
109
|
+
provided that such additional attribution notices cannot be construed as
|
110
|
+
modifying the License.
|
111
|
+
You may add Your own copyright statement to Your modifications and may provide
|
112
|
+
additional or different license terms and conditions for use, reproduction, or
|
113
|
+
distribution of Your modifications, or for any such Derivative Works as a whole,
|
114
|
+
provided Your use, reproduction, and distribution of the Work otherwise complies
|
115
|
+
with the conditions stated in this License.
|
116
|
+
|
117
|
+
5. Submission of Contributions.
|
118
|
+
|
119
|
+
Unless You explicitly state otherwise, any Contribution intentionally submitted
|
120
|
+
for inclusion in the Work by You to the Licensor shall be under the terms and
|
121
|
+
conditions of this License, without any additional terms or conditions.
|
122
|
+
Notwithstanding the above, nothing herein shall supersede or modify the terms of
|
123
|
+
any separate license agreement you may have executed with Licensor regarding
|
124
|
+
such Contributions.
|
125
|
+
|
126
|
+
6. Trademarks.
|
127
|
+
|
128
|
+
This License does not grant permission to use the trade names, trademarks,
|
129
|
+
service marks, or product names of the Licensor, except as required for
|
130
|
+
reasonable and customary use in describing the origin of the Work and
|
131
|
+
reproducing the content of the NOTICE file.
|
132
|
+
|
133
|
+
7. Disclaimer of Warranty.
|
134
|
+
|
135
|
+
Unless required by applicable law or agreed to in writing, Licensor provides the
|
136
|
+
Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
|
137
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
|
138
|
+
including, without limitation, any warranties or conditions of TITLE,
|
139
|
+
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
|
140
|
+
solely responsible for determining the appropriateness of using or
|
141
|
+
redistributing the Work and assume any risks associated with Your exercise of
|
142
|
+
permissions under this License.
|
143
|
+
|
144
|
+
8. Limitation of Liability.
|
145
|
+
|
146
|
+
In no event and under no legal theory, whether in tort (including negligence),
|
147
|
+
contract, or otherwise, unless required by applicable law (such as deliberate
|
148
|
+
and grossly negligent acts) or agreed to in writing, shall any Contributor be
|
149
|
+
liable to You for damages, including any direct, indirect, special, incidental,
|
150
|
+
or consequential damages of any character arising as a result of this License or
|
151
|
+
out of the use or inability to use the Work (including but not limited to
|
152
|
+
damages for loss of goodwill, work stoppage, computer failure or malfunction, or
|
153
|
+
any and all other commercial damages or losses), even if such Contributor has
|
154
|
+
been advised of the possibility of such damages.
|
155
|
+
|
156
|
+
9. Accepting Warranty or Additional Liability.
|
157
|
+
|
158
|
+
While redistributing the Work or Derivative Works thereof, You may choose to
|
159
|
+
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
|
160
|
+
other liability obligations and/or rights consistent with this License. However,
|
161
|
+
in accepting such obligations, You may act only on Your own behalf and on Your
|
162
|
+
sole responsibility, not on behalf of any other Contributor, and only if You
|
163
|
+
agree to indemnify, defend, and hold each Contributor harmless for any liability
|
164
|
+
incurred by, or claims asserted against, such Contributor by reason of your
|
165
|
+
accepting any such warranty or additional liability.
|
166
|
+
|
167
|
+
END OF TERMS AND CONDITIONS
|
168
|
+
|
169
|
+
APPENDIX: How to apply the Apache License to your work
|
170
|
+
|
171
|
+
To apply the Apache License to your work, attach the following boilerplate
|
172
|
+
notice, with the fields enclosed by brackets "[]" replaced with your own
|
173
|
+
identifying information. (Don't include the brackets!) The text should be
|
174
|
+
enclosed in the appropriate comment syntax for the file format. We also
|
175
|
+
recommend that a file or class name and description of purpose be included on
|
176
|
+
the same "printed page" as the copyright notice for easier identification within
|
177
|
+
third-party archives.
|
178
|
+
|
179
|
+
Copyright [yyyy] [name of copyright owner]
|
180
|
+
|
181
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
182
|
+
you may not use this file except in compliance with the License.
|
183
|
+
You may obtain a copy of the License at
|
184
|
+
|
185
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
186
|
+
|
187
|
+
Unless required by applicable law or agreed to in writing, software
|
188
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
189
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
190
|
+
See the License for the specific language governing permissions and
|
191
|
+
limitations under the License.
|
data/README.textile
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
h1. 粗糙的MONGOID TAG
|
2
|
+
|
3
|
+
h3. 设计目的:
|
4
|
+
|
5
|
+
# 不用动脑子想tag的设计
|
6
|
+
# 单向对基于tag查询实体的优化
|
7
|
+
|
8
|
+
h3. 基于以下假设
|
9
|
+
|
10
|
+
# 根据标签名称,查找实体的情况频繁于根据实体查找tags
|
11
|
+
# 实体间不共享一类 tag
|
12
|
+
|
13
|
+
h3. 用法
|
14
|
+
|
15
|
+
<ruby>
|
16
|
+
|
17
|
+
class Model
|
18
|
+
include Mongoid::Document
|
19
|
+
include EasyMongoidTag
|
20
|
+
|
21
|
+
field :bname, as: :book_name, type: String
|
22
|
+
easy_tags :tests
|
23
|
+
end
|
24
|
+
|
25
|
+
book1 = Model.create(bname: '红楼梦', :tests => ['曹雪芹 ', ' 高 鹗 '])
|
26
|
+
book2 = Model.create(bname: '石头记', :tests => ['曹沾', '高 鹗'])
|
27
|
+
|
28
|
+
|
29
|
+
book1.test_tags
|
30
|
+
TestTag.find_by(title: '曹雪芹')
|
31
|
+
TestTag.search('曹')
|
32
|
+
|
33
|
+
|
34
|
+
</ruby>
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/easy_mongoid_tag/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = 'easy_mongoid_tag'
|
6
|
+
s.version = EasyMongoidTag::VERSION
|
7
|
+
s.date = '2013-09-05'
|
8
|
+
s.summary = "粗糙的mongid tag"
|
9
|
+
s.description = "实现实体和标签间的N2N关系,对基于tag查询实体的单向优化"
|
10
|
+
s.authors = ["Wade Xing"]
|
11
|
+
s.email = ['iamxingxing@gmail.com']
|
12
|
+
s.files = `git ls-files`.split($\)
|
13
|
+
|
14
|
+
s.executables = s.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
15
|
+
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
16
|
+
|
17
|
+
s.require_paths = ['lib']
|
18
|
+
|
19
|
+
s.homepage = 'https://github.com/xingxing/easy_mongoid_tag'
|
20
|
+
|
21
|
+
s.add_runtime_dependency 'mongoid', '~> 3.1.0'
|
22
|
+
|
23
|
+
s.add_development_dependency 'rspec', '~> 2.14.1'
|
24
|
+
s.add_development_dependency 'mongoid-rspec', '~> 1.9.0'
|
25
|
+
s.add_development_dependency 'guard', '~> 1.8.0'
|
26
|
+
s.add_development_dependency 'guard-rspec', '~> 3.0.0'
|
27
|
+
s.add_development_dependency 'guard-spork', '~> 1.5.1'
|
28
|
+
s.add_development_dependency 'terminal-notifier-guard', '~> 1.5.3'
|
29
|
+
end
|
@@ -0,0 +1,151 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module EasyMongoidTag
|
3
|
+
|
4
|
+
def self.included mod
|
5
|
+
unless mod.included_modules.include?(Mongoid::Document)
|
6
|
+
raise(RuntimeError, 'EasyMongoidTag is mixined A non-mongoid_document')
|
7
|
+
else
|
8
|
+
mod.class_eval do
|
9
|
+
extend ClassMethods
|
10
|
+
|
11
|
+
# 存储 tag 的名字
|
12
|
+
class_attribute :tag_items
|
13
|
+
self.tag_items = []
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
module ClassMethods
|
20
|
+
|
21
|
+
# 生成 标签field
|
22
|
+
# @param[Symbol]
|
23
|
+
def easy_tag tag_name
|
24
|
+
field_name = Helper.field_name(tag_name)
|
25
|
+
|
26
|
+
field field_name, type: Array
|
27
|
+
self.tag_items << tag_name
|
28
|
+
index({ field_name => 1 })
|
29
|
+
|
30
|
+
tag_class = generate_tag_class(tag_name)
|
31
|
+
|
32
|
+
self.instance_eval do
|
33
|
+
define_method Helper.tags_method_name(tag_name) do
|
34
|
+
tag_class.find(*self.send(field_name))
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
before_validation do |doc|
|
39
|
+
doc.send("#{field_name}=",
|
40
|
+
doc[tag_name].map do |title_or_object_id|
|
41
|
+
if title_or_object_id.is_a? Moped::BSON::ObjectId
|
42
|
+
title_or_object_id
|
43
|
+
else
|
44
|
+
title_or_object_id.strip!
|
45
|
+
tag = tag_class.where(title: title_or_object_id).first
|
46
|
+
if tag
|
47
|
+
tag.id
|
48
|
+
else
|
49
|
+
tag = tag_class.new(title: title_or_object_id)
|
50
|
+
tag.save ? tag.id : nil
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end.select(&:present?)) if doc[tag_name]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def easy_tags *tag_names
|
58
|
+
tag_names.each do |tag_name|
|
59
|
+
easy_tag tag_name
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# 生成标签类
|
64
|
+
#
|
65
|
+
def generate_tag_class tag_name
|
66
|
+
|
67
|
+
tag_class_name = Helper.tag_class_name(tag_name)
|
68
|
+
field_name = Helper.field_name(tag_name)
|
69
|
+
|
70
|
+
if Helper.class_existed?(tag_class_name)
|
71
|
+
raise(RuntimeError, "Class #{tag_class_name} already existed!")
|
72
|
+
return
|
73
|
+
else
|
74
|
+
# model 类的
|
75
|
+
main_class_name = self.name
|
76
|
+
Object.const_set(tag_class_name,
|
77
|
+
Class.new do
|
78
|
+
include Mongoid::Document
|
79
|
+
include Mongoid::Timestamps::Created
|
80
|
+
|
81
|
+
store_in collection: tag_class_name.tableize
|
82
|
+
|
83
|
+
field :title, type: String
|
84
|
+
index({ title: 1 }, { unique: true })
|
85
|
+
|
86
|
+
define_method main_class_name.downcase.pluralize do
|
87
|
+
Object.const_get(main_class_name).where(field_name => self.id)
|
88
|
+
end
|
89
|
+
|
90
|
+
class << self
|
91
|
+
def search key_word
|
92
|
+
self.any_of(title: /.*#{key_word}.*/)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
before_validation do |record|
|
97
|
+
record.title = record.title.strip
|
98
|
+
end
|
99
|
+
|
100
|
+
after_destroy do |record|
|
101
|
+
record.send(main_class_name.downcase.pluralize).each do |model|
|
102
|
+
Object.const_get(main_class_name).skip_callback(:validation, :before)
|
103
|
+
model.send("#{field_name}=", model.send(field_name).reject{|t| t == record.id } )
|
104
|
+
model.save
|
105
|
+
Object.const_get(main_class_name).set_callback(:validation, :before)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
end)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
|
115
|
+
module Helper
|
116
|
+
|
117
|
+
include ActiveSupport::Concern
|
118
|
+
|
119
|
+
class << self
|
120
|
+
|
121
|
+
def field_name tag_name
|
122
|
+
tag_name.to_sym
|
123
|
+
end
|
124
|
+
|
125
|
+
def tags_method_name tag_name
|
126
|
+
"#{tag_name.to_s.singularize}_tags".to_sym
|
127
|
+
end
|
128
|
+
|
129
|
+
# tags_list_name = 'list_' + tag_name
|
130
|
+
def tag_list_name tag_name
|
131
|
+
"list_#{tag_name}".to_sym
|
132
|
+
end
|
133
|
+
|
134
|
+
# 标签类的类名
|
135
|
+
# @return [String]
|
136
|
+
def tag_class_name tag_name
|
137
|
+
tag_name.to_s.classify + 'Tag'
|
138
|
+
end
|
139
|
+
|
140
|
+
# 是否已经存在 类
|
141
|
+
# @param [ String ] 类名
|
142
|
+
def class_existed? class_name
|
143
|
+
klass = Module.const_get(class_name)
|
144
|
+
return klass.is_a?(Class)
|
145
|
+
rescue NameError
|
146
|
+
return false
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
151
|
+
end
|