plutonium 0.10.0 → 0.10.2

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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -0
  3. data/app/assets/javascripts/turbo/index.js +1 -1
  4. data/app/views/application/_resource_header.html.erb +12 -12
  5. data/app/views/layouts/resource.html.erb +1 -0
  6. data/app/views/layouts/rodauth.html.erb +4 -4
  7. data/app/views/resource/_nav_user.html.erb +1 -1
  8. data/app/views/resource/index.rabl +1 -1
  9. data/brakeman.ignore +1 -1
  10. data/config/initializers/rabl.rb +2 -0
  11. data/css.manifest +1 -1
  12. data/js.manifest +2 -2
  13. data/lib/generators/pu/core/install/templates/config/initializers/plutonium.rb +0 -3
  14. data/lib/generators/pu/gen/pug/pug_generator.rb +6 -0
  15. data/lib/generators/pu/gen/pug/templates/pug.rb.tt +1 -1
  16. data/lib/generators/pu/pkg/app/templates/config/routes.rb.tt +3 -3
  17. data/lib/plutonium/config.rb +1 -11
  18. data/lib/plutonium/core/autodiscovery/input_discoverer.rb +1 -1
  19. data/lib/plutonium/core/autodiscovery/renderer_discoverer.rb +1 -1
  20. data/lib/plutonium/core/controllers/base.rb +13 -3
  21. data/lib/plutonium/core/controllers/queryable.rb +3 -1
  22. data/lib/plutonium/pkg/app.rb +6 -0
  23. data/lib/plutonium/railtie.rb +15 -0
  24. data/lib/plutonium/reloader.rb +99 -0
  25. data/lib/plutonium/resource/controller.rb +61 -22
  26. data/lib/plutonium/resource/policy.rb +56 -9
  27. data/lib/plutonium/resource/presenter.rb +44 -12
  28. data/lib/plutonium/resource/query_object.rb +186 -73
  29. data/lib/plutonium/resource/record.rb +213 -119
  30. data/lib/plutonium/rodauth/controller_methods.rb +7 -0
  31. data/lib/plutonium/version.rb +1 -1
  32. data/lib/plutonium.rb +50 -12
  33. data/package-lock.json +174 -0
  34. data/package.json +2 -0
  35. data/public/plutonium-assets/plutonium-app-6WILQCTT.js +39 -0
  36. data/public/plutonium-assets/plutonium-app-6WILQCTT.js.map +7 -0
  37. data/public/plutonium-assets/plutonium-logo-original.png +0 -0
  38. data/public/plutonium-assets/plutonium-logo-white.png +0 -0
  39. data/public/plutonium-assets/plutonium-logo.png +0 -0
  40. data/public/plutonium-assets/plutonium.2d4f0c333cd000051d3b.css +3424 -0
  41. data/public/plutonium-assets/plutonium.ico +0 -0
  42. metadata +10 -4
  43. data/lib/plutonium/reactor/core.rb +0 -78
  44. data/public/plutonium-assets/logo.png +0 -0
@@ -10,113 +10,135 @@ module Plutonium
10
10
  named_scope = :"associated_with_#{record.model_name.singular}"
11
11
  return send(named_scope, record) if respond_to?(named_scope)
12
12
 
13
- # TODO: add suppport for polymorphic associations
13
+ # TODO: add support for polymorphic associations
14
14
  # TODO: add logging
15
15
  # TODO: memoize this
16
16
 
17
- if (own_association = reflect_on_all_associations.find { |assoc| assoc.klass.name == record.class.name })
18
- case own_association.macro
19
- when :has_one
20
- joins(own_association.name).where({
21
- own_association.name => {
22
- record.class.primary_key => record.id
23
- }
24
- })
25
- when :belongs_to
26
- where(own_association.name => record)
27
- when :has_many
28
- joins(own_association.name).where(own_association.klass.table_name => record)
29
- else
30
- raise NotImplementedError, "associated_with->##{own_association.macro}"
31
- end
32
- elsif (record_association = record.class.reflect_on_all_associations.find { |assoc| assoc.klass.name == klass.name })
17
+ own_association = klass.find_association_to_record(record)
18
+ if own_association
19
+ return klass.query_based_on_association(own_association, record)
20
+ end
21
+
22
+ record_association = klass.find_association_to_self(record)
23
+ if record_association
33
24
  # TODO: add a warning here about a potentially poor performing query
