populate-me 0.0.33 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -0
  3. data/LICENSE +1 -1
  4. data/README.md +399 -4
  5. data/Rakefile +14 -0
  6. data/example/config.ru +67 -0
  7. data/lib/populate_me.rb +2 -0
  8. data/lib/populate_me/admin.rb +143 -0
  9. data/lib/populate_me/admin/__assets__/css/main.css +174 -0
  10. data/lib/populate_me/admin/__assets__/js/columnav.js +82 -0
  11. data/lib/populate_me/admin/__assets__/js/main.js +251 -0
  12. data/lib/populate_me/admin/__assets__/js/mustache.js +578 -0
  13. data/lib/populate_me/admin/__assets__/js/sortable.js +2 -0
  14. data/lib/populate_me/admin/views/page.erb +163 -0
  15. data/lib/populate_me/api.rb +124 -0
  16. data/lib/populate_me/attachment.rb +182 -0
  17. data/lib/populate_me/document.rb +178 -0
  18. data/lib/populate_me/document_mixins/admin_adapter.rb +131 -0
  19. data/lib/populate_me/document_mixins/callbacks.rb +104 -0
  20. data/lib/populate_me/document_mixins/outcasting.rb +49 -0
  21. data/lib/populate_me/document_mixins/persistence.rb +92 -0
  22. data/lib/populate_me/document_mixins/schema.rb +99 -0
  23. data/lib/populate_me/document_mixins/typecasting.rb +60 -0
  24. data/lib/populate_me/document_mixins/validation.rb +44 -0
  25. data/lib/populate_me/file_system_attachment.rb +40 -0
  26. data/lib/populate_me/grid_fs_attachment.rb +127 -0
  27. data/lib/populate_me/mongo.rb +98 -3
  28. data/lib/populate_me/variation.rb +34 -0
  29. data/lib/populate_me/version.rb +4 -0
  30. data/populate-me.gemspec +20 -12
  31. data/test/helper.rb +37 -0
  32. data/test/test_admin.rb +161 -0
  33. data/test/test_api.rb +246 -0
  34. data/test/test_attachment.rb +155 -0
  35. data/test/test_document.rb +120 -0
  36. data/test/test_document_admin_adapter.rb +43 -0
  37. data/test/test_document_callbacks.rb +107 -0
  38. data/test/test_document_persistence.rb +56 -0
  39. data/test/test_document_typecasting.rb +121 -0
  40. data/test/test_mongo.rb +217 -0
  41. data/test/test_variation.rb +91 -0
  42. data/test/test_version.rb +11 -0
  43. metadata +115 -66
  44. data/lib/populate_me/control.rb +0 -196
  45. data/lib/populate_me/control/_public/css/main.css +0 -207
  46. data/lib/populate_me/control/_public/css/plugin.asmselect.css +0 -63
  47. data/lib/populate_me/control/_public/css/ui-darkness/images/ui-bg_flat_30_cccccc_40x100.png +0 -0
  48. data/lib/populate_me/control/_public/css/ui-darkness/images/ui-bg_flat_50_5c5c5c_40x100.png +0 -0
  49. data/lib/populate_me/control/_public/css/ui-darkness/images/ui-bg_glass_20_555555_1x400.png +0 -0
  50. data/lib/populate_me/control/_public/css/ui-darkness/images/ui-bg_glass_40_0078a3_1x400.png +0 -0
  51. data/lib/populate_me/control/_public/css/ui-darkness/images/ui-bg_glass_40_ffc73d_1x400.png +0 -0
  52. data/lib/populate_me/control/_public/css/ui-darkness/images/ui-bg_gloss-wave_25_333333_500x100.png +0 -0
  53. data/lib/populate_me/control/_public/css/ui-darkness/images/ui-bg_highlight-soft_80_eeeeee_1x100.png +0 -0
  54. data/lib/populate_me/control/_public/css/ui-darkness/images/ui-bg_inset-soft_25_000000_1x100.png +0 -0
  55. data/lib/populate_me/control/_public/css/ui-darkness/images/ui-bg_inset-soft_30_f58400_1x100.png +0 -0
  56. data/lib/populate_me/control/_public/css/ui-darkness/images/ui-icons_222222_256x240.png +0 -0
  57. data/lib/populate_me/control/_public/css/ui-darkness/images/ui-icons_4b8e0b_256x240.png +0 -0
  58. data/lib/populate_me/control/_public/css/ui-darkness/images/ui-icons_a83300_256x240.png +0 -0
  59. data/lib/populate_me/control/_public/css/ui-darkness/images/ui-icons_cccccc_256x240.png +0 -0
  60. data/lib/populate_me/control/_public/css/ui-darkness/images/ui-icons_ffffff_256x240.png +0 -0
  61. data/lib/populate_me/control/_public/css/ui-darkness/jquery-ui-1.8.17.custom.css +0 -430
  62. data/lib/populate_me/control/_public/img/grip.png +0 -0
  63. data/lib/populate_me/control/_public/img/icons-cms-solarized.png +0 -0
  64. data/lib/populate_me/control/_public/img/icons-cms.png +0 -0
  65. data/lib/populate_me/control/_public/img/placeholder.png +0 -0
  66. data/lib/populate_me/control/_public/img/placeholder.stash_thumb.gif +0 -0
  67. data/lib/populate_me/control/_public/img/placeholder.stash_thumb.png +0 -0
  68. data/lib/populate_me/control/_public/img/small-loader.gif +0 -0
  69. data/lib/populate_me/control/_public/js/addon.timepicker.js +0 -20
  70. data/lib/populate_me/control/_public/js/jquery-ui.js +0 -114
  71. data/lib/populate_me/control/_public/js/jquery.js +0 -167
  72. data/lib/populate_me/control/_public/js/jquery.mustache.js +0 -559
  73. data/lib/populate_me/control/_public/js/main.js +0 -144
  74. data/lib/populate_me/control/_public/js/plugin.asmselect.js +0 -407
  75. data/lib/populate_me/control/_public/js/plugin.form.js +0 -11
  76. data/lib/populate_me/control/_public/js/plugin.quicksearch.js +0 -1
  77. data/lib/populate_me/control/_public/js/plugin.underwood.js +0 -4
  78. data/lib/populate_me/control/views/populate_me_layout.erb +0 -75
  79. data/lib/populate_me/ext.rb +0 -16
  80. data/lib/populate_me/mongo/backend_api_plug.rb +0 -78
  81. data/lib/populate_me/mongo/crushyform.rb +0 -243
  82. data/lib/populate_me/mongo/mutation.rb +0 -324
  83. data/lib/populate_me/mongo/plug.rb +0 -134
  84. data/lib/populate_me/mongo/stash.rb +0 -171
  85. data/test/spec_ext.rb +0 -29
  86. data/test/spec_mongo_mutation.rb +0 -279
