locomotive_cms 0.0.1.4 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. data/Gemfile +4 -2
  2. data/app/controllers/admin/api_contents_controller.rb +30 -0
  3. data/app/controllers/admin/base_controller.rb +2 -2
  4. data/app/controllers/admin/content_types_controller.rb +1 -1
  5. data/app/controllers/admin/custom_fields_controller.rb +33 -0
  6. data/app/controllers/admin/my_accounts_controller.rb +2 -2
  7. data/app/controllers/admin/sites_controller.rb +2 -2
  8. data/app/helpers/admin/accounts_helper.rb +1 -1
  9. data/app/helpers/admin/custom_fields_helper.rb +1 -1
  10. data/app/models/asset.rb +2 -1
  11. data/app/models/asset_collection.rb +2 -2
  12. data/app/models/content_instance.rb +7 -0
  13. data/app/models/content_type.rb +1 -0
  14. data/app/models/page_part.rb +4 -4
  15. data/app/models/site.rb +1 -1
  16. data/app/models/theme_asset.rb +2 -0
  17. data/app/uploaders/asset_uploader.rb +2 -2
  18. data/app/views/admin/asset_collections/edit.html.haml +6 -3
  19. data/app/views/admin/content_types/_form.html.haml +10 -5
  20. data/app/views/admin/content_types/edit.html.haml +3 -1
  21. data/app/views/admin/content_types/new.html.haml +2 -0
  22. data/app/views/admin/contents/_form.html.haml +12 -2
  23. data/app/views/admin/current_sites/_form.html.haml +1 -1
  24. data/app/views/admin/custom_fields/_edit_field.html.haml +9 -0
  25. data/app/views/admin/{shared/_custom_fields.html.haml → custom_fields/_index.html.haml} +14 -4
  26. data/app/views/admin/custom_fields/edit_category.html.haml +43 -0
  27. data/app/views/admin/pages/_form.html.haml +1 -1
  28. data/app/views/admin/passwords/edit.html.haml +2 -2
  29. data/app/views/admin/passwords/new.html.haml +2 -2
  30. data/app/views/admin/sessions/new.html.haml +1 -1
  31. data/app/views/admin/shared/_head.html.haml +1 -1
  32. data/app/views/admin/shared/_header.html.haml +2 -2
  33. data/app/views/admin/sites/_form.html.haml +1 -1
  34. data/app/views/admin/theme_assets/images.html.haml +7 -7
  35. data/app/views/devise/mailer/reset_password_instructions.html.haml +1 -1
  36. data/config/application.rb +4 -3
  37. data/config/boot.rb +3 -14
  38. data/config/initializers/locomotive.rb +1 -0
  39. data/config/initializers/mongoid.rb +11 -12
  40. data/config/initializers/secret_token.rb +7 -0
  41. data/config/locales/admin_ui_en.yml +113 -4
  42. data/config/routes.rb +6 -8
  43. data/lib/locomotive/configuration.rb +2 -1
  44. data/lib/locomotive/liquid/drops/contents.rb +11 -13
  45. data/lib/locomotive/liquid/drops/javascripts.rb +1 -1
  46. data/lib/locomotive/liquid/tags/paginate.rb +1 -1
  47. data/lib/locomotive/render.rb +1 -1
  48. data/lib/locomotive/routing/site_dispatcher.rb +2 -1
  49. data/lib/locomotive.rb +3 -1
  50. data/lib/misc_form_builder.rb +10 -0
  51. data/public/images/admin/form/big_item-popup.png +0 -0
  52. data/public/images/admin/form/footer-popup.png +0 -0
  53. data/public/images/admin/form/header-popup.png +0 -0
  54. data/public/images/admin/form/icons/edit.png +0 -0
  55. data/public/images/admin/form/item-popup.png +0 -0
  56. data/public/images/admin/list/none-small.png +0 -0
  57. data/public/javascripts/admin/application.js +3 -2
  58. data/public/javascripts/admin/content_types.js +1 -1
  59. data/public/javascripts/admin/contents.js +11 -1
  60. data/public/javascripts/admin/custom_fields/category.js +91 -0
  61. data/public/javascripts/admin/custom_fields.js +27 -0
  62. data/public/javascripts/admin/page_parts.js +10 -5
  63. data/public/javascripts/admin/pages.js +1 -1
  64. data/public/javascripts/admin/snippets.js +1 -1
  65. data/public/javascripts/admin/theme_assets.js +2 -0
  66. data/public/javascripts/admin/utils.js +9 -0
  67. data/public/javascripts/all.js +14 -2
  68. data/public/stylesheets/admin/application.css +2 -2
  69. data/public/stylesheets/admin/box.css +80 -4
  70. data/public/stylesheets/admin/formtastic_changes.css +7 -2
  71. data/public/stylesheets/all.css +6 -1
  72. data/spec/lib/locomotive/render_spec.rb +2 -2
  73. data/spec/models/asset_collections_spec.rb +4 -4
  74. data/spec/spec_helper.rb +1 -1
  75. data/spec/support/locomotive.rb +1 -1
  76. data/vendor/plugins/custom_fields/Gemfile +11 -0
  77. data/vendor/plugins/custom_fields/README +2 -2
  78. data/vendor/plugins/custom_fields/Rakefile +23 -17
  79. data/vendor/plugins/custom_fields/lib/custom_fields/custom_fields_for.rb +2 -1
  80. data/vendor/plugins/custom_fields/lib/custom_fields/extensions/mongoid/associations/embeds_many.rb +20 -13
  81. data/vendor/plugins/custom_fields/lib/custom_fields/extensions/mongoid/associations/has_many_related.rb +33 -0
  82. data/vendor/plugins/custom_fields/lib/custom_fields/extensions/mongoid/associations/proxy.rb +20 -0
  83. data/vendor/plugins/custom_fields/lib/custom_fields/extensions/mongoid/document.rb +14 -21
  84. data/vendor/plugins/custom_fields/lib/custom_fields/{custom_field.rb → field.rb} +25 -23
  85. data/vendor/plugins/custom_fields/lib/custom_fields/proxy_class_enabler.rb +37 -0
  86. data/vendor/plugins/custom_fields/lib/custom_fields/types/category.rb +73 -0
  87. data/vendor/plugins/custom_fields/lib/custom_fields/types/default.rb +18 -0
  88. data/vendor/plugins/custom_fields/lib/custom_fields.rb +9 -1
  89. data/vendor/plugins/custom_fields/spec/integration/custom_fields_for_spec.rb +28 -0
  90. data/vendor/plugins/custom_fields/spec/integration/types/category_spec.rb +26 -0
  91. data/vendor/plugins/custom_fields/spec/models/person.rb +10 -0
  92. data/vendor/plugins/custom_fields/spec/models/project.rb +16 -0
  93. data/vendor/plugins/custom_fields/spec/models/task.rb +10 -0
  94. data/vendor/plugins/custom_fields/spec/spec_helper.rb +31 -0
  95. data/vendor/plugins/custom_fields/spec/unit/custom_field_spec.rb +42 -0
  96. data/vendor/plugins/custom_fields/spec/unit/custom_fields_for_spec.rb +106 -0
  97. data/vendor/plugins/custom_fields/spec/unit/proxy_class_enabler_spec.rb +25 -0
  98. data/vendor/plugins/custom_fields/spec/unit/types/category_spec.rb +97 -0
  99. metadata +83 -35
  100. data/app/views/devise/confirmations/new.html.haml +0 -12
  101. data/app/views/devise/registrations/edit.html.haml +0 -35
  102. data/app/views/devise/registrations/new.html.haml +0 -20
  103. data/app/views/devise/sessions/new.html.haml +0 -22
  104. data/app/views/devise/shared/_links.haml +0 -20
  105. data/app/views/devise/unlocks/new.html.haml +0 -12
  106. data/vendor/plugins/custom_fields/install.rb +0 -1