34
- where(id: record.send(record_association.name))
35
- else
36
- raise "Could not resolve the association between '#{klass.name}' and '#{record.class.name}'\n\n" \
37
- "Define\n" \
38
- " 1. the associations between the models\n" \
39
- " 2. a named scope on #{klass.name} e.g.\n\n" \
40
- "scope :#{named_scope}, ->(#{record.model_name.singular}) { do_something_here }"
25
+ return where(id: record.send(record_association.name))
41
26
  end
27
+
28
+ klass.raise_association_error(record, named_scope)
42
29
  end
43
30
  end
44
31
 
45
32
  class_methods do
33
+ # Returns the resource field names
34
+ # @return [Array<Symbol>]
46
35
  def resource_field_names
47
- @resource_field_names ||= belongs_to_association_field_names +
48
- has_one_attached_field_names + has_one_association_field_names +
49
- has_many_attached_field_names + has_many_association_field_names +
50
- content_column_field_names
36
+ return @resource_field_names if defined?(@resource_field_names) && !Rails.env.local?
37
+
38
+ @resource_field_names = gather_resource_field_names
51
39
  end
52
40
 
41
+ # Overrides belongs_to to add support for polymorphic associations
42
+ # @param [Symbol] name The name of the association
43
+ # @param [Proc] scope The scope for the association
44
+ # @param [Hash] options The options for the association
53
45
  def belongs_to(name, scope = nil, **options)
54
46
  super(name, scope, **options)
55
47
 
56
- if options[:polymorphic]
57
- mod = Module.new
58
- mod.module_eval <<-RUBY, __FILE__, __LINE__ + 1
59
- extend ActiveSupport::Concern
48
+ return unless options[:polymorphic]
60
49
 
61
- def #{name}_sgid
62
- #{name}&.to_signed_global_id
63
- end
50
+ mod = Module.new
51
+ mod.module_eval <<-RUBY, __FILE__, __LINE__ + 1
52
+ extend ActiveSupport::Concern
64
53
 
65
- def #{name}_sgid=(sgid)
66
- self.#{name} = GlobalID::Locator.locate_signed(sgid)
67
- end
54
+ def #{name}_sgid
55
+ #{name}&.to_signed_global_id
56
+ end
68
57
 
69
- define_singleton_method(:to_s) { "Plutonium::Polymormorphic::BelongsTo(:#{name})" }
70
- define_singleton_method(:inspect) { "Plutonium::Polymormorphic::BelongsTo(:#{name})" }
71
- RUBY
72
- include mod
73
- end
58
+ def #{name}_sgid=(sgid)
59
+ self.#{name} = GlobalID::Locator.locate_signed(sgid)
60
+ end
61
+
62
+ define_singleton_method(:to_s) { "Plutonium::Polymorphic::BelongsTo(:#{name})" }
63
+ define_singleton_method(:inspect) { "Plutonium::Polymorphic::BelongsTo(:#{name})" }
64
+ RUBY
65
+ include mod
74
66
  end
75
67
 
68
+ # Returns the names of belongs_to associations
69
+ # @return [Array<Symbol>]
76
70
  def belongs_to_association_field_names
77
- @belongs_to_association_field_names ||= reflect_on_all_associations(:belongs_to).map(&:name)
71
+ return @belongs_to_association_field_names if defined?(@belongs_to_association_field_names) && !Rails.env.local?
72
+
73
+ @belongs_to_association_field_names = reflect_on_all_associations(:belongs_to).map(&:name)
78
74
  end
79
75
 
76
+ # Returns the names of has_one associations
77
+ # @return [Array<Symbol>]
80
78
  def has_one_association_field_names
81
- @has_one_association_field_names ||= reflect_on_all_associations(:has_one)
82
- .map { |assoc| /_attachment$|_blob$/.match?(assoc.name) ? nil : assoc.name }
79
+ return @has_one_association_field_names if defined?(@has_one_association_field_names) && !Rails.env.local?
80
+
81
+ @has_one_association_field_names = reflect_on_all_associations(:has_one)
82
+ .map { |assoc| (!/_attachment$|_blob$/.match?(assoc.name)) ? assoc.name : nil }
83
83
  .compact
84
84
  end
85
85
 
86
+ # Returns the names of has_many associations
87
+ # @return [Array<Symbol>]
86
88
  def has_many_association_field_names
