markdown_record 0.1.3 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +63 -43
  3. data/app/helpers/markdown_record/application_helper.rb +23 -0
  4. data/app/helpers/markdown_record/controller_helpers.rb +1 -1
  5. data/app/helpers/markdown_record/view_helpers.rb +9 -3
  6. data/{lib → app/models}/markdown_record/base.rb +10 -0
  7. data/{lib → app/models}/markdown_record/content_fragment.rb +17 -2
  8. data/lib/generators/markdown_record_generator.rb +6 -0
  9. data/lib/markdown_record/configuration.rb +4 -0
  10. data/lib/markdown_record/file_sorting/base.rb +25 -0
  11. data/lib/markdown_record/file_sorting/date_sorter.rb +14 -0
  12. data/lib/markdown_record/file_sorting/sem_ver_sorter.rb +47 -0
  13. data/lib/markdown_record/{association.rb → models/association.rb} +20 -3
  14. data/lib/markdown_record/{associations.rb → models/associations.rb} +17 -9
  15. data/lib/markdown_record/{content_associations.rb → models/content_associations.rb} +4 -2
  16. data/lib/markdown_record/models/filtering.rb +13 -0
  17. data/lib/markdown_record/models/filters/array_filter.rb +11 -0
  18. data/lib/markdown_record/models/filters/base_filter.rb +35 -0
  19. data/lib/markdown_record/models/filters/hash_filter.rb +81 -0
  20. data/lib/markdown_record/models/filters/nil_filter.rb +11 -0
  21. data/lib/markdown_record/models/filters/range_filter.rb +11 -0
  22. data/lib/markdown_record/models/filters/regexp_filter.rb +11 -0
  23. data/lib/markdown_record/models/filters/symbol_filter.rb +14 -0
  24. data/lib/markdown_record/models/filters.rb +22 -0
  25. data/lib/markdown_record/models/model_inflator.rb +65 -0
  26. data/lib/markdown_record/path_utilities.rb +20 -11
  27. data/lib/markdown_record/rendering/content_dsl/attribute.rb +22 -0
  28. data/lib/markdown_record/{content_dsl → rendering/content_dsl}/directory_fragment.rb +3 -3
  29. data/lib/markdown_record/{content_dsl → rendering/content_dsl}/disable.rb +2 -2
  30. data/lib/markdown_record/{content_dsl → rendering/content_dsl}/enable.rb +2 -2
  31. data/lib/markdown_record/{content_dsl → rendering/content_dsl}/end_attribute.rb +3 -3
  32. data/lib/markdown_record/{content_dsl → rendering/content_dsl}/end_model.rb +3 -3
  33. data/lib/markdown_record/{content_dsl → rendering/content_dsl}/fragment.rb +3 -3
  34. data/lib/markdown_record/rendering/content_dsl/model.rb +22 -0
  35. data/lib/markdown_record/rendering/content_dsl/scope.rb +22 -0
  36. data/lib/markdown_record/{content_dsl → rendering/content_dsl}/use_layout.rb +3 -3
  37. data/lib/markdown_record/rendering/content_dsl.rb +45 -0
  38. data/lib/markdown_record/rendering/html_renderer.rb +22 -0
  39. data/lib/markdown_record/{indexer.rb → rendering/indexer.rb} +0 -10
  40. data/lib/markdown_record/rendering/json_renderer.rb +20 -0
  41. data/lib/markdown_record/rendering/nodes/html_base.rb +95 -0
  42. data/lib/markdown_record/rendering/nodes/html_directory.rb +51 -0
  43. data/lib/markdown_record/rendering/nodes/html_file.rb +48 -0
  44. data/lib/markdown_record/rendering/nodes/json_base.rb +55 -0
  45. data/lib/markdown_record/rendering/nodes/json_directory.rb +69 -0
  46. data/lib/markdown_record/rendering/nodes/json_file.rb +172 -0
  47. data/lib/markdown_record/{rendering.rb → rendering/rendering.rb} +1 -1
  48. data/lib/markdown_record/{validator.rb → rendering/validator.rb} +4 -4
  49. data/lib/markdown_record/version.rb +1 -1
  50. data/lib/markdown_record.rb +21 -14
  51. data/templates/demo/content/10_custom_models_and_associations.md.erb +27 -7
  52. data/templates/demo/content/11_controller_helpers.md.erb +2 -2
  53. data/templates/demo/content/12_configuration.md.erb +22 -3
  54. data/templates/demo/content/13_sandbox/1_foo.md +2 -1
  55. data/templates/demo/content/13_sandbox/2_sandbox_nested/1_bar.md +4 -1
  56. data/templates/demo/content/1_home.md.erb +30 -13
  57. data/templates/demo/content/2_installation.md.erb +61 -46
  58. data/templates/demo/content/3_rendering_basics.md.erb +3 -3
  59. data/templates/demo/content/4_content_dsl.md.erb +22 -11
  60. data/templates/demo/content/5_routes.md.erb +10 -7
  61. data/templates/demo/content/6_model_basics.md.erb +11 -11
  62. data/templates/demo/content/7_content_frags.md.erb +9 -6
  63. data/templates/demo/content/8_erb_syntax_and_view_helpers.md.erb +32 -11
  64. data/templates/demo/content/9_layouts.md.erb +3 -3
  65. data/templates/demo/layouts/_global_layout.html.erb +1 -0
  66. data/templates/demo/models/dsl_command.rb +6 -0
  67. data/templates/demo/models/section.rb +5 -0
  68. data/templates/render_content.thor +2 -1
  69. data/templates/tests/assets/images/ruby-logo.png +0 -0
  70. data/templates/tests/content/1_test_files_home.md.erb +31 -0
  71. data/templates/tests/content/2_content_dsl_tests/1_content_dsl.md.erb +162 -0
  72. data/templates/tests/content/2_content_dsl_tests/2_nested_directory/1_associations.md.erb +83 -0
  73. data/templates/tests/layouts/_concatenated_layout.html.erb +12 -0
  74. data/templates/tests/layouts/_custom_layout.html.erb +14 -0
  75. data/templates/tests/layouts/_file_layout.html.erb +15 -0
  76. data/templates/tests/layouts/_global_layout.html.erb +116 -0
  77. metadata +53 -34
  78. data/app/models/markdown_record/demo/dsl_command.rb +0 -10
  79. data/app/models/markdown_record/demo/section.rb +0 -9
  80. data/app/models/markdown_record/tests/child_model.rb +0 -15
  81. data/app/models/markdown_record/tests/fake_active_record_model.rb +0 -13
  82. data/app/models/markdown_record/tests/model.rb +0 -15
  83. data/app/models/markdown_record/tests/other_child_model.rb +0 -15
  84. data/lib/markdown_record/cli.rb +0 -54
  85. data/lib/markdown_record/content_dsl/attribute.rb +0 -22
  86. data/lib/markdown_record/content_dsl/model.rb +0 -23
  87. data/lib/markdown_record/content_dsl/render_format.rb +0 -22
  88. data/lib/markdown_record/content_dsl/render_strategy.rb +0 -22
  89. data/lib/markdown_record/content_dsl.rb +0 -37
  90. data/lib/markdown_record/html_renderer.rb +0 -194
  91. data/lib/markdown_record/json_renderer.rb +0 -270
  92. data/lib/markdown_record/model_inflator.rb +0 -107
  93. data/lib/markdown_record/routes_renderer.rb +0 -0
  94. /data/lib/markdown_record/{file_saver.rb → rendering/file_saver.rb} +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5cf70bc7bfe4be124645f86a8182c31f2026a5c8c1736b79852e1ca17981b835