@@ -1,134 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require 'populate_me/mongo/mutation'
4
- require 'populate_me/mongo/stash'
5
- require 'populate_me/mongo/crushyform'
6
- require 'populate_me/mongo/backend_api_plug'
7
-
8
- module PopulateMe
9
- module Mongo
10
- module Plug
11
-
12
- # This module is the one that plugs the model to the CMS
13
-
14
- def self.included(base)
15
- base.class_eval do
16
- include PopulateMe::Mongo::Mutation
17
- include PopulateMe::Mongo::Stash if (base.const_defined?(:WITH_STASH) && base::WITH_STASH)
18
- include PopulateMe::Mongo::BackendApiPlug
19
- include PopulateMe::Mongo::Crushyform
20
- include InstanceMethods
21
- end
22
- base.extend(ClassMethods)
23
- base.populate_config = {:nut_tree_class=>'sortable-grid'}
24
- end
25
-
26
- module ClassMethods
27
-
28
- attr_accessor :populate_config
29
-
30
- # def list_view(r)
31
- # @list_options = {:request=>r, :destination=>r.fullpath, :path=>r.script_name, :filter=>r['filter'] }
32
- # @list_options.store(:sortable,sortable_on_that_page?)
33
- # out = list_view_header
34
- # out << many_to_many_picker unless populate_config[:minilist_class].nil?
35
- # out << "<ul class='nut-tree #{'sortable' if @list_options[:sortable]} #{populate_config[:nut_tree_class]}' id='#{self.name}' rel='#{@list_options[:path]}/#{self.name}'>"
36
- # self.find(@list_options[:filter]||{}).each {|m| out << m.to_nutshell }
37
- # out << "</ul>"
38
- # end
39
-
40
- def sortable_on_that_page?(r)
41
- @schema.key?('position') && (@schema['position'][:scope].nil? || (r['filter']||{}).key?(@schema['position'][:scope]))
42
- end
43
-
44
- # def minilist_view
45
- # o = "<ul class='minilist'>\n"
46
- # self.collection.find.each_mutant do |m|
47
- # thumb = m.respond_to?(:to_populate_thumb) ? m.to_populate_thumb('stash_thumb_gif') : m.placeholder_thumb('stash_thumb_gif')
48
- # o << "<li title='#{m.to_label}' id='mini-#{m.id}'>#{thumb}<div>#{m.to_label}</div></li>\n"
49
- # end
50
- # o << "</ul>\n"
51
- # end
52
-
53
- private
54
-
55
- def image_slot(name='image',opts={})
56
- super(name,opts)
57
- # First image slot is considered the best populate thumb by default
58
- unless instance_methods.include?(:to_populate_thumb)
59
- define_method :to_populate_thumb do |style|
60
- generic_thumb(name, style)
61
- end
62
- end
63
- end
64
-
65
- end
66
-
67
- module InstanceMethods
68
-
69
- def after_stash(col)
70
- convert(col, "-resize '100x75^' -gravity center -extent 100x75", 'stash_thumb_gif')
71
- end
72
-
73
- def generic_thumb(img , size='stash_thumb_gif', obj=self)
74
- return placeholder_thumb(size) if obj.nil?
75
- current = obj.doc[img]
76
- if !current.nil? && !current[size].nil?
77
- "/gridfs/#{current[size]}"
78
- else
79
- placeholder_thumb(size)
80
- end
81
- end
82
-
83
- def placeholder_thumb(size)
84
- "/_public/img/placeholder.#{size.gsub(/^(.*)_([a-zA-Z]+)$/, '\1.\2')}"
85
- end
86
-
87
- def to_nutshell
88
- {
89
- 'class_name'=>model.name,
90
- 'id'=>@doc['_id'].to_s,
91
- 'foreign_key_name'=>model.foreign_key_name,
92
- 'title'=>self.to_label,
93
- 'thumb'=>self.respond_to?(:to_populate_thumb) ? self.to_populate_thumb('stash_thumb_gif') : nil,
94
- 'children'=>nutshell_children,
95
- }
96
- end
97
-
98
- def in_nutshell
99
- o = model.list_options
100
- out = "<div class='in-nutshell'>\n"
101
- out << self.to_populate_thumb('nutshell_jpg') if self.respond_to?(:to_populate_thumb)
102
- cols = model.populate_config[:quick_update_fields] || nutshell_backend_columns.select{|col|
103
- [:boolean,:select].include?(model.schema[col][:type]) && !model.schema[col][:multiple] && !model.schema[col][:no_quick_update]
104
- }
105
- cols.each do |c|
106
- column_label = c.to_s.sub(/^id_/, '').tr('_', ' ').capitalize
107
- out << "<div class='quick-update'><form><span class='column-title'>#{column_label}:</span> #{self.crushyinput(c)}</form></div>\n"
108
- end
109
- out << "</div>\n"
110
- end
111
-
112
- def nutshell_backend_associations
113
- model.relationships
114
- end
115
-
116
- def nutshell_children
117
- nutshell_backend_associations.inject([]) do |arr, (k, opts)|
118
- unless opts[:hidden]
119
- klass = Kernel.const_get(k)
120
- arr << {
121
- 'children_class_name'=>k,
122
- 'title'=>opts[:link_text] || "#{klass.human_name}(s)",
123
- 'count'=>self.children_count(klass),
124
- }
125
- end
126
- end
127
- end
128
-
129
- end
130
-
131
- end
132
- end
133
- end
134
-
@@ -1,171 +0,0 @@
1
- # encoding: utf-8
2
- module PopulateMe
3
- module Mongo
4
- module Stash
5
-
6
- # This module gives models the ability to deal with attachments
7
-
8
- def self.included(base)
9
- Stash.classes << base
10
- base.extend(ClassMethods)
11
- base.gridfs = GRID
12
- end
13
-
14
- module ClassMethods
15
- attr_accessor :gridfs
16
- def all_after_stash
17
- self.collection.find.each do |i|
18
- self.schema.each do |k,v|
19
- obj = self.new(i)
20
- obj.after_stash(k) if v[:type]==:attachment&&obj[k].to_s!=''
21
- end
22
- end
23
- end
24
- end
25
-
26
- # Instance Methods
27
-
28
- def build_image_tag(col='image', style='original', html_attributes={})
29
- return '' if @doc[col].nil?||@doc[col][style].nil?
30
- title_field, alt_field = col+'_tooltip', col+'_alternative_text'
31
- title = @doc[title_field] if model.schema.keys.include?(title_field)
32
- alt = @doc[alt_field] if model.schema.keys.include?(alt_field)
33
- html_attributes = {:src => "/gridfs/#{@doc[col][style]}", :title => title, :alt => alt}.update(html_attributes)
34
- html_attributes = html_attributes.map do |k,v|
35
- %{#{k}="#{model.html_escape(v.to_s)}"}
36
- end.join(' ')
37
- "<img #{html_attributes} />"
38
- end
39
-
40
- def fix_type_attachment(k,v)
41
- if v=='nil'
42
- delete_files_for(k) unless new?
43
- @doc[k] = nil
44
- elsif v.is_a?(Hash)&&v.key?(:tempfile)
45
- delete_files_for(k) unless new?
46
- @temp_attachments ||= {}
47
- @temp_attachments[k] = v
48
- attachment_id = model.gridfs.upload_from_stream(
49
- v[:filename],
50
- v[:tempfile], {
51
- :content_type=>v[:type]
52
- })
53
- @doc[k] = {'original'=>attachment_id}
54
- else # Untouched
55
- @doc[k] = @old_doc[k]
56
- end
57
- end
58
-
59
- def delete_files_for(col)
60
- obj = (@old_doc||@doc)[col]
61
- if obj.respond_to?(:each)
62
- obj.each do |k,v|
63
- gridfile = model.gridfs.find(_id: v).first
64
- model.gridfs.delete(v) unless gridfile.nil?
65
- end
66
- end
67
- end
68
-
69
- def after_delete
70
- super
71
- model.schema.each do |k,v|
72
- delete_files_for(k) if v[:type]==:attachment
73
- end
74
- end
75
-
76
- def after_save
77
- super
78
- unless @temp_attachments.nil?
79
- @temp_attachments.each do |k,v|
80
- after_stash(k)
81
- end
82
- end
83
- end
84
-
85
- def after_stash(col); end
86
-
87
- def convert(col, convert_steps, style)
88
- return if @doc[col].nil?
89
- if @temp_attachments.nil? || @temp_attachments[col].nil?
90
- f = model.gridfs.find({'_id'=>@doc[col]['original']}).first
91
- return if f.nil?
92
- src = Tempfile.new('MongoStash_src')
93
- src.binmode
94
- model.gridfs.download_to_stream(@doc[col]['original'], src)
95
- return unless f['contentType'].to_s[/^image\//]
96
- src.close
97
- @temp_attachments ||= {}
98
- @temp_attachments[col] ||= {}
99
- @temp_attachments[col][:tempfile] = src
100
- @temp_attachments[col][:type] = f['contentType']
101
- else
102
- return unless @temp_attachments[col][:type][/^image\//]
103
- src = @temp_attachments[col][:tempfile]
104
- end
105
- model.gridfs.delete(@doc[col][style]) unless @doc[col][style].nil?
106
- ext = style[/[a-zA-Z]+$/].insert(0,'.')
107
- content_type = Rack::Mime.mime_type(ext)
108
- unless content_type[/^image\//]
109
- ext = '.jpg'
110
- content_type = 'image/jpeg'
111
- end
112
- dest = Tempfile.new(['MongoStash_dest', ext])
113
- dest.binmode
114
- dest.close
115
- system "convert \"#{src.path}\" #{convert_steps} \"#{dest.path}\""
116
- filename = "#{model.name}/#{self.id}/#{style}"
117
- attachment_id = model.gridfs.upload_from_stream(
118
- filename,
119
- dest.open,
120
- {:content_type=>content_type}
121
- )
122
- @doc[col] = @doc[col].update({style=>attachment_id})
123
- model.collection.update_one({'_id'=>@doc['_id']}, @doc)
124
- #src.close!
125
- dest.close!
126
- end
127
-
128
- class << self
129
- attr_accessor :classes
130
- Stash.classes = []
131
-
132
- def all_after_stash
133
- Stash.classes.each do |m|
134
- m.all_after_stash
135
- end
136
- end
137
-
138
- def fix_dots_in_keys(c, for_real=false)
139
- puts "\n#{c}" unless for_real
140
- img_keys = c.schema.select{|k,v| v[:type]==:attachment }.keys
141
- c.find({}, {:fields=>img_keys}).each do |e|
142
- old_hash = e.doc.select{|k,v| img_keys.include?(k) }
143
- fixed_hash = Marshal.load(Marshal.dump(old_hash))
144
- img_keys.each do |k|
145
- (fixed_hash[k]||{}).keys.each do |style|
146
- fixed_hash[k][style.tr('.','_')] = fixed_hash[k].delete(style)
147
- end
148
- end
149
- next if old_hash==fixed_hash
150
-
151
- if for_real
152
- c.collection.update_one({'_id'=>e.id}, {'$set'=>fixed_hash})
153
- else
154
- puts old_hash.inspect
155
- puts fixed_hash.inspect
156
- end
157
-
158
- end
159
- end
160
-
161
- def all_fix_dots_in_keys(for_real=false)
162
- Stash.classes.each do |c|
163
- Stash.fix_dots_in_keys(c, for_real)
164
- end
165
- end
166
-
167
- end
168
-
169
- end
170
- end
171
- end
data/test/spec_ext.rb DELETED
@@ -1,29 +0,0 @@
1
- # encoding: utf-8
2
- Encoding.default_internal = Encoding.default_external = Encoding::UTF_8 if RUBY_VERSION >= '1.9.0'
3
-
4
- require 'rubygems'
5
- require 'bacon'
6
- $:.unshift './lib'
7
- require "populate_me/ext"
8
-
9
- describe 'Integer' do
10
- describe '#to_price_string' do
11
- should 'Display numbers correctly' do
12
- 4595.to_price_string.should=='45.95'
13
- 7000.to_price_string.should=='70'
14
- 1234567890.to_price_string.should=='12,345,678.90'
15
- -140000.to_price_string.should=='-1,400'
16
- end
17
- end
18
- end
19
-
20
- describe 'String' do
21
- describe '#to_price_integer' do
22
- should 'Parse numbers correctly' do
23
- '28'.to_price_integer.should==2800
24
- '45.95'.to_price_integer.should==4595
25
- ' £-12,345,678.90 '.to_price_integer.should==-1234567890
26
- end
27
- end
28
- end
29
-
@@ -1,279 +0,0 @@
1
- # encoding: utf-8
2
- Encoding.default_internal = Encoding.default_external = Encoding::UTF_8 if RUBY_VERSION >= '1.9.0'
3
-
4
- require 'rubygems'
5
- require 'bacon'
6
- require 'mongo'
7
- require 'rack/utils'
8
- $:.unshift './lib'
9
- require 'populate_me/mongo'
10
-
11
- MONGO = Mongo::Client.new([ '127.0.0.1:27017' ], :database => 'test-mongo-mutation')
12
- class NoDB
13
- include PopulateMe::Mongo::Plug
14
- def self.human_name; 'No DB'; end
15
- end
16
- DB = MONGO.database
17
-
18
- class Naked; include PopulateMe::Mongo::Plug; end
19
-
20
- class Person
21
- include PopulateMe::Mongo::Plug
22
- slot "name" # no options
23
- slot "surname"
24
- slot "age", :type=>:integer, :default=>18
25
- image_slot "portrait"
26
- slot 'subscribed_on', :type=>:date, :default=>proc{Time.now}
27
- end
28
-
29
- class Address
30
- include PopulateMe::Mongo::Plug
31
- slot "body"
32
- end
33
-
34
- class Article
35
- include PopulateMe::Mongo::Plug
36
- slot 'title'
37
- slot 'content', :type=>:text
38
- image_slot
39
- end
40
-
41
- class FeatureBox
42
- include PopulateMe::Mongo::Plug
43
- slot 'header'
44
- self.label_column = 'header'
45
- def self.human_plural_name; 'Feature Boxes'; end
46
- end
47
-
48
- describe "PopulateMe::Mongo::Mutation" do
49
-
50
- describe ".db" do
51
- it "Should be set to DB constant by default" do
52
- NoDB.db.should==nil
53
- Naked.db.should==DB
54
- end
55
- end
56
-
57
- shared "Empty Hash" do
58
- it "Should be set to an empty hash by default" do
59
- @bson.class.should==Hash
60
- @bson.empty?.should==true
61
- end
62
- end
63
-
64
- describe ".schema" do
65
- before { @bson = Naked.schema }
66
- behaves_like "Empty Hash"
67
- end
68
-
69
- describe ".relationships" do
70
- before { @bson = Naked.relationships }
71
- behaves_like "Empty Hash"
72
- end
73
-
74
- describe ".human_name" do
75
- it "Returns a legible version of the class name - override when incorrect" do
76
- Article.human_name.should=='Article'
77
- FeatureBox.human_name.should=='Feature Box'
78
- # No accronym for simplicity
79
- # Easier to override when needed
80
- NoDB.human_name.should=='No DB'
81
- end
82
- end
83
-
84
- describe ".human_plural_name" do
85
- it "Only adds an 's' to human name - override if needed" do
86
- Article.human_plural_name.should=='Articles'
87
- # No rules for simplicity
88
- # Easier to override when needed
89
- FeatureBox.human_plural_name.should=='Feature Boxes'
90
- # Here only .human_name was overridden
91
- NoDB.human_plural_name.should=='No DBs'
92
- end
93
- end
94
-
95
- describe ".ref" do
96
- it 'Returns a selector for a BSON::ObjectId' do
97
- id = BSON::ObjectId.new
98
- Address.ref(id).should=={'_id'=>id}
99
- end
100
- it 'Makes the argument a BSON::ObjectId if it is a valid string' do
101
- string_id = '000000000000000000000000'
102
- BSON::ObjectId.legal?(string_id).should==true
103
- Address.ref(string_id).should=={'_id'=>BSON::ObjectId.from_string(string_id)}
104
- end
105
- it 'Makes a selector for multiple docs if argument is an Array' do
106
- Address.ref([]).should=={'_id'=>{'$in'=>[]}}
107
- id = BSON::ObjectId.new
108
- string_id = '000000000000000000000000'
109
- Address.ref([id,string_id]).should=={'_id'=>{'$in'=>[id,BSON::ObjectId.from_string(string_id)]}}
110
- end
111
- it 'Just put an empty string in selector for any invalid argument' do
112
- Address.ref('abc').should=={'_id'=>''}
113
- end
114
- end
115
-
116
- shared "Basic slot" do
117
- it "Adds the declared slot to the schema" do
118
- @klass.schema.key?(@key).should==true
119
- end
120
- it "Defines getters and setters" do
121
- @klass.new.respond_to?(@key).should==true
122
- @klass.new.respond_to?(@key+'=').should==true
123
- end
124
- end
125
-
126
- describe ".slot" do
127
- before { @klass = Person; @key = 'age' }
128
- behaves_like "Basic slot"
129
- it "Keeps the options in schema" do
130
- Person.schema['age'][:default].should==18
131
- Person.schema['age'][:type].should==:integer
132
- end
133
- it "Sets :type option to :string by default if not provided" do
134
- Person.schema['name'][:type].should==:string
135
- end
136
- end
137
-
138
- shared "Correctly typed" do
139
- it "Has the correct type" do
140
- @klass.schema[@key][:type].should==@type
141
- end
142
- end
143
-
144
- shared "Image slot" do
145
- describe "Reference slot" do
146
- before { @type = :attachment }
147
- behaves_like "Basic slot"
148
- behaves_like "Correctly typed"
149
- end
150
- describe "Tooltip slot" do
151
- before { @key = @key+'_tooltip'; @type = :string }
152
- behaves_like "Basic slot"
153
- behaves_like "Correctly typed"
154
- end
155
- describe "Alt text slot" do
156
- before { @key = @key+'_alternative_text'; @type = :string }
157
- behaves_like "Basic slot"
158
- behaves_like "Correctly typed"
159
- end
160
- end
161
-
162
- describe ".image_slot" do
163
- describe "Name provided" do
164
- before { @klass = Person; @key = 'portrait' }
165
- behaves_like "Image slot"
166
- end
167
- describe "Name not provided" do
168
- before { @klass = Article; @key = 'image' }
169
- behaves_like "Image slot"
170
- end
171
- end
172
-
173
- # .slug_column
174
- # .foreign_key_name
175
- # .collection
176
- # .find
177
- # .find_one
178
- # .count
179
- # .sorting_order
180
- # .sort
181
- # .get
182
- # .delete
183
- # .is_unique
184
- # .has_many
185
-
186
- shared "Has error recipient" do
187
- it "Has an empty recipent for errors" do
188
- @inst.errors.should=={}
189
- end
190
- end
191
-
192
- describe "#initialize" do
193
- describe "With fields" do
194
- before { @inst = Person.new({'age'=>42, 'name'=>'Bozo', 'car'=>'Jaguar'}) }
195
- it "Should be flagged as new if the doc has no _id yet" do
196
- @inst.new?.should==true
197
- end
198
- it "Should not be flagged as new if the doc has an _id" do
199
- @inst['_id'] = 'abc'
200
- @inst.new?.should==false
201
- end
202
- it "Should pass all keys to the doc" do
203
- @inst['name'].should=='Bozo'
204
- @inst['car'].should=='Jaguar'
205
- end
206
- behaves_like "Has error recipient"
207
- end
208
- describe "Fresh new one" do
209
- before { @inst = Person.new }
210
- it "Should be flagged as new" do
211
- @inst.new?.should==true
212
- end
213
- it "Has default values correctly set" do
214
- @inst['age'].should==18 # direct value
215
- @inst['subscribed_on'].class.should==Time # with proc
216
- end
217
- behaves_like "Has error recipient"
218
- end
219
- end
220
-
221
- describe "#model" do
222
- it "Is a shortcut for self.class" do
223
- Naked.new.model.should==Naked
224
- end
225
- end
226
-
227
- describe '#to_label' do
228
- it 'Uses a built-in list of slots to pick from for a label' do
229
- Person.new({'age'=>42, 'name'=>'Bozo', 'surname'=>'Montana', 'car'=>'Jaguar'}).to_label.should=='Montana'
230
- end
231
- it 'Uses an other slot declared with label_column=' do
232
- FeatureBox.new({'header'=>'Glamour'}).to_label.should=='Glamour'
233
- end
234
- end
235
-
236
- describe '#auto_slug' do
237
- it 'Should build a url friendly slug based on #to_label' do
238
- FeatureBox.new({'header'=>"Así es la vida by Daniel Bär & Mickaël ? (100%)"}).auto_slug.should=='Asi-es-la-vida-by-Daniel-Bar-and-Mickael-100%25'
239
- end
240
- end
241
-
242
- # #default_doc
243
- # #id
244
- # #[]
245
- # #[]=
246
- # #auto_slug
247
- # #to_slug
248
- # #to_param
249
- # #field_id_for
250
- # #resolve_class
251
- # #parent
252
- # #slot_children
253
- # #first_slot_child
254
- # #children
255
- # #first_child
256
- # #children_count
257
- # #delete
258
- # #new?
259
- # #update_doc
260
- # #errors_on
261
- # #valid?
262
- # Hooks
263
- # Validation
264
- # Fix types
265
- # #save
266
-
267
- describe 'CursorMutation' do
268
- it 'Should give the correct class of object on iterations' do
269
- Address.new('body'=>'42').save
270
- Address.find.each do |a|
271
- a.model.name.should=='Address'
272
- end
273
- end
274
- end
275
-
276
- end
277
-
278
- DB.drop
279
-