87
- @has_many_association_field_names ||= reflect_on_all_associations(:has_many)
88
- .map { |assoc| /_attachments$|_blobs$/.match?(assoc.name) ? nil : assoc.name }
89
+ return @has_many_association_field_names if defined?(@has_many_association_field_names) && !Rails.env.local?
90
+
91
+ @has_many_association_field_names = reflect_on_all_associations(:has_many)
92
+ .map { |assoc| (!/_attachments$|_blobs$/.match?(assoc.name)) ? assoc.name : nil }
89
93
  .compact
90
94
  end
91
95
 
96
+ # Returns the names of has_one attached associations
97
+ # @return [Array<Symbol>]
92
98
  def has_one_attached_field_names
93
- @has_one_attached_field_names ||= if respond_to?(:reflect_on_all_attachments)
99
+ return @has_one_attached_field_names if defined?(@has_one_attached_field_names) && !Rails.env.local?
100
+
101
+ @has_one_attached_field_names = if respond_to?(:reflect_on_all_attachments)
94
102
  reflect_on_all_attachments
95
- .map { |a| (a.macro == :has_one_attached) ? a.name : nil }
96
- .compact
103
+ .select { |a| a.macro == :has_one_attached }
104
+ .map(&:name)
97
105
  else
98
106
  []
99
107
  end
100
108
  end
101
109
 
110
+ # Returns the names of has_many attached associations
111
+ # @return [Array<Symbol>]
102
112
  def has_many_attached_field_names
103
- @has_many_attached_field_names ||= if respond_to?(:reflect_on_all_attachments)
113
+ return @has_many_attached_field_names if defined?(@has_many_attached_field_names) && !Rails.env.local?
114
+
115
+ @has_many_attached_field_names = if respond_to?(:reflect_on_all_attachments)
104
116
  reflect_on_all_attachments
105
- .map { |a| (a.macro == :has_many_attached) ? a.name : nil }
106
- .compact
117
+ .select { |a| a.macro == :has_many_attached }
118
+ .map(&:name)
107
119
  else
108
120
  []
109
121
  end
110
122
  end
111
123
 
124
+ # Returns the names of content columns
125
+ # @return [Array<Symbol>]
112
126
  def content_column_field_names
113
- @content_column_field_names ||= content_columns.map { |col| col.name.to_sym }
127
+ return @content_column_field_names if defined?(@content_column_field_names) && !Rails.env.local?
128
+
129
+ @content_column_field_names = content_columns.map { |col| col.name.to_sym }
114
130
  end
115
131
 
132
+ # Returns the routes for has_many associations
133
+ # @return [Array<Symbol>]
116
134
  def has_many_association_routes
117
- @has_many_association_routes ||= reflect_on_all_associations(:has_many).map { |assoc| assoc.klass.model_name.plural }
135
+ return @has_many_association_routes if defined?(@has_many_association_routes) && !Rails.env.local?
136
+
137
+ @has_many_association_routes = reflect_on_all_associations(:has_many).map { |assoc| assoc.klass.model_name.plural }
118
138
  end
119
139
 
140
+ # Returns all nested attributes options
141
+ # @return [Hash]
120
142
  def all_nested_attributes_options
121
143
  unless Rails.env.local?
122
144
  return @all_nested_attributes_options if defined?(@all_nested_attributes_options)
@@ -125,98 +147,155 @@ module Plutonium
125
147
  @all_nested_attributes_options = reflect_on_all_associations.map do |association|
126
148
  setter_method = "#{association.name}_attributes="
127
149
  if method_defined?(setter_method)
128
- [association.name, {
129
- **nested_attributes_options[association.name],
150
+ [association.name, nested_attributes_options[association.name].merge(
130
151
  macro: association.macro,
131
152
  class: association.polymorphic? ? nil : association.klass
132
- }]
153
+ )]
133
154
  end
134
155
  end.compact.to_h
135
156
  end
136
157
 
137
- #
138
158
  # Returns the strong parameters definition for the given attribute names
139
- #
140
- # @param [Array] *attributes Attribute names
141
- #
142
- # @return [Array] A strong parameters compatible array e.g.
143
- # [:title, :body, {:images=>[]}, {:docs=>[]}]
144
- #
159
+ # @param [Array<Symbol>] *attributes Attribute names
160
+ # @return [Array<Symbol, Hash>] A strong parameters compatible array
145
161
  def strong_parameters_for(*attributes)