4
- data.tar.gz: 7ff16d507f7fec68fcf09ecebfa7012cf5c8e700f4ebe74d73e163b83a02cea4
3
+ metadata.gz: 269413176d8f175aac4611a05b3e877a8f6e35e8d2578693a61b8137ba3e468c
4
+ data.tar.gz: 9bd2e4bbcfd47f25d95bd89cee4fa55ef702ef12c1c02b3ffb3def240210f034
5
5
  SHA512:
6
- metadata.gz: 4f28579beda2d8605428020e04db510d9df937513560e5c1c8fb0768767e43573f785584316c7c5748516d9d4881ce0b32db1430a8f658906486af634daf110f
7
- data.tar.gz: 5882b40b524c9a121aac21ef9adadc32868e1138c92adc47e8dfbbadc84e71e130526831f3e0a78148f9a04298cdecbae8ac068334542ea788e38d3a0fe16676
6
+ metadata.gz: cfa28a6d993347abcc68d6a0d28163ea238c67516bb82b0293e4bb1779499db6ac027b508c1c56c9edd88136a6310ee9a3d265226bee2e966e629e8f8e6389c4
7
+ data.tar.gz: 1ffc583808ddd0886ec481997b52f36fabfeb457bb3c7447c58e3dabd40558111141ec3372634ae5da8a334ce2caec650b2ef7319dfc4334538215dc6c247d19
data/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  Welcome to MarkdownRecord. This project is still in BETA stage, and as such is subject to rapid change. There are many things that still need improving, so bear that in mind. That said, please feel free to test this project out and provide feedback in the form of GitHub issues! Thank you.
4
4
 
