acts_as_word_cloud 0.0.1
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.
- data/.DS_Store +0 -0
- data/.document +5 -0
- data/.gitignore_new +7 -0
- data/.rspec +1 -0
- data/CHANGELOG +3 -0
- data/Gemfile +22 -0
- data/Gemfile.lock +130 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +122 -0
- data/Rakefile +52 -0
- data/VERSION +1 -0
- data/acts_as_word_cloud.gemspec +127 -0
- data/features/acts_as_word_cloud.feature +9 -0
- data/features/step_definitions/acts_as_word_cloud_steps.rb +0 -0
- data/features/support/env.rb +13 -0
- data/lib/acts_as_word_cloud/config.rb +31 -0
- data/lib/acts_as_word_cloud/engine.rb +4 -0
- data/lib/acts_as_word_cloud/railtie.rb +12 -0
- data/lib/acts_as_word_cloud/word_cloud.rb +227 -0
- data/lib/acts_as_word_cloud.rb +2 -0
- data/lib/generators/acts_as_word_cloud/install_generator.rb +23 -0
- data/lib/generators/acts_as_word_cloud/templates/config.rb +7 -0
- data/lib/model_methods_helper.rb +87 -0
- data/spec/acts_as_word_cloud_spec.rb +109 -0
- data/spec/dummy/README.rdoc +261 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/assets/javascripts/application.js +15 -0
- data/spec/dummy/app/assets/stylesheets/application.css +13 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/mailers/.gitkeep +0 -0
- data/spec/dummy/app/models/.gitkeep +0 -0
- data/spec/dummy/app/models/article.rb +9 -0
- data/spec/dummy/app/models/author.rb +7 -0
- data/spec/dummy/app/models/following.rb +5 -0
- data/spec/dummy/app/models/publisher.rb +7 -0
- data/spec/dummy/app/models/reader.rb +7 -0
- data/spec/dummy/app/models/site.rb +8 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/config/application.rb +65 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +37 -0
- data/spec/dummy/config/environments/production.rb +67 -0
- data/spec/dummy/config/environments/test.rb +37 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +15 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +58 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/db/migrate/20121107162154_create_system.rb +64 -0
- data/spec/dummy/db/schema.rb +81 -0
- data/spec/dummy/features/support/blueprints.rb +57 -0
- data/spec/dummy/lib/assets/.gitkeep +0 -0
- data/spec/dummy/lib/model_methods_helper.rb +87 -0
- data/spec/dummy/log/.gitkeep +0 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +25 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/spec_helper.rb +21 -0
- metadata +211 -0
@@ -0,0 +1,227 @@
|
|
1
|
+
module ActsAsWordCloud
|
2
|
+
module WordCloud
|
3
|
+
def self.included(base)
|
4
|
+
base.extend ClassMethods
|
5
|
+
end
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
# args:
|
9
|
+
# using, takes an array of Symbols that refer to the methods we'll use on the model calling word_cloud
|
10
|
+
# excluded models, takes in Class names of models we want to ignore that are associated to model calling word_cloud
|
11
|
+
# skipped attributes, takes in Symbols referring to attributes that won't be pulled from model calling word_cloud
|
12
|
+
# depth level, takes in an Integer referring to how deep of a recursive search we'll make
|
13
|
+
# no_mixin_fields, is a default pre-set array of methods to use on models that do not include the mixin
|
14
|
+
#
|
15
|
+
def acts_as_word_cloud(args)
|
16
|
+
|
17
|
+
# getter/setter methods for the module
|
18
|
+
mattr_accessor :word_cloud_using unless respond_to? :word_cloud_using
|
19
|
+
mattr_accessor :word_cloud_excluded unless respond_to? :word_cloud_excluded
|
20
|
+
mattr_accessor :word_cloud_skipped unless respond_to? :word_cloud_skipped
|
21
|
+
mattr_accessor :word_cloud_depth unless respond_to? :word_cloud_depth
|
22
|
+
mattr_accessor :word_cloud_no_mixin_fields unless respond_to? :word_cloud_no_mixin_fields
|
23
|
+
|
24
|
+
# set empty arrays to allow |= on values
|
25
|
+
unless self.word_cloud_using.is_a?(Array)
|
26
|
+
self.word_cloud_using = []
|
27
|
+
end
|
28
|
+
unless self.word_cloud_excluded.is_a?(Array)
|
29
|
+
self.word_cloud_excluded = []
|
30
|
+
end
|
31
|
+
unless self.word_cloud_skipped.is_a?(Array)
|
32
|
+
self.word_cloud_skipped = []
|
33
|
+
end
|
34
|
+
unless self.word_cloud_no_mixin_fields.is_a?(Array)
|
35
|
+
self.word_cloud_no_mixin_fields = []
|
36
|
+
end
|
37
|
+
|
38
|
+
# default values if none set in the mixin call on the model
|
39
|
+
self.word_cloud_using |= args[:methods_to_use].present? ? args[:methods_to_use] : []
|
40
|
+
self.word_cloud_excluded |= args[:excluded_models].present? ? args[:excluded_models] : []
|
41
|
+
self.word_cloud_skipped |= args[:skipped_attributes].present? ? args[:skipped_attributes] : []
|
42
|
+
self.word_cloud_depth = args[:depth].present? ? args[:depth] : ActsAsWordCloud.config.min_depth
|
43
|
+
self.word_cloud_no_mixin_fields = [:name, :title, :label] #ActsAsWordCloud.config.no_mixin_fields
|
44
|
+
|
45
|
+
include ActsAsWordCloud::WordCloud::InstanceMethods
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
module InstanceMethods
|
50
|
+
|
51
|
+
# collects associations on a model as long as they're not nil
|
52
|
+
#
|
53
|
+
# @param [Symbol] the association type to look in
|
54
|
+
# @returns [Array <Symbol>] association names under the passed in type
|
55
|
+
#
|
56
|
+
def word_cloud_get_associated(type)
|
57
|
+
self.class.reflect_on_all_associations(type).select {|r| self.send(r.name).present? }.collect { |r| r.name }
|
58
|
+
end
|
59
|
+
|
60
|
+
# goes through array of objects or arrays (in the case of has_many association)
|
61
|
+
#
|
62
|
+
# @param [Symbol] the association type to fetch objects from
|
63
|
+
# @returns [Array <Object>] that under association passed in
|
64
|
+
#
|
65
|
+
def word_cloud_associated_objects(type)
|
66
|
+
objects = []
|
67
|
+
associated = word_cloud_get_associated(type)
|
68
|
+
associated.each do |o|
|
69
|
+
if o.class == Array
|
70
|
+
nested_array = self.send(o)
|
71
|
+
nested_array.each do |a|
|
72
|
+
objects << a
|
73
|
+
end
|
74
|
+
else
|
75
|
+
objects << self.send(o)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
return objects
|
79
|
+
end
|
80
|
+
|
81
|
+
# removes objects that are in the list of objects to exclude
|
82
|
+
#
|
83
|
+
# @returns [Array <Object>] that are not in the excluded list
|
84
|
+
#
|
85
|
+
def word_cloud_exclude_words(objects)
|
86
|
+
if objects.nil?
|
87
|
+
return []
|
88
|
+
else
|
89
|
+
result = objects.flatten.reject { |x| self.word_cloud_excluded.include?(x.class) }
|
90
|
+
return result.present? ? result : []
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# removes objects that include word_cloud mixin
|
95
|
+
#
|
96
|
+
# @returns [Array <Object>] that don't include the mixin
|
97
|
+
#
|
98
|
+
def word_cloud_no_mixin(objects)
|
99
|
+
if objects.nil?
|
100
|
+
return []
|
101
|
+
else
|
102
|
+
result = objects.flatten.reject { |n| n.respond_to?(:word_cloud) }
|
103
|
+
result.present? ? result : []
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# goes through each object passed in trying the included methods for each of those objects
|
108
|
+
# keeps the first one to work and returns the value of that method called on the object
|
109
|
+
#
|
110
|
+
# @param [Array <Objects>] to look through for values
|
111
|
+
# @returns [Array <String>] values returned by method
|
112
|
+
#
|
113
|
+
def word_cloud_process_words(objects)
|
114
|
+
output = []
|
115
|
+
objects.each do |obj|
|
116
|
+
obj_calls = obj.word_cloud_using.select { |f| obj.respond_to?(f) }
|
117
|
+
if obj_calls.first.present?
|
118
|
+
output << obj.send(obj_calls.first)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
return output
|
122
|
+
end
|
123
|
+
|
124
|
+
# goes through each of the default fields to call on models that don't include mixin
|
125
|
+
# and attempts to return the value of the first one to work, if none do return model class name
|
126
|
+
#
|
127
|
+
# @returns [String] value for object passed in
|
128
|
+
#
|
129
|
+
def word_cloud_apply_fields_to(no_mixin_model)
|
130
|
+
# fields that should be tried on models that don't have the mixin, set with other attributes
|
131
|
+
fields = self.word_cloud_no_mixin_fields
|
132
|
+
fields.each do |f|
|
133
|
+
if no_mixin_model.respond_to?(f)
|
134
|
+
return no_mixin_model.send(f)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
return no_mixin_model.class.name
|
138
|
+
end
|
139
|
+
|
140
|
+
# goes through models that don't include mixin trying to find a relevant value for each
|
141
|
+
#
|
142
|
+
# @returns [Array <String>] of values for objects passed in
|
143
|
+
#
|
144
|
+
def word_cloud_find_field(no_mixin)
|
145
|
+
output = []
|
146
|
+
flag = 0
|
147
|
+
no_mixin.each do |n|
|
148
|
+
output << word_cloud_apply_fields_to(n)
|
149
|
+
end
|
150
|
+
return output
|
151
|
+
end
|
152
|
+
|
153
|
+
|
154
|
+
# returns values from methods specified in using option
|
155
|
+
# ignores string attributes that are listed in the skipped option
|
156
|
+
#
|
157
|
+
# @returns [Array <String>]
|
158
|
+
#
|
159
|
+
def word_cloud_get_valid_strings
|
160
|
+
output = []
|
161
|
+
ignore = []
|
162
|
+
|
163
|
+
self.word_cloud_using.each do |m|
|
164
|
+
output << self.send(m)
|
165
|
+
end
|
166
|
+
|
167
|
+
self.word_cloud_skipped.each do |s|
|
168
|
+
ignore << self.send(s)
|
169
|
+
end
|
170
|
+
|
171
|
+
# current model's string attributes
|
172
|
+
output += self.attributes.select {|k,v| v.class == String}.values
|
173
|
+
output -= ignore
|
174
|
+
|
175
|
+
return output
|
176
|
+
end
|
177
|
+
|
178
|
+
# finds string attributes on model
|
179
|
+
# processes associations on model, either fetching word_cloud results if they include mixin or default information if they don't
|
180
|
+
# if depth is said to something higher than one the word_cloud results on each associated model then makes more recursive calls (BFS)
|
181
|
+
#
|
182
|
+
# @params Integer, recursive depth for method; Symbol for the type of result (array or string)
|
183
|
+
# @returns [Array <String>] all processed values
|
184
|
+
#
|
185
|
+
def word_cloud( depth = self.word_cloud_depth, type = :string )
|
186
|
+
|
187
|
+
output = []
|
188
|
+
objects = []
|
189
|
+
no_mixin = []
|
190
|
+
|
191
|
+
# string attributes in current model
|
192
|
+
output = word_cloud_get_valid_strings
|
193
|
+
|
194
|
+
# objects on all associations collected
|
195
|
+
objects += self.word_cloud_associated_objects(:belongs_to)
|
196
|
+
objects += self.word_cloud_associated_objects(:has_one)
|
197
|
+
objects += self.word_cloud_associated_objects(:has_many)
|
198
|
+
|
199
|
+
# remove objects that have been explicitly excluded on current model
|
200
|
+
objects = word_cloud_exclude_words(objects)
|
201
|
+
# find associated models that do not include mixin
|
202
|
+
no_mixin = word_cloud_no_mixin(objects)
|
203
|
+
objects -= no_mixin
|
204
|
+
|
205
|
+
# process object using set methods for each model with mixin, or try preset general methods for models without
|
206
|
+
output += self.word_cloud_process_words(objects) + word_cloud_find_field(no_mixin)
|
207
|
+
|
208
|
+
# recursive step, if depth > 1, calls word cloud on objects array (which already excludes objects that don't have the mixin)
|
209
|
+
if depth < 1
|
210
|
+
return "depth for word cloud can't be less than 0"
|
211
|
+
elsif depth == 1
|
212
|
+
# recursive steps got a bit more complicated with :array/:string addition, that last line gets rid of duplicate results in the 'long' strings being returned
|
213
|
+
return ( type == :array ? output.uniq : output.uniq.join(' ') )
|
214
|
+
else
|
215
|
+
if type == :array
|
216
|
+
output |= objects.collect { |o| o.word_cloud(depth-1, :array) }
|
217
|
+
return output.flatten.uniq
|
218
|
+
else
|
219
|
+
output |= objects.collect { |o| o.word_cloud(depth-1) }
|
220
|
+
return output.flatten.join(' ').split(' ').uniq.join(' ')
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
require 'rails/generators/migration'
|
3
|
+
require 'active_record'
|
4
|
+
require 'rails/generators/active_record'
|
5
|
+
|
6
|
+
module ActsAsWordCloud
|
7
|
+
module Generators
|
8
|
+
class InstallGenerator < Rails::Generators::Base
|
9
|
+
include Rails::Generators::Migration
|
10
|
+
|
11
|
+
source_root File.expand_path(File.join(File.dirname(__FILE__), "templates"))
|
12
|
+
|
13
|
+
desc <<DESC
|
14
|
+
Description:
|
15
|
+
Copies over migrations and config for the normalizer.
|
16
|
+
DESC
|
17
|
+
|
18
|
+
def copy_config_file
|
19
|
+
copy_file "config.rb", "config/initializers/acts_as_word_cloud.rb"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
ActsAsWordCloud.configure do |config|
|
2
|
+
#the default setting for smallest recursive step for calling wordcloud on models
|
3
|
+
config.min_depth = 1
|
4
|
+
|
5
|
+
#methods whose values we'll attempt to get for models that don't include the mixin
|
6
|
+
config.no_mixin_fields = [:name, :title, :label]
|
7
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'find'
|
2
|
+
class ModelMethodsHelper
|
3
|
+
|
4
|
+
# finds or makes a model based on the given attributes
|
5
|
+
# @param [Constant] model_name The name of the model
|
6
|
+
# @param [Hash] attributes The attributes to find the model or add to the new one
|
7
|
+
def self.find_or_make_by_attributes(model_name, attributes)
|
8
|
+
instances = model_name.where(attributes)
|
9
|
+
if instances.empty?
|
10
|
+
return model_name.make(attributes)
|
11
|
+
else
|
12
|
+
return instances.first
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# Uses the descendants_of method to determine the model structure
|
17
|
+
# Then tableizes and converts to symbol
|
18
|
+
#
|
19
|
+
# Load all models must be run for accurate descendants list
|
20
|
+
# it is now being called every time this method is called
|
21
|
+
# for now it works because this is only called one time when the authorization config is loaded on initialize
|
22
|
+
# if this ever changes, this code may need to be update (2-15-2012)
|
23
|
+
#
|
24
|
+
# @return [Array] Array with file names underscored and pluralized in the format [:users, :case_placements, :roles, :job_locations, ... ]
|
25
|
+
def self.get_model_symbol_array
|
26
|
+
# Old method:
|
27
|
+
# Major redesign of this method that finds namespaced models
|
28
|
+
# Finds all files in the given folder, tries to find the ruby files
|
29
|
+
# Then processes the names to get the names we need for the code
|
30
|
+
#
|
31
|
+
# @return [Array] Array with file names underscored and pluralized in the format [:users, :case_placements, :roles, :job_locations, ... ]
|
32
|
+
#model_array = []
|
33
|
+
#Find.find("#{Rails.root.to_s}/app/models") do |model_path|
|
34
|
+
# if model_path.match(/\.rb$/)
|
35
|
+
# model_path = model_path.gsub("#{Rails.root.to_s}/app/models/", "")
|
36
|
+
# model_path = model_path.gsub("/","_")
|
37
|
+
# model_path = model_path.gsub(/\.rb$/, "")
|
38
|
+
# model_array.push model_path.pluralize.to_sym
|
39
|
+
# end
|
40
|
+
#end
|
41
|
+
#return model_array
|
42
|
+
|
43
|
+
# new method
|
44
|
+
self.load_all_models
|
45
|
+
# returns the table name if there is one or tableizes the model name if not
|
46
|
+
# our permissions system generally uses table names for model permissions
|
47
|
+
return self.descendants_of(ActiveRecord::Base).map{ |m| m.abstract_class ? m.to_s.tableize.to_sym : m.table_name.to_sym }
|
48
|
+
end
|
49
|
+
|
50
|
+
# Requires all models so that they are visible in the object space
|
51
|
+
# This is only necessary when we are not caching classes
|
52
|
+
def self.load_all_models
|
53
|
+
if !::Rails.application.config.cache_classes
|
54
|
+
Dir[Rails.root.join("app/models/**/*.rb")].each {|f| require f}
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Return a list of descendants of the given model.
|
59
|
+
#
|
60
|
+
# If direct is set to true, only return immediate descendants
|
61
|
+
# The load_all_models must be called before this is called or the result may not be correct
|
62
|
+
#
|
63
|
+
# @param [Constant] parent_class The parent class to look for descendants for
|
64
|
+
# @param [Boolean] direct Whether to look for all descendants or immediate descendants
|
65
|
+
# @return [Array] An array of class constants that satisfy the conditions of the parameters
|
66
|
+
def self.descendants_of(parent_class, direct = false)
|
67
|
+
classes = []
|
68
|
+
ObjectSpace.each_object(::Class).each do |klass|
|
69
|
+
if direct
|
70
|
+
classes << klass if klass.superclass == parent_class
|
71
|
+
else
|
72
|
+
classes << klass if klass < parent_class
|
73
|
+
end
|
74
|
+
end
|
75
|
+
return classes
|
76
|
+
end
|
77
|
+
|
78
|
+
# Convenience method to return the results of descendants_of with direct set to true
|
79
|
+
#
|
80
|
+
# The load_all_models must be called before this is called or the result may not be correct
|
81
|
+
#
|
82
|
+
# @param [Constant] parent_class The parent class to look for descendants for
|
83
|
+
# @return [Array] An array of class constants that satisfy the conditions of the parameters
|
84
|
+
def self.direct_descendants_of(parent_class)
|
85
|
+
return self.descendants_of(parent_class, true)
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe "ActsAsWordCloud" do
|
4
|
+
before(:all) do
|
5
|
+
@lone_article = Article.make
|
6
|
+
@publisher = Publisher.make(:name => "publisher", :location => "location")
|
7
|
+
@site = Site.make( :name => "site name", :domain => "uff.us", :genre => "site genre", :publisher => @publisher)
|
8
|
+
@author = Author.make(:name => "author", :genre => "author genre", :publisher => @publisher, :site => @site)
|
9
|
+
@article = Article.make(:title => "article title", :genre => "genre", :content => "article text", :author => @author, :publisher => @publisher, :site => @site)
|
10
|
+
@reader = Reader.make(:username => "reader", :site => @site)
|
11
|
+
@following = Following.make(:article => @article, :reader => @reader, :special_name => "following1")
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "word_cloud" do
|
15
|
+
describe "class method use_word_cloud" do
|
16
|
+
it "should contain set or default values in attributes" do
|
17
|
+
@article.word_cloud_using.should == [:title]
|
18
|
+
@article.word_cloud_excluded.should == []
|
19
|
+
@article.word_cloud_depth.should == 1
|
20
|
+
@article.word_cloud_no_mixin_fields.should == [:name, :title, :label]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should return the right association models" do
|
25
|
+
@lone_article.word_cloud.should == [@lone_article.title, @lone_article.genre, @lone_article.content, @lone_article.author.name, @lone_article.publisher.name, @lone_article.site.domain ].join(' ')
|
26
|
+
@article.word_cloud.should == [@article.title, @article.genre, @article.content, @article.author.name, @article.publisher.name, @article.site.domain, @article.readers.first.username, "Following" ].join(' ')
|
27
|
+
|
28
|
+
@publisher2 = Publisher.make(:name => "publisher2", :location => "location2")
|
29
|
+
@site2 = Site.make( :name => "site2 name", :domain => "uff.us2", :genre => "site2 genre", :publisher => @publisher2)
|
30
|
+
@author2 = Author.make(:name => "author2", :genre => "author2 genre", :publisher => @publisher2, :site => @site2)
|
31
|
+
@article2 = Article.make(:title => "article2 title", :genre => "genre2", :content => "article2 text", :author => @author2, :publisher => @publisher2, :site => @site2)
|
32
|
+
@following2 = Following.make(:article => @article2, :reader => @reader , :special_name => "following2")
|
33
|
+
|
34
|
+
@reader.word_cloud(2, :array).should == [@reader.username, @reader.site.domain, @article.title, @article2.title, "Following", @site.name, @site.genre, @site.publisher.name, @site.authors.first.name, @article.genre, @article.content, @article2.genre, @article2.content, @article2.author.name, @article2.publisher.name, @article2.site.domain ]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "instance methods:" do
|
39
|
+
describe "word_cloud_associated_objects" do
|
40
|
+
it "should return correct models when called with belongs_to" do
|
41
|
+
@article.word_cloud_associated_objects(:belongs_to).should == [@article.author, @article.publisher, @article.site]
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should return correct models when called with has_many" do
|
45
|
+
@article.word_cloud_associated_objects(:has_many).should == [@article.followings, @article.readers]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "word_cloud_get_associated" do
|
50
|
+
it "should return collectoin of non-nil associated models" do
|
51
|
+
@article.word_cloud_get_associated(:belongs_to).should == [:author, :publisher, :site]
|
52
|
+
@lone_article.word_cloud_get_associated(:has_many).should == []
|
53
|
+
@article.word_cloud_get_associated(:has_many).should == [:followings, :readers]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "word_cloud_exclude_words" do
|
58
|
+
it "should not keep excluded models" do
|
59
|
+
@article.stub!(:word_cloud_excluded).and_return([Publisher])
|
60
|
+
objects = @article.word_cloud_associated_objects(:belongs_to)
|
61
|
+
@article.word_cloud_exclude_words(objects).should == [@article.author, @article.site]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe "word_cloud_no_mixin" do
|
66
|
+
it "should only have models that don't have the mixin" do
|
67
|
+
objects = @article.word_cloud_associated_objects(:has_many)
|
68
|
+
@article.word_cloud_no_mixin(objects).should == @article.followings
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "word_cloud_process_words" do
|
73
|
+
it "should return result of first included method to work on objects with mixin" do
|
74
|
+
objects = []
|
75
|
+
objects += @article.word_cloud_associated_objects(:belongs_to)
|
76
|
+
objects += @article.word_cloud_associated_objects(:has_many)
|
77
|
+
objects = @article.word_cloud_exclude_words(objects)
|
78
|
+
no_mixin = @article.word_cloud_no_mixin(objects)
|
79
|
+
objects -= no_mixin
|
80
|
+
@article.word_cloud_process_words(objects).should == [@article.author.name, @article.publisher.name, @article.site.domain, @article.readers.first.username]
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe "word_cloud_apply_fields_to" do
|
85
|
+
it "return the value found in the first method to work on object passed in, if there's none return class name" do
|
86
|
+
@article.word_cloud_apply_fields_to(@article.followings.first).should == "Following"
|
87
|
+
@article.stub!(:word_cloud_no_mixin_fields).and_return([:special_name])
|
88
|
+
@article.word_cloud_apply_fields_to(@article.followings.first).should == @article.followings.first.special_name
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe "word_cloud_find_field" do
|
93
|
+
it "should return result of first included method to work on objects with mixin or their class names" do
|
94
|
+
@article.word_cloud_find_field(@article.followings).should == ["Following"]
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe "word_cloud_get_valid_strings" do
|
99
|
+
it "should return used methods on model and string attributes not in skipped list" do
|
100
|
+
@article.stub!(:word_cloud_skipped).and_return([:title, :content])
|
101
|
+
@article.word_cloud_get_valid_strings.should_not include "article title"
|
102
|
+
@article.word_cloud_get_valid_strings.should_not include "article text"
|
103
|
+
@article.word_cloud_get_valid_strings.should include "genre"
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|