146
- # attributes that are passed but we do not have a model/database backed definition for e.g. virtual attributes.
147
- # if they are passed and we are not expecting them, our inputs will filter them out as they apply an additional level
148
- # of filtering
149
162
  unbacked = attributes - strong_parameters_definition.keys
150
163
 
151
- # attributes backed by some model/database definition
152
- # {:name=>{:name=>nil}, :body=>{:body=>nil}, :cover_image=>{:cover_image=>nil}, :comments=>{:comment_ids=>[]}}
153
- backed = strong_parameters_definition.
154
- # {:name=>{:name=>nil}, :comments=>{:comment_ids=>[]}, :cover_image=>{:cover_image=>nil}}
155
- slice(*attributes).
156
- # [{:name=>nil}, {:comment_ids=>[]}, {:cover_image=>nil}]
157
- values.
158
- # {:name=>nil, :comment_ids=>[], :cover_image=>nil}
159
- reduce(:merge)&.
160
- # [:name, {:comment_ids=>[]}, :cover_image]
161
- map { |key, value| value.nil? ? key : {key => value} } || {}
164
+ backed = strong_parameters_definition.slice(*attributes).values.reduce(:merge)
165
+ &.map { |key, value| value.nil? ? key : {key => value} } || {}
162
166
 
163
- unbacked + backed
167
+ case backed.presence
168
+ when Hash
169
+ [*unbacked, **backed]
170
+ when Array
171
+ [*unbacked, *backed]
172
+ when nil
173
+ unbacked
174
+ else
175
+ raise "Unexpected strong parameters definition: #{backed.class}"
176
+ end
177
+ end
178
+
179
+ # Finds the association to the given record
180
+ # @param [ActiveRecord::Base] record The record to find the association with
181
+ # @return [ActiveRecord::Reflection::AssociationReflection, nil]
182
+ def find_association_to_record(record)
183
+ reflect_on_all_associations.find do |assoc|
184
+ assoc.klass.name == record.class.name
185
+ rescue
186
+ assoc.check_validity!
187
+ raise
188
+ end
189
+ end
190
+
191
+ # Finds the association to self in the given record
192
+ # @param [ActiveRecord::Base] record The record to find the association with
193
+ # @return [ActiveRecord::Reflection::AssociationReflection, nil]
194
+ def find_association_to_self(record)
195
+ record.class.reflect_on_all_associations.find do |assoc|
196
+ assoc.klass.name == name
197
+ rescue
198
+ assoc.check_validity!
199
+ raise
200
+ end
201
+ end
202
+
203
+ # Queries based on the association type
204
+ # @param [ActiveRecord::Reflection::AssociationReflection] assoc The association
205
+ # @param [ActiveRecord::Base] record The record to query with
206
+ # @return [ActiveRecord::Relation]
207
+ def query_based_on_association(assoc, record)
208
+ case assoc.macro
209
+ when :has_one
210
+ joins(assoc.name).where(assoc.name => {record.class.primary_key => record.id})
211
+ when :belongs_to
212
+ where(assoc.name => record)
213
+ when :has_many
214
+ joins(assoc.name).where(assoc.klass.table_name => record)
215
+ else
216
+ raise NotImplementedError, "associated_with->##{assoc.macro}"
217
+ end
218
+ end
219
+
220
+ # Raises an error for unresolved associations
221
+ # @param [ActiveRecord::Base] record The record with unresolved association
222
+ # @param [Symbol] named_scope The named scope
223
+ # @raise [RuntimeError]
224
+ def raise_association_error(record, named_scope)
225
+ raise "Could not resolve the association between '#{name}' and '#{record.class.name}'\n\n" \
226
+ "Define\n" \
227
+ " 1. the associations between the models\n" \
228
+ " 2. a named scope on #{name} e.g.\n\n" \
229
+ "scope :#{named_scope}, ->(#{record.model_name.singular}) { do_something_here }"
164
230
  end
165
231
 
166
232
  private
167
233
 
234
+ # Defines the strong parameters
235
+ # @return [Hash]
168
236
  def strong_parameters_definition
169
237
  unless Rails.env.local?
170
238
  return @strong_parameters if defined?(@strong_parameters)
171
239
  end
172
240
 