5
+ You can find the complete usage guide [here](https://markdown-record-docs.herokuapp.com/).
6
+
5
7
  MarkdownRecord is a Rails engine that allows you to write markdown with embedded json like this:
6
8
 
7
9
  ```md
@@ -100,19 +102,24 @@ The above command will install the engine, resulting in the following output and
100
102
  create markdown_record/content
101
103
  create markdown_record/layouts
102
104
  create markdown_record/rendered
105
+ exist app/models
106
+ identical app/models/dsl_command.rb
107
+ identical app/models/section.rb
103
108
  exist markdown_record/content
104
- create markdown_record/content/controller_helpers.md.erb
105
- create markdown_record/content/configuration.md.erb
106
- create markdown_record/content/sandbox/foo.md
107
- create markdown_record/content/home.md.erb
108
- create markdown_record/content/installation.md.erb
109
- create markdown_record/content/rendering_basics.md.erb
110
- create markdown_record/content/content_dsl.md.erb
111
- create markdown_record/content/routes.md.erb
112
- create markdown_record/content/model_basics.md.erb
113
- create markdown_record/content/content_frags.md.erb
114
- create markdown_record/content/erb_syntax_and_view_helpers.md.erb
115
- create markdown_record/content/custom_models_and_associations.md.erb
109
+ create markdown_record/content/10_custom_models_and_associations.md.erb
110
+ create markdown_record/content/11_controller_helpers.md.erb
111
+ create markdown_record/content/12_configuration.md.erb
112
+ create markdown_record/content/13_sandbox/1_foo.md
113
+ create markdown_record/content/13_sandbox/2_sandbox_nested/1_bar.md
114
+ create markdown_record/content/1_home.md.erb
115
+ create markdown_record/content/2_installation.md.erb
116
+ create markdown_record/content/3_rendering_basics.md.erb
117
+ create markdown_record/content/4_content_dsl.md.erb
118
+ create markdown_record/content/5_routes.md.erb
119
+ create markdown_record/content/6_model_basics.md.erb
120
+ create markdown_record/content/7_content_frags.md.erb
121
+ create markdown_record/content/8_erb_syntax_and_view_helpers.md.erb
122
+ create markdown_record/content/9_layouts.md.erb
116
123
  exist markdown_record/layouts
117
124
  create markdown_record/layouts/_concatenated_layout.html.erb
118
125
  create markdown_record/layouts/_custom_layout.html.erb
@@ -124,6 +131,7 @@ The above command will install the engine, resulting in the following output and
124
131
  create Thorfile
125
132
  create lib/tasks/render_content.thor
126
133
  gsub config/routes.rb
134
+ gsub config/routes.rb
127
135
  ```
128
136
 
129
137
  The files and folders inside `markdown_record/content` are for demo purposes only, and can be deleted once you are ready to create your own content.
@@ -146,56 +154,67 @@ You should see the following output:
146
154
 
147
155
  ```bash
148
156
  ---------------------------------------------------------------
149
- rendering html and json content with options {:concat=>true, :deep=>true, :save=>true, :layout=>"_concatenated_layout.html.erb", :render_content_fragment_json=>true} ...
157
+ rendering html and json content with options {:concat=>true, :deep=>true, :save=>true, :render_content_fragment_json=>true} ...
150
158
  ---------------------------------------------------------------
151
159
  rendered: /markdown_record/rendered/content_fragments.json
152
160
  rendered: /markdown_record/rendered/content.json
153
- rendered: /markdown_record/rendered/content/custom_models_and_associations_fragments.json
154
- rendered: /markdown_record/rendered/content/custom_models_and_associations.json
155
- rendered: /markdown_record/rendered/content/erb_syntax_and_view_helpers_fragments.json
156
- rendered: /markdown_record/rendered/content/erb_syntax_and_view_helpers.json
157
- rendered: /markdown_record/rendered/content/content_frags_fragments.json
158
- rendered: /markdown_record/rendered/content/content_frags.json
159
- rendered: /markdown_record/rendered/content/model_basics_fragments.json
160
- rendered: /markdown_record/rendered/content/model_basics.json
161
- rendered: /markdown_record/rendered/content/routes_fragments.json
162
- rendered: /markdown_record/rendered/content/routes.json
163
- rendered: /markdown_record/rendered/content/content_dsl_fragments.json
164
- rendered: /markdown_record/rendered/content/content_dsl.json
165
161
  rendered: /markdown_record/rendered/content/rendering_basics_fragments.json
166
162
  rendered: /markdown_record/rendered/content/rendering_basics.json
167
- rendered: /markdown_record/rendered/content/installation_fragments.json
168
- rendered: /markdown_record/rendered/content/installation.json
169
163
  rendered: /markdown_record/rendered/content/home_fragments.json
170
164
  rendered: /markdown_record/rendered/content/home.json
165
+ rendered: /markdown_record/rendered/content/controller_helpers_fragments.json
166
+ rendered: /markdown_record/rendered/content/controller_helpers.json
167
+ rendered: /markdown_record/rendered/content/erb_syntax_and_view_helpers_fragments.json
168
+ rendered: /markdown_record/rendered/content/erb_syntax_and_view_helpers.json
169
+ rendered: /markdown_record/rendered/content/layouts_fragments.json
170
+ rendered: /markdown_record/rendered/content/layouts.json
171
+ rendered: /markdown_record/rendered/content/configuration_fragments.json
172
+ rendered: /markdown_record/rendered/content/configuration.json
171
173
  rendered: /markdown_record/rendered/content/sandbox_fragments.json
172
174
  rendered: /markdown_record/rendered/content/sandbox.json
175
+ rendered: /markdown_record/rendered/content/sandbox/sandbox_nested_fragments.json
176
+ rendered: /markdown_record/rendered/content/sandbox/sandbox_nested.json
177
+ rendered: /markdown_record/rendered/content/sandbox/sandbox_nested/bar_fragments.json
178
+ rendered: /markdown_record/rendered/content/sandbox/sandbox_nested/bar.json
173
179
  rendered: /markdown_record/rendered/content/sandbox/foo_fragments.json
174
180
  rendered: /markdown_record/rendered/content/sandbox/foo.json
175
- rendered: /markdown_record/rendered/content/configuration_fragments.json
176
- rendered: /markdown_record/rendered/content/configuration.json
177
- rendered: /markdown_record/rendered/content/controller_helpers_fragments.json
178
- rendered: /markdown_record/rendered/content/controller_helpers.json
181
+ rendered: /markdown_record/rendered/content/content_frags_fragments.json
182
+ rendered: /markdown_record/rendered/content/content_frags.json
183
+ rendered: /markdown_record/rendered/content/content_dsl_fragments.json
184
+ rendered: /markdown_record/rendered/content/content_dsl.json
185
+ rendered: /markdown_record/rendered/content/routes_fragments.json
186
+ rendered: /markdown_record/rendered/content/routes.json
187
+ rendered: /markdown_record/rendered/content/model_basics_fragments.json
188
+ rendered: /markdown_record/rendered/content/model_basics.json
189
+ rendered: /markdown_record/rendered/content/installation_fragments.json
190
+ rendered: /markdown_record/rendered/content/installation.json
191
+ rendered: /markdown_record/rendered/content/custom_models_and_associations_fragments.json
192
+ rendered: /markdown_record/rendered/content/custom_models_and_associations.json
179
193
  rendered: /markdown_record/rendered/content.html
180
- rendered: /markdown_record/rendered/content/custom_models_and_associations.html
181
- rendered: /markdown_record/rendered/content/erb_syntax_and_view_helpers.html
182
- rendered: /markdown_record/rendered/content/content_frags.html
183
- rendered: /markdown_record/rendered/content/model_basics.html
184
- rendered: /markdown_record/rendered/content/routes.html
185
- rendered: /markdown_record/rendered/content/content_dsl.html
186
194
  rendered: /markdown_record/rendered/content/rendering_basics.html
187
- rendered: /markdown_record/rendered/content/installation.html
188
195
  rendered: /markdown_record/rendered/content/home.html
196
+ rendered: /markdown_record/rendered/content/controller_helpers.html
197
+ rendered: /markdown_record/rendered/content/erb_syntax_and_view_helpers.html
198
+ rendered: /markdown_record/rendered/content/layouts.html
199
+ rendered: /markdown_record/rendered/content/configuration.html
189
200
  rendered: /markdown_record/rendered/content/sandbox.html
201
+ rendered: /markdown_record/rendered/content/sandbox/sandbox_nested.html
202
+ rendered: /markdown_record/rendered/content/sandbox/sandbox_nested/bar.html
190
203
  rendered: /markdown_record/rendered/content/sandbox/foo.html
191
- rendered: /markdown_record/rendered/content/configuration.html
192
- rendered: /markdown_record/rendered/content/controller_helpers.html
204
+ rendered: /markdown_record/rendered/content/content_frags.html
205
+ rendered: /markdown_record/rendered/content/content_dsl.html
206
+ rendered: /markdown_record/rendered/content/routes.html
207
+ rendered: /markdown_record/rendered/content/model_basics.html
208
+ rendered: /markdown_record/rendered/content/installation.html
209
+ rendered: /markdown_record/rendered/content/custom_models_and_associations.html
193
210
  ---------------------------------------------------------------
194
- 42 files rendered.
195
- 42 files saved.
211
+ 51 files rendered.
212
+ 51 files saved.
196
213
  ```
197
214
 
198
- Congratulations! You have installed MarkdownRecord. If you are not viewing this from the host application already, go ahead and start your Rails server and navigate to http://localhost:3000/mdr/content/home to continue following this guide.
215
+ Congratulations! You have installed MarkdownRecord. If you are not viewing this from the host application already, go ahead and start your Rails server with `rails s` and navigate to http://localhost:3000/mdr/content/home to continue following this guide.
216
+
217
+ Alternatively, you can find the complete usage guide [here](https://markdown-record-docs.herokuapp.com/).
199
218
 
200
219
  ## Contributing
201
220
 
@@ -220,6 +239,7 @@ To test a local version of this gem in a local app, simply add the `path` parame
220
239
 
221
240
  - Make the Content DSL extensible
222
241
  - Add support for raw JSON files as source content
242
+ - Support semantic versioning in numeric filename prefixes
223
243
 
224
244
  ## License
225
245
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -1,4 +1,27 @@
1
1
  module MarkdownRecord
2
2
  module ApplicationHelper
3
+ def method_missing(method, *args, &block)
4
+ if method.to_s.end_with?('_path') || method.to_s.end_with?('_url')
5
+ if main_app.respond_to?(method)
6
+ main_app.send(method, *args)
7
+ else
8
+ super
9
+ end
10
+ else
11
+ super
12
+ end
13
+ end
14
+
15
+ def respond_to?(method)
16
+ if method.to_s.end_with?('_path') || method.to_s.end_with?('_url')
17
+ if main_app.respond_to?(method)
18
+ true
19
+ else
20
+ super
21
+ end
22
+ else
23
+ super
24
+ end
25
+ end
3
26
  end
4
27
  end
@@ -33,7 +33,7 @@ module MarkdownRecord
33
33
  end
34
34
 
35
35
  def content_fragment(content_path = params[:content_path])
36
- ::MarkdownRecord::ContentFragment.find(content_path)
36
+ @content_fragment ||= ::MarkdownRecord::ContentFragment.find(content_path)
37
37
  end
38
38
  end
39
39
  end
@@ -59,7 +59,7 @@ module MarkdownRecord
59
59
  path_to_markdown_record(model, "json", download)
60
60
  end
61
61
 
62
- def url_for_markdown_record_html(model, download = false)
62
+ def url_for_markdown_record_json(model, download = false)
63
63
  path = path_to_markdown_record_json(model, download)
64
64
 
65
65
  "#{root_url}/#{path}"
@@ -77,8 +77,14 @@ module MarkdownRecord
77
77
  "/#{path}"
78
78
  end
79
79
 
80
- def render_html_example(example)
81
- CGI.escapeHTML(example)
80
+ def render_fragment(fragment_or_model)
81
+ unless fragment_or_model.is_a?(MarkdownRecord::ContentFragment)
82
+ fragment = fragment_or_model.fragment
83
+ end
84
+
85
+ fragment ||= fragment_or_model
86
+
87
+ raw(fragment.read_html)
82
88
  end
83
89
  end
84
90
  end
@@ -9,6 +9,8 @@ module MarkdownRecord
9
9
  attribute :type, :type => String
10
10
  attribute :subdirectory, :type => String
11
11
  attribute :filename, :type => String
12
+ attribute :scope, :type => String
13
+ attribute :scoped_id, :type => String
12
14
 
13
15
  def self.new_association(base_filters = {}, search_filters = {})
14
16
  MarkdownRecord::Association.new(base_filters, search_filters)
@@ -21,5 +23,13 @@ module MarkdownRecord
21
23
  def self.json_klass
22
24
  name.underscore
23
25
  end
26
+
27
+ def model_name
28
+ OpenStruct.new param_key: type
29
+ end
30
+
31
+ def to_key
32
+ scope.nil? ? [id] : ["#{scope}::id"]
33
+ end
24
34
  end
25
35
  end
@@ -5,6 +5,8 @@ module MarkdownRecord
5
5
  attribute :meta, :type => Object
6
6
  attribute :concatenated, :type => Boolean
7
7
 
8
+ attribute :__scope__
9
+
8
10
  def initialize(attributes = nil, options = {})
9
11
  super
10
12
 
@@ -19,12 +21,17 @@ module MarkdownRecord
19
21
  MarkdownRecord::Association.new(base_filters, search_filters).fragmentize
20
22
  end
21
23
 
24
+ def find_relative(relative_id)
25
+ real_id = Pathname.new(id).parent.join(relative_id).to_s
26
+ self.class.find(real_id)
27
+ end
28
+
22
29
  def fragment_id
23
30
  id
24
31
  end
25
32
 
26
33
  def name
27
- meta[:name]
34
+ meta[:name] || Pathname.new(id).basename.to_s
28
35
  end
29
36
 
30
37
  def exists?
@@ -69,7 +76,14 @@ module MarkdownRecord
69
76
  end
70
77
 
71
78
  def parent
72
- self.class.find(meta[:parent_id] || subdirectory)
79
+ if meta[:parent_id].present?
80
+ self.class.find(meta[:parent_id])
81
+ elsif meta[:relative_parent_id].present?
82
+ real_id = Pathname.new(id).parent.join(meta[:relative_parent_id])
83
+ self.class.find(real_id)
84
+ else
85
+ self.class.find(subdirectory)
86
+ end
73
87
  end
74
88
 
75
89
  def ancestors_from(ancestor)
@@ -94,6 +108,7 @@ module MarkdownRecord
94
108
  def parents_from(ancestor)
95
109
  ancestor = self.class.find(ancestor) if ancestor.is_a?(String)
96
110
 
111
+
97
112
  parents = []
98
113
  current_parent = self
99
114
 
@@ -4,6 +4,7 @@ require "rails/generators"
4
4
  class MarkdownRecordGenerator < Rails::Generators::Base
5
5
  source_root File.expand_path("../../templates", __dir__)
6
6
  class_option :demo, type: :boolean, aliases: :d
7
+ class_option :tests, type: :boolean, aliases: :t
7
8
 
8
9
  desc "This generator creates the default directories required for markdown_record and copies the default layout into the default location."
9
10
  def create_directories
@@ -14,9 +15,14 @@ class MarkdownRecordGenerator < Rails::Generators::Base
14
15
 
15
16
  def copy_demo_or_base
16
17
  if options[:demo]
18
+ directory "demo/models", "app/models"
17
19
  directory "demo/content", "markdown_record/content"
18
20
  directory "demo/layouts", "markdown_record/layouts"
19
21
  directory "demo/assets/images", "app/assets/images"
22
+ elsif options[:tests]
23
+ directory "tests/content", "markdown_record/content"
24
+ directory "tests/layouts", "markdown_record/layouts"
25
+ directory "tests/assets/images", "app/assets/images"
20
26
  else
21
27
  directory "base/content", "markdown_record/content"
22
28
  directory "base/layouts", "markdown_record/layouts"
@@ -19,6 +19,8 @@ module MarkdownRecord
19
19
  attr_accessor :render_content_fragment_json
20
20
  attr_accessor :render_controller
21
21
  attr_accessor :ignore_numeric_prefix
22
+ attr_accessor :filename_sorter
23
+ attr_accessor :always_concatenate_json
22
24
 
23
25
  RENDER_STRATEGIES = [:full, :directory, :file]
24
26
 
@@ -33,6 +35,7 @@ module MarkdownRecord
33
35
  @global_layout_path = "_global_layout.html.erb"
34
36
  @public_layout = "layouts/application"
35
37
  @render_strategy = :full
38
+ @always_concatenate_json = true
36
39
  @html_routes = [:show]
37
40
  @json_routes = [:show]
38
41
  @content_routes = [:show]
@@ -40,6 +43,7 @@ module MarkdownRecord
40
43
  @render_content_fragment_json = true
41
44
  @render_controller = nil
42
45
  @ignore_numeric_prefix = true
46
+ @filename_sorter = MarkdownRecord::FileSorting::Base.new
43
47
  end
44
48
 
45
49
  def render_strategy_options(strategy = nil)
@@ -0,0 +1,25 @@
1
+ module MarkdownRecord
2
+ module FileSorting
3
+ class Base
4
+
5
+ def initialize(sort_regex = /^(\d+)_/)
6
+ @sort_regex = sort_regex
7
+ end
8
+
9
+ def path_to_sort_value(path)
10
+ m = path.split("/").last.match(@sort_regex)
11
+ to_sort_value(m.try(:[], 1))
12
+ end
13
+
14
+ def to_sort_value(value)
15
+ value.to_i
16
+ end
17
+
18
+ def remove_prefix(filename_or_id)
19
+ parts = filename_or_id.split("/")
20
+ parts = parts.map { |p| p.sub(@sort_regex,"")}
21
+ parts.join("/")
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,14 @@
1
+ module MarkdownRecord
2
+ module FileSorting
3
+ class DateSorter < MarkdownRecord::FileSorting::Base
4
+ def initialize(sort_regex = /^(\d\d\d\d?_\d\d?_\d\d?)/, date_pattern = "%Y_%m_%d")
5
+ super(sort_regex)
6
+ @date_pattern = date_pattern || "%Y_%m_%d"
7
+ end
8
+
9
+ def to_sort_value(value)
10
+ Date.strptime(value, @date_pattern)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,47 @@
1
+ module MarkdownRecord
2
+ module FileSorting
3
+ class SemVerSorter < MarkdownRecord::FileSorting::Base
4
+ def initialize(sort_regex = /(\d+(?:_\d+)*)(?:_|$)/)
5
+ super(sort_regex)
6
+ end
7
+
8
+ def to_sort_value(value)
9
+ SemVer.new(value)
10
+ end
11
+
12
+ class SemVer
13
+ include Comparable
14
+
15
+ attr_reader :parts
16
+
17
+ def initialize(sem_ver_string)
18
+ @parts = sem_ver_string.split(/\D/).map(&:to_i)
19
+ end
20
+
21
+ def <=>(other)
22
+ result = 0
23
+ index = 0
24
+
25
+ while result == 0
26
+ if parts[index].nil? && other.parts[index].nil?
27
+ return 0
28
+ end
29
+
30
+ if other.parts[index].nil?
31
+ return 1
32
+ end
33
+
34
+ if parts[index].nil?
35
+ return -1
36
+ end
37
+
38
+ result = parts[index] <=> other.parts[index]
39
+ index += 1
40
+ end
41
+
42
+ result
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -2,6 +2,8 @@ require "markdown_record/errors/duplicate_id_error"
2
2
 
3
3
  module MarkdownRecord
4
4
  class Association
5
+ include MarkdownRecord::PathUtilities
6
+
5
7
  attr_accessor :base_filters
6
8
  attr_accessor :search_filters
7
9
  attr_reader :fulfilled
@@ -12,6 +14,7 @@ module MarkdownRecord
12
14
  @search_filters = search_filters
13
15
  @data = []
14
16
  @fulfilled = false
17
+ @force_render = false
15
18
  end
16
19
 
17
20
  def execute
@@ -22,11 +25,17 @@ module MarkdownRecord
22
25
  else
23
26
  final_filters.merge!(:exclude_fragments => true)
24
27
  end
25
- results = MarkdownRecord::ModelInflator.new.where(final_filters)
28
+ results = MarkdownRecord::ModelInflator.new(@force_render).where(final_filters)
26
29
  @data.push(*results)
27
30
  @fulfilled = true
28
31
  end
29
32
 
33
+ def force_render
34
+ reset
35
+ @force_render = true
36
+ self
37
+ end
38
+
30
39
  def fragmentize
31
40
  reset
32
41
  @include_fragments = true
@@ -120,11 +129,19 @@ module MarkdownRecord
120
129
  @data.fourth(...)
121
130
  end
122
131
 
123
- def __find__(id)
132
+ def __find__(id, scope = nil)
124
133
  reset
125
- search_filters.merge!({:id => id})
134
+
135
+ if scope.nil?
136
+ search_filters.merge!({:id => id, :scope => scope})
137
+ else
138
+ search_filters.merge!({:scoped_id => to_scoped_id(scope, id)})
139
+ end
140
+
126
141
  execute
142
+
127
143
  raise ::MarkdownRecord::Errors::DuplicateIdError.new(@base_filters[:klass].name, id) if @data.count > 1
144
+
128
145
  @data.first
129
146
  end
130
147
  end
@@ -11,7 +11,7 @@ module MarkdownRecord
11
11
  foreign_key = "#{self.name.demodulize.underscore}_id".to_sym
12
12
 
13
13
  define_method(association) do
14
- klass.new_association({:klass => klass, foreign_key => self.id})
14
+ klass.new_association({:klass => klass, :scope => self.scope, foreign_key => self.id})
15
15
  end
16
16
  end
17
17
 
@@ -22,7 +22,7 @@ module MarkdownRecord
22
22
  foreign_key = "#{self.name.demodulize.underscore}_id".to_sym
23
23
 
24
24
  define_method(association) do
25
- results = klass.new_association({:klass => klass, foreign_key => self.id}).all
25
+ results = klass.new_association({:klass => klass, :scope => self.scope, foreign_key => self.id}).all
26
26
  if results.count > 1
27
27
  raise ArgumentError.new("Multiple MarkdownRecords belong to the same record in a has_one_content assocition: #{self.class.name} has a has_one_content #{association} and the following records ids were found #{ results.map(&:id) } ")
28
28
  end
@@ -40,7 +40,7 @@ module MarkdownRecord
40
40
  self.attribute foreign_key unless self.attributes[foreign_key].present?
41
41
 
42
42
  define_method(association) do
43
- klass.find(self[foreign_key])
43
+ klass.find(self[foreign_key], self.scope)
44
44
  end
45
45
  end
46
46
 
@@ -52,8 +52,16 @@ module MarkdownRecord
52
52
  new_association({ :klass => self }, filters)
53
53
  end
54
54
 
55
- def find(id)
56
- new_association({ :klass => self }).__find__(id)
55
+ def force_render_where(filters = {})
56
+ new_association({ :klass => self }, filters).force_render
57
+ end
58
+
59
+ def find(id, scope = nil)
60
+ new_association({ :klass => self }).__find__(id, scope)
61
+ end
62
+
63
+ def force_render_find(id, scope = nil)
64
+ new_association({ :klass => self }).force_render.__find__(id, scope)
57
65
  end
58
66
 
59
67
  def infer_klass(association, options)
@@ -69,20 +77,20 @@ module MarkdownRecord
69
77
  end
70
78
 
71
79
  def siblings(filters = {})
72
- self.class.new_association(filters.merge({:subdirectory => subdirectory}).merge!(not_self))
80
+ self.class.new_association(filters.merge({:subdirectory => subdirectory, :scope => scope}).merge!(not_self))
73
81
  end
74
82
 
75
83
  def class_siblings(filters = {})
76
- self.class.new_association(filters.merge({:klass => self.class, :subdirectory => subdirectory, :__not__ => { :id => self.id }}))
84
+ self.class.new_association(filters.merge({:klass => self.class, :scope => scope, :subdirectory => subdirectory, :__not__ => { :id => self.id }}))
77
85
  end
78
86
 
79
87
  def children(filters = {})
80
88
  sub_start = "#{subdirectory}/".delete_prefix("/")
81
- self.class.new_association(filters.merge({:subdirectory => Regexp.new("#{sub_start}[\\S|\\w]+")}).merge!(not_self))
89
+ self.class.new_association(filters.merge({:scope => scope, :subdirectory => Regexp.new("#{sub_start}[\\S|\\w]+")}).merge!(not_self))
82
90
  end
83
91
 
84
92
  def fragment
85
- self.class.new_association.fragmentize.__find__(fragment_id)
93
+ @fragment ||= self.class.new_association.fragmentize.__find__(fragment_id)
86
94
  end
87
95
 
88
96
  private
@@ -1,6 +1,7 @@
1
1
  module MarkdownRecord
2
2
  module ContentAssociations
3
3
  extend ActiveSupport::Concern
4
+ include MarkdownRecord::PathUtilities
4
5
 
5
6
  class_methods do
6
7
  def has_many_content(association, **options)
@@ -11,7 +12,7 @@ module MarkdownRecord
11
12
  raise ArgumentError.new("#{self} does not have the #{foreign_key} attribute required for this association.") unless self.attribute_names.include?(foreign_key)
12
13
 
13
14
  define_method(association) do
14
- klass.new_association({:klass => klass, :id => self[foreign_key.to_sym]})
15
+ klass.new_association({:klass => klass, :scoped_id => self[foreign_key.to_sym]})
15
16
  end
16
17
  end
17
18
 
@@ -27,7 +28,8 @@ module MarkdownRecord
27
28
  raise ArgumentError.new("#{self} does not have the #{foreign_key} attribute required for this association.") unless self.attribute_names.include?(foreign_key)
28
29
 
29
30
  define_method(association) do
30
- klass.find(self[foreign_key])
31
+ assoc_scope, assoc_id = scoped_id_to_parts(self[foreign_key])
32
+ klass.find(assoc_id, assoc_scope)
31
33
  end
32
34
  end
33
35
 
@@ -0,0 +1,13 @@
1
+ require "markdown_record/models/filters"
2
+
3
+ module MarkdownRecord
4
+ module Models
5
+ module Filtering
6
+ def filter_for(filter_value, attribute_value)
7
+ klass = MarkdownRecord::Models::Filters::FILTER_MAPPING[filter_value.class.name] || MarkdownRecord::Models::BaseFilter
8
+
9
+ klass.new(filter_value, attribute_value)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,11 @@
1
+ module MarkdownRecord
2
+ module Models
3
+ module Filters
4
+ class ArrayFilter < MarkdownRecord::Models::Filters::BaseFilter
5
+ def passes_filter?
6
+ @filter_value.include?(@attribute_value)
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end