@@ -23,7 +23,7 @@ $(document).ready(function() {
23
23
  $(parts).each(function() {
24
24
  // console.log("iterating..." + this.slug);
25
25
  var control = $('#control-part-' + this.slug);
26
-
26
+
27
27
  // adding missing part
28
28
  if (control.size() == 0) {
29
29
  // console.log('adding part');
@@ -42,10 +42,15 @@ $(document).ready(function() {
42
42
  var wrapper = $('#parts-' + index);
43
43
 
44
44
  // updating part
45
- control.html('<span>' + this.name + '</span>').addClass('enabled').show();
46
- wrapper.find('input.disabled').val('false');
47
- wrapper.show();
48
- }
45
+ wrapper.find('input.disabled').val(this.disabled == true ? 'true' : 'false');
46
+ if (this.disabled == false) {
47
+ control.html('<span>' + this.name + '</span>').addClass('enabled').show();
48
+ wrapper.show();
49
+ } else {
50
+ control.hide();
51
+ wrapper.hide();
52
+ }
53
+ }
49
54
  });
50
55
 
51
56
  // removing or hiding parts
@@ -38,7 +38,7 @@ $(document).ready(function() {
38
38
 
39
39
  if (!slug.hasClass('filled')) {
40
40
  setTimeout(function() {
41
- slug.val(input.val().replace(/\s/g, '_').toLowerCase()).addClass('touched');
41
+ slug.val(makeSlug(input.val())).addClass('touched');
42
42
  }, 50);
43
43
  }
44
44
  });
@@ -7,7 +7,7 @@ $(document).ready(function() {
7
7
 
8
8
  if (!slug.hasClass('filled')) {
9
9
  setTimeout(function() {
10
- slug.val(input.val().replace(/\s/g, '_').toLowerCase());
10
+ slug.val(makeSlug(input.val()));
11
11
  }, 50);
12
12
  }
13
13
  });
@@ -71,6 +71,8 @@ var setupUploader = function() {
71
71
 
72
72
  asset.removeClass('new-asset');
73
73
 
74
+ $('.asset-picker p.no-items').hide();
75
+
74
76
  $('.asset-picker ul').scrollTo($('li.asset:last'), 400);
75
77
  }
76
78
  });
@@ -0,0 +1,9 @@
1
+ function makeSlug(val, sep) { // code largely inspired by http://www.thewebsitetailor.com/jquery-slug-plugin/
2
+ if (typeof sep == 'undefined') sep = '_';
3
+ var alphaNumRegexp = new RegExp('[^a-zA-Z0-9\\' + sep + ']', 'g');
4
+ var avoidDuplicateRegexp = new RegExp('[\\' + sep + ']{2,}', 'g');
5
+ val = val.replace(/\s/g, sep);
6
+ val = val.replace(alphaNumRegexp, '');
7
+ val = val.replace(avoidDuplicateRegexp, sep);
8
+ return val.toLowerCase();
9
+ }
@@ -687,6 +687,17 @@ jQuery(function ($) {
687
687
 
688
688
 
689
689
 
690
+ function makeSlug(val, sep) { // code largely inspired by http://www.thewebsitetailor.com/jquery-slug-plugin/
691
+ if (typeof sep == 'undefined') sep = '_';
692
+ var alphaNumRegexp = new RegExp('[^a-zA-Z0-9\\' + sep + ']', 'g');
693
+ var avoidDuplicateRegexp = new RegExp('[\\' + sep + ']{2,}', 'g');
694
+ val = val.replace(/\s/g, sep);
695
+ val = val.replace(alphaNumRegexp, '');
696
+ val = val.replace(avoidDuplicateRegexp, sep);
697
+ return val.toLowerCase();
698
+ }
699
+
700
+
690
701
  /**
691
702
  *
692
703
  * Copyright (c) 2009 Tony Dewan (http://www.tonydewan.com/)
@@ -1059,15 +1070,16 @@ $.growl.settings.dockCss = {
1059
1070
  /* ___ codemirror ___ */
1060
1071
 
1061
1072
  var addCodeMirrorEditor = function(type, el, parser) {
1073
+ if (type == 'liquid') type = 'xml';
1062
1074
  var parserfile = "parse" + type + ".js";
1063
- if (parser != undefined) parserfile = parser;
1064
- // if (type == 'liquid') type = 'xml';
1075
+ if (parser != undefined) parserfile = parser;
1065
1076
 
1066
1077
  var editor = CodeMirror.fromTextArea(el.attr('id'), {
1067
1078
  height: "400px",
1068
1079
  parserfile: parserfile,
1069
1080
  stylesheet: [
1070
1081
  "/stylesheets/admin/plugins/codemirror/csscolors.css",
1082
+ "/stylesheets/admin/plugins/codemirror/xmlcolors.css",
1071
1083
  "/stylesheets/admin/plugins/codemirror/javascriptcolors.css",
1072
1084
  "/stylesheets/admin/plugins/codemirror/liquidcolors.css"],
1073
1085
  path: "/javascripts/admin/plugins/codemirror/",
@@ -149,7 +149,7 @@ ul.assets li.asset div.image div.inside {
149
149
 
150
150
  ul.assets li.asset div.actions {
151
151
  position: absolute;
152
- top: 8px;
152
+ top: 4px;
153
153
  right: 12px;
154
154
  }
155
155
 
@@ -234,7 +234,7 @@ div#uploadAssetsInputQueue { display: none; }
234
234
 
235
235
  #pages-list li .more {
236
236
  position: absolute;
237
- top: 3px;
237
+ top: 6px;
238
238
  right: 20px;
239
239
  font-size: 0.7em;
240
240
  color: #8b8d9a;
@@ -1,8 +1,10 @@
1
1
  /* custom styles for fancybox */
2
2
 
3
- div.asset-picker { width: 470px; position: relative; }
4
- div.asset-picker .actions { position: absolute; right: 4px; top: 0px; }
5
- div.asset-picker h2 {
3
+ /* ___ common ___ */
4
+
5
+ .box-wrapper { display: none; }
6
+
7
+ #fancybox-inner h2 {
6
8
  border-bottom:1px dotted #BBBBBD;
7
9
  color:#1E1F26;
8
10
  font-size:1.1em;
@@ -10,5 +12,79 @@ div.asset-picker h2 {
10
12
  padding-bottom:10px;
11
13
  }
12
14
 
15
+ #fancybox-inner form.formtastic legend span {
16
+ background-image: url("/images/admin/form/header-popup.png");
17
+ width: 453px;
18
+ }
19
+
20
+ #fancybox-inner form.formtastic ol {
21
+ background-image: url("/images/admin/form/footer-popup.png");
22
+ }
23
+
24
+ #fancybox-inner form.formtastic .editable-list ol {
25
+ width: 433px;
26
+ }
27
+
28
+ #fancybox-inner form.formtastic .editable-list li {
29
+ width: 413px;
30
+ }
31
+
32
+ #fancybox-inner form.formtastic .editable-list li {
33
+ background-image: url("/images/admin/form/item-popup.png");
34
+ }
35
+
36
+ #fancybox-inner form.formtastic .editable-list li.template {
37
+ background-image: url("/images/admin/form/big_item-popup.png");
38
+ }
39
+
40
+ #fancybox-inner p { color:#8B8D9A; font-size:0.8em; }
41
+
42
+ /* ___ asset picker ___ */
43
+
44
+ div.asset-picker { width: 470px; position: relative; }
45
+ div.asset-picker .actions { position: absolute; right: 4px; top: 0px; }
46
+
47
+ div.asset-picker p.no-items { background-image: url("/images/admin/list/none-small.png"); }
48
+
13
49
  div.asset-picker ul { overflow: auto; height: 471px; }
14
- div.asset-picker ul li.new-asset { display: none; }
50
+ div.asset-picker ul li.new-asset { display: none; }
51
+
52
+ /* ___ custom fields ___ */
53
+
54
+ #edit-custom-field {
55
+ width: 473px;
56
+ }
57
+
58
+ #edit-custom-field-category {
59
+ width: 493px;
60
+ }
61
+
62
+ #edit-custom-field-category .inner {
63
+ padding: 10px 10px 61px 10px;
64
+ }
65
+
66
+ /* ___ form action ___ */
67
+
68
+ #fancybox-inner .popup-actions {
69
+ position: absolute;
70
+ left: 0px;
71
+ bottom: 0px;
72
+ height: 61px;
73
+ width: 100%;
74
+ background: #8b8d9a;
75
+ }
76
+
77
+ #fancybox-inner .popup-actions p {
78
+ padding: 15px;
79
+ margin: 0px;
80
+ text-align: right;
81
+ }
82
+
83
+ /*#fancybox-inner .actions a {
84
+ color: #fff;
85
+ text-decoration: none;
86
+ font-size: 0.8em;
87
+ position: relative;
88
+ top: 4px;
89
+ }*/
90
+
@@ -224,10 +224,11 @@ form.formtastic fieldset ol li.item em {
224
224
 
225
225
  form.formtastic fieldset ol li.item span.actions {
226
226
  position: absolute;
227
- top: 7px;
227
+ top: 5px;
228
228
  right: 10px;
229
- width: 16px;
229
+ width: 50px;
230
230
  height: 16px;
231
+ text-align:right;
231
232
  }
232
233
 
233
234
  /* ___ editable-list (content type fields and validations) ___ */
@@ -338,6 +339,10 @@ form.formtastic fieldset.editable-list ol li.template span.actions {
338
339
  top: 10px;
339
340
  }
340
341
 
342
+ form.formtastic fieldset.editable-list ol li.template span.actions a.edit {
343
+ display: none;
344
+ }
345
+
341
346
  form.formtastic fieldset.editable-list ol li.template span.actions a.remove {
342
347
  display: none;
343
348
  }
@@ -896,8 +896,9 @@ form.formtastic fieldset ol li.item span.actions {
896
896
  position: absolute;
897
897
  top: 7px;
898
898
  right: 10px;
899
- width: 16px;
899
+ width: 50px;
900
900
  height: 16px;
901
+ text-align:right;
901
902
  }
902
903
 
903
904
  /* ___ editable-list (content type fields and validations) ___ */
@@ -1008,6 +1009,10 @@ form.formtastic fieldset.editable-list ol li.template span.actions {
1008
1009
  top: 10px;
1009
1010
  }
1010
1011
 
1012
+ form.formtastic fieldset.editable-list ol li.template span.actions a.edit {
1013
+ display: none;
1014
+ }
1015
+
1011
1016
  form.formtastic fieldset.editable-list ol li.template span.actions a.remove {
1012
1017
  display: none;
1013
1018
  }
@@ -61,7 +61,7 @@ describe 'Locomotive rendering system' do
61
61
 
62
62
  before(:each) do
63
63
  @page.published = false
64
- @controller.current_account = nil
64
+ @controller.current_admin = nil
65
65
  end
66
66
 
67
67
  it 'should return the 404 page if the page has not been published yet' do
@@ -72,7 +72,7 @@ describe 'Locomotive rendering system' do
72
72
  end
73
73
 
74
74
  it 'should not return the 404 page if the page has not been published yet and admin is logged in' do
75
- @controller.current_account = true
75
+ @controller.current_admin = true
76
76
  @controller.request.fullpath = '/contact'
77
77
  @controller.current_site.pages.expects(:where).with({ :fullpath => 'contact' }).returns([@page])
78
78
  @controller.send(:locomotive_page).should == @page
@@ -20,7 +20,7 @@ describe AssetCollection do
20
20
  context 'unit' do
21
21
 
22
22
  before(:each) do
23
- @field = CustomFields::CustomField.new(:kind => 'String')
23
+ @field = CustomFields::Field.new(:kind => 'String')
24
24
  end
25
25
 
26
26
  it 'should tell if it is a String' do
@@ -66,8 +66,8 @@ describe AssetCollection do
66
66
  end
67
67
 
68
68
  it 'should have an unique alias' do
69
- @collection.asset_custom_fields.first._alias.should == "description"
70
- @collection.asset_custom_fields.last._alias.should == "active"
69
+ @collection.asset_custom_fields.first.safe_alias.should == "description"
70
+ @collection.asset_custom_fields.last.safe_alias.should == "active"
71
71
  end
72
72
 
73
73
  end
@@ -164,7 +164,7 @@ describe AssetCollection do
164
164
  end
165
165
 
166
166
  end
167
-
167
+
168
168
  end
169
169
 
170
170
  def build_asset(collection)
data/spec/spec_helper.rb CHANGED
@@ -12,6 +12,6 @@ Rspec.configure do |config|
12
12
  config.mock_with :mocha
13
13
 
14
14
  config.before(:each) do
15
- Mongoid.master.collections.each(&:drop)
15
+ Mongoid.master.collections.select { |c| c.name != 'system.indexes' }.each(&:drop)
16
16
  end
17
17
  end
@@ -7,7 +7,7 @@ module Locomotive
7
7
 
8
8
  include Locomotive::Render
9
9
 
10
- attr_accessor :output, :current_site, :current_account
10
+ attr_accessor :output, :current_site, :current_admin
11
11
 
12
12
  def render(options = {})
13
13
  self.output = options[:text]
@@ -0,0 +1,11 @@
1
+ source "http://gemcutter.org"
2
+
3
+ gem "bson_ext", ">= 1.0.1"
4
+ gem "mongo_ext"
5
+ gem "mongoid", ">= 2.0.0.beta6"
6
+ gem "activesupport", ">= 3.0.0.beta4"
7
+
8
+ group :test do
9
+ gem 'rspec', '>= 2.0.0.beta.10'
10
+ gem 'mocha', :git => 'git://github.com/floehopper/mocha.git'
11
+ end
@@ -1,4 +1,4 @@
1
- CustomField
1
+ CustomFields
2
2
  ===========
3
3
 
4
4
  Introduction goes here.
@@ -10,4 +10,4 @@ Example
10
10
  Example goes here.
11
11
 
12
12
 
13
- Copyright (c) 2010 [name of plugin creator], released under the MIT license
13
+ Copyright (c) 2010 [Didier Lafforgue], released under the MIT license
@@ -1,23 +1,29 @@
1
- require 'rake'
2
- require 'rake/testtask'
3
- require 'rake/rdoctask'
1
+ require "rubygems"
2
+ require "rake"
3
+ require "rake/rdoctask"
4
+ require "rspec"
5
+ require "rspec/core/rake_task"
4
6
 
5
- desc 'Default: run unit tests.'
6
- task :default => :test
7
-
8
- desc 'Test the custom_field plugin.'
9
- Rake::TestTask.new(:test) do |t|
10
- t.libs << 'lib'
11
- t.libs << 'test'
12
- t.pattern = 'test/**/*_test.rb'
13
- t.verbose = true
14
- end
15
-
16
- desc 'Generate documentation for the custom_field plugin.'
7
+ desc 'Generate documentation for the custom_fields plugin.'
17
8
  Rake::RDocTask.new(:rdoc) do |rdoc|
18
9
  rdoc.rdoc_dir = 'rdoc'
19
- rdoc.title = 'CustomField'
10
+ rdoc.title = 'CustomFields'
20
11
  rdoc.options << '--line-numbers' << '--inline-source'
21
12
  rdoc.rdoc_files.include('README')
22
13
  rdoc.rdoc_files.include('lib/**/*.rb')
23
- end
14
+ end
15
+
16
+ Rspec::Core::RakeTask.new('spec:unit') do |spec|
17
+ spec.pattern = "spec/unit/**/*_spec.rb"
18
+ # spec.pattern = "spec/unit/custom_fields_for_spec.rb"
19
+ # spec.pattern = "spec/unit/types/category_spec.rb"
20
+ end
21
+
22
+ Rspec::Core::RakeTask.new('spec:integration') do |spec|
23
+ spec.pattern = "spec/integration/**/*_spec.rb"
24
+ # spec.pattern = "spec/integration/types/category_spec.rb"
25
+ end
26
+
27
+ task :spec => ['spec:unit', 'spec:integration']
28
+
29
+ task :default => :spec
@@ -30,7 +30,7 @@ module CustomFields
30
30
  class_eval <<-EOV
31
31
  field :#{singular_name}_custom_fields_counter, :type => Integer, :default => 0
32
32
 
33
- embeds_many :#{singular_name}_custom_fields, :class_name => "::CustomFields::CustomField"
33
+ embeds_many :#{singular_name}_custom_fields, :class_name => "::CustomFields::Field"
34
34
 
35
35
  validates_associated :#{singular_name}_custom_fields
36
36
 
@@ -39,6 +39,7 @@ module CustomFields
39
39
  def ordered_#{singular_name}_custom_fields
40
40
  self.#{singular_name}_custom_fields.sort { |a, b| (a.position || 0) <=> (b.position || 0) }
41
41
  end
42
+
42
43
  EOV
43
44
  end
44
45
 
@@ -2,23 +2,30 @@
2
2
  module Mongoid #:nodoc:
3
3
  module Associations #:nodoc:
4
4
  class EmbedsMany < Proxy
5
- def build_with_custom_field_settings(attrs = {}, type = nil)
6
- document = build_without_custom_field_settings(attrs, type)
7
-
8
- if @association_name.ends_with?('_custom_fields')
9
- document.class_eval <<-EOV
10
- self.associations = {} # prevent associations to be nil
11
- embedded_in :#{@parent.class.to_s.underscore}, :inverse_of => :#{@association_name}
12
- EOV
5
+
6
+ def initialize_with_custom_fields(parent, options, target_array = nil)
7
+ if custom_fields?(parent, options.name)
8
+ options = options.clone # 2 parent instances should not share the exact same option instance
13
9
 
14
- document.send(:set_unique_name!)
15
- document.send(:set_alias)
10
+ custom_fields = parent.send(:"ordered_#{custom_fields_association_name(options.name)}")
11
+
12
+ klass = options.klass.to_klass_with_custom_fields(custom_fields)
13
+ klass._parent = parent
14
+ klass.association_name = options.name
15
+
16
+ options.instance_eval <<-EOF
17
+ def klass=(klass); @klass = klass; end
18
+ def klass; @klass || class_name.constantize; end
19
+ EOF
20
+
21
+ options.klass = klass
16
22
  end
17
- document
23
+
24
+ initialize_without_custom_fields(parent, options, target_array)
18
25
  end
19
26
 
20
- alias_method_chain :build, :custom_field_settings
27
+ alias_method_chain :initialize, :custom_fields
28
+
21
29
  end
22
-
23
30
  end
24
31
  end
@@ -0,0 +1,33 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Associations #:nodoc:
4
+ # Represents an relational one-to-many association with an object in a
5
+ # separate collection or database.
6
+ class HasManyRelated < Proxy
7
+
8
+ def initialize_with_custom_fields(parent, options, target_array = nil)
9
+ if custom_fields?(parent, options.name)
10
+ options = options.clone # 2 parent instances should not share the exact same option instance
11
+
12
+ custom_fields = parent.send(:"ordered_#{custom_fields_association_name(options.name)}")
13
+
14
+ klass = options.klass.to_klass_with_custom_fields(custom_fields)
15
+ klass._parent = parent
16
+ klass.association_name = options.name
17
+
18
+ options.instance_eval <<-EOF
19
+ def klass=(klass); @klass = klass; end
20
+ def klass; @klass || class_name.constantize; end
21
+ EOF
22
+
23
+ options.klass = klass
24
+ end
25
+
26
+ initialize_without_custom_fields(parent, options, target_array)
27
+ end
28
+
29
+ alias_method_chain :initialize, :custom_fields
30
+
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,20 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc
3
+ module Associations #:nodoc
4
+ class Proxy #:nodoc
5
+
6
+ def custom_fields_association_name(association_name)
7
+ "#{association_name.to_s.singularize}_custom_fields".to_sym
8
+ end
9
+
10
+ def custom_fields?(object, association_name)
11
+ object.respond_to?(custom_fields_association_name(association_name))
12
+ end
13
+
14
+ def klass
15
+ @klass
16
+ end
17
+
18
+ end
19
+ end
20
+ end
@@ -2,34 +2,27 @@
2
2
  module Mongoid #:nodoc:
3
3
  module Document
4
4
  module InstanceMethods
5
+
5
6
  def parentize_with_custom_fields(object, association_name)
7
+ if association_name.to_s.ends_with?('_custom_fields')
8
+ self.singleton_class.associations = {}
9
+ self.singleton_class.embedded_in object.class.to_s.underscore.to_sym, :inverse_of => association_name
10
+ end
11
+
6
12
  parentize_without_custom_fields(object, association_name)
7
13
 
8
- if self.custom_fields?(object, association_name)
9
- # puts "[parentize_with_custom_fields] association_name = #{association_name} / #{self.custom_fields_association_name(association_name)}"
10
- object.send(self.custom_fields_association_name(association_name)).each do |field|
11
- field.apply(self, association_name)
12
- end
13
-
14
- self.instance_eval <<-EOV
15
- def custom_fields
16
- fields = self._parent.send(:#{self.custom_fields_association_name(association_name)})
17
- fields.sort { |a, b| (a.position || 0) <=> (b.position || 0) }
18
- end
19
- EOV
14
+ if self.embedded? && self.instance_variable_get(:"@association_name").nil?
15
+ self.instance_variable_set(:"@association_name", association_name) # weird bug with proxy class
16
+ end
17
+
18
+ if association_name.to_s.ends_with?('_custom_fields')
19
+ self.send(:set_unique_name!)
20
+ self.send(:set_alias)
20
21
  end
21
22
  end
22
23
 
23
24
  alias_method_chain :parentize, :custom_fields
24
25
 
25
- def custom_fields_association_name(association_name)
26
- "#{association_name.to_s.singularize}_custom_fields".to_sym
27
- end
28
-
29
- def custom_fields?(object, association_name)
30
- object.respond_to?(custom_fields_association_name(association_name)) &&
31
- object.associations[association_name]
32
- end
33
- end
26
+ end
34
27
  end
35
28
  end
@@ -1,14 +1,19 @@
1
1
  module CustomFields
2
2
 
3
- class CustomField
4
- include Mongoid::Document
5
- include Mongoid::Timestamps
3
+ class Field
4
+ include ::Mongoid::Document
5
+ include ::Mongoid::Timestamps
6
+
7
+ # types ##
8
+ include Types::Default
9
+ include Types::Category
6
10
 
7
11
  ## fields ##
8
- field :label, :type => String
9
- field :_alias, :type => String # need it for instance in: > asset.description (description being a custom field)
10
- field :_name, :type => String
11
- field :kind, :type => String
12
+ field :label
13
+ field :_alias # need it for instance in: > asset.description (description being a custom field)
14
+ field :_name
15
+ field :kind
16
+ field :hint
12
17
  field :position, :type => Integer, :default => 0
13
18
 
14
19
  ## validations ##
@@ -17,7 +22,7 @@ module CustomFields
17
22
 
18
23
  ## methods ##
19
24
 
20
- %w{String Text Email Boolean Date File}.each do |kind|
25
+ %w{String Text Category}.each do |kind|
21
26
  define_method "#{kind.downcase}?" do
22
27
  self.kind == kind
23
28
  end
@@ -25,27 +30,25 @@ module CustomFields
25
30
 
26
31
  def field_type
27
32
  case self.kind
28
- when 'String', 'Text', 'Email' then String
33
+ when 'String', 'Text', 'Category' then String
29
34
  else
30
35
  self.kind.constantize
31
36
  end
32
37
  end
33
-
34
- def apply(object, association_name)
38
+
39
+ def apply(klass)
35
40
  return unless self.valid?
36
41
 
37
- # trick mongoid
38
- object.class_eval { def meta; (class << self; self; end); end }
39
- object.meta.fields = object.fields.clone
40
- object.meta.send(:define_method, :fields) { self.meta.fields }
42
+ klass.field self._name, :type => self.field_type
41
43
 
42
- object.meta.field self._name, :type => self.field_type
43
- object.class_eval <<-EOF
44
- alias :#{self.safe_alias} :#{self._name}
45
- alias :#{self.safe_alias}= :#{self._name}=
46
- EOF
44
+ case self.kind
45
+ when 'Category'
46
+ apply_category_type(klass)
47
+ else
48
+ apply_default_type(klass)
49
+ end
47
50
  end
48
-
51
+
49
52
  def safe_alias
50
53
  self.set_alias
51
54
  self._alias
@@ -66,8 +69,7 @@ module CustomFields
66
69
 
67
70
  def set_alias
68
71
  return if self.label.blank? && self._alias.blank?
69
- self._alias ||= self.label.clone
70
- self._alias.slugify!(:downcase => true, :underscore => true)
72
+ self._alias = (self._alias.blank? ? self.label : self._alias).parameterize('_').downcase
71
73
  end
72
74
 
73
75
  def increment_counter!