173
- @strong_parameters = begin
174
- # Columns
175
-
176
- content_column_parameters = content_column_field_names.map do |name|
177
- column = columns_hash[name.to_s]
178
-
179
- type = nil
180
- type = [] if column&.try(:array?)
181
- type = {} if [:json, :jsonb].include?(column&.type)
241
+ @strong_parameters = build_strong_parameters
242
+ end
182
243
 
183
- [name, {name => type}]
244
+ # Builds the strong parameters hash
245
+ # @return [Hash]
246
+ def build_strong_parameters
247
+ parameters = content_column_field_names.map do |name|
248
+ column = columns_hash[name.to_s]
249
+ type = if column.try(:array?)
250
+ []
251
+ else
252
+ ([:json, :jsonb].include?(column&.type) ? {} : nil)
184
253
  end
185
- parameters = content_column_parameters.to_h
254
+ [name, {name => type}]
255
+ end.to_h
186
256
 
187
- # Associations
257
+ parameters.merge!(belongs_to_association_parameters)
258
+ parameters.merge!(has_many_association_parameters)
259
+ parameters.merge!(attachment_parameters)
260
+ parameters.merge!(nested_attributes_parameters)
188
261
 
189
- parameters.merge! reflect_on_all_associations(:belongs_to)
190
- .map { |reflection|
191
- input_param = reflection.respond_to?(:options) ? reflection.options[:foreign_key] : :"#{reflection.name}_id"
192
- [reflection.name, {input_param => nil}]
193
- }
194
- .to_h
195
-
196
- parameters.merge! has_many_association_field_names
197
- .map { |name| [name, {"#{name.to_s.singularize}_ids": []}] }
198
- .to_h
199
-
200
- # Attachments
201
-
202
- parameters.merge! has_many_attached_field_names.map { |name| [name, {name => []}] }.to_h
203
-
204
- parameters.merge! has_one_attached_field_names.map { |name| [name, {name => nil}] }.to_h
262
+ parameters
263
+ end
205
264
 
206
- # Nested Attributes
265
+ # Returns the parameters for belongs_to associations
266
+ # @return [Hash]
267
+ def belongs_to_association_parameters
268
+ reflect_on_all_associations(:belongs_to).map do |reflection|
269
+ input_param = reflection.options[:foreign_key] || :"#{reflection.name}_id"
270
+ [reflection.name, {input_param => nil}]
271
+ end.to_h
272
+ end
207
273
 
208
- parameters.merge! all_nested_attributes_options.keys
209
- .map { |name| [name, {"#{name}_attributes" => {}}] }
210
- .to_h
274
+ # Returns the parameters for has_many associations
275
+ # @return [Hash]
276
+ def has_many_association_parameters
277
+ has_many_association_field_names.map do |name|
278
+ [name, {"#{name.to_s.singularize}_ids": []}]
279
+ end.to_h
280
+ end
211
281
 
212
- # e.g.
213
- # {:name=>{:name=>nil}, :cover_image=>{:cover_image=>nil}, :user=>{:user_id=>nil} :comments=>{:comment_ids=>[]}}
214
- parameters
215
- end
282
+ # Returns the parameters for attachments
283
+ # @return [Hash]
284
+ def attachment_parameters
285
+ has_many_attached_field_names.map { |name| [name, {name => []}] }.to_h
286
+ .merge(has_one_attached_field_names.map { |name| [name, {name => nil}] }.to_h)
216
287
  end
217
288
 
218
- # Path parameters
289
+ # Returns the parameters for nested attributes
290
+ # @return [Hash]
291
+ def nested_attributes_parameters
292
+ all_nested_attributes_options.keys.map do |name|
293
+ [name, {"#{name}_attributes" => {}}]
294
+ end.to_h
295
+ end
219
296
 
297
+ # Defines a scope and method for path parameters
298
+ # @param [Symbol] param_name The name of the parameter
220
299
  def path_parameter(param_name)
221
300
  param_name = param_name.to_sym
222
301
 
@@ -225,10 +304,12 @@ module Plutonium
225
304
  define_method :to_param do
226
305
  return nil unless persisted?
227
306
 
228
- send param_name
307
+ send(param_name)
229
308
  end
230
309
  end
231
310
 
311
+ # Defines a scope and method for dynamic path parameters
312
+ # @param [Symbol] param_name The name of the parameter
232
313
  def dynamic_path_parameter(param_name)
233
314
  param_name = param_name.to_sym
234
315
 
@@ -240,8 +321,21 @@ module Plutonium
240
321
  "#{id}-#{send(param_name)}".parameterize
241
322
  end
242
323
  end
324
+
325
+ # Gathers all resource field names
326
+ # @return [Array<Symbol>]
327
+ def gather_resource_field_names
328
+ belongs_to_association_field_names +
329
+ has_one_attached_field_names +
330
+ has_one_association_field_names +
331
+ has_many_attached_field_names +
332
+ has_many_association_field_names +
333
+ content_column_field_names
334
+ end
243
335
  end
244
336
 
337
+ # Returns a label for the record
338
+ # @return [String]
245
339
  def to_label
246
340
  %i[name title].each do |method|
247
341
  name = send(method) if respond_to?(method)
@@ -6,6 +6,13 @@ module Plutonium
6
6
  included do
7
7
  layout "rodauth"
8
8
  append_view_path File.expand_path("app/views", Plutonium.root)
9
+ helper_method :application_name
10
+ end
11
+
12
+ private
13
+
14
+ def application_name
15
+ Rails.application.class.module_parent.name
9
16
  end
10
17
  end
11
18
  end
@@ -1,3 +1,3 @@
1
1
  module Plutonium
2
- VERSION = "0.10.0"
2
+ VERSION = "0.10.2"
3
3
  end
data/lib/plutonium.rb CHANGED
@@ -19,33 +19,71 @@ module Plutonium
19
19
  root.join("lib", "plutonium")
20
20
  end
21
21
 
22
+ def self.logger
23
+ Rails.logger
24
+ end
25
+
26
+ def self.development?
27
+ ActiveModel::Type::Boolean.new.cast(ENV["PLUTONIUM_DEV"]).present?
28
+ end
29
+
22
30
  def self.stylesheet_link
23
- if Plutonium::Config.development
31
+ return @stylesheet_link if defined?(@stylesheet_link) && !development?
32
+
33
+ if development?
24
34
  base_dir = "/plutonium-assets/build"
25
- manifest = "css.dev.manifest"
26
35
  filename = "plutonium-dev.css"
27
36
  else
28
37
  base_dir = "/plutonium-assets"
29
- manifest = "css.manifest"
30
38
  filename = "plutonium.css"
31
39
  end
32
40
 
33
- file = JSON.parse(File.read(root.join(manifest)))[filename]
34
- "#{base_dir}/#{file}"
41
+ file = stylesheet_manifest[filename]
42
+ @stylesheet_link = "#{base_dir}/#{file}"
35
43
  end
36
44
 
37
45
  def self.script_link
46
+ return @script_link if defined?(@script_link) && !development?
47
+
38
48
  filename = "plutonium-app.js"
39
- if Plutonium::Config.development
40
- base_dir = "/plutonium-assets/build"
41
- manifest = "js.dev.manifest"
49
+ base_dir = if development?
50
+ "/plutonium-assets/build"
42
51
  else
43
- base_dir = "/plutonium-assets"
44
- manifest = "js.manifest"
52
+ "/plutonium-assets"
53
+ end
54
+
55
+ file = script_manifest[filename]
56
+ @script_link = "#{base_dir}/#{file}"
57
+ end
58
+
59
+ def self.favicon_link
60
+ "/plutonium-assets/plutonium.ico"
61
+ end
62
+
63
+ def self.logo_link
64
+ "/plutonium-assets/plutonium-logo.png"
65
+ end
66
+
67
+ def self.stylesheet_manifest
68
+ return @stylesheet_manifest if defined?(@stylesheet_manifest) && !development?
69
+
70
+ manifest = if development?
71
+ "css.dev.manifest"
72
+ else
73
+ "css.manifest"
45
74
  end
75
+ @stylesheet_manifest = JSON.parse(File.read(root.join(manifest)))
76
+ end
77
+
78
+ def self.script_manifest
79
+ return @script_manifest if defined?(@script_manifest) && !development?
46
80
 
47
- file = JSON.parse(File.read(root.join(manifest)))[filename]
48
- "#{base_dir}/#{file}"
81
+ manifest = if development?
82
+ "js.dev.manifest"
83
+ else
84
+ "js.manifest"
85
+ end
86
+ @script_manifest = JSON.parse(File.read(root.join(manifest)))
49
87
  end
50
88
  end
51
89