I create a Rails Engine to easily include a JavaScript plugin for rails apps. The problem is that this plugin is really only for development and when pushing an app to production the developer needs to remove the require marx
in the javascript manifest file and then the actual call in the JavaScript.
What I'm hoping to do is allow the developer to just add this to the Gemfile with gem 'marxjs-rails', group: :development
and setup some configurations in config/application.rb or config/environments/development.rb for the plugin settings.
The gem should then insert html to the parent application:
<script src='marx.js'></script>
<script>
var marx = new Marx()
</script>
I've been playing around with a helper method to insert the html but I can't get it to insert it as html. Rails continues to escape the HTML. Though I don't really like this path any how.
I've been looking through the jasmine-gem and rack-olark as examples, but can't quite get anything to work.
UPDATE
This is not the solution I'm really looking for but this may help others and is what I'm using till I can track down a better way to do this. You can view the whole code here but I'll give you the highlights:
# lib/marxjs/rails.rb
require "marxjs/rails/version"
require "marxjs/view_helpers"
module Marxjs
module Rails
class Engine < ::Rails::Engine
initializer "marxjs.view_helpers" do
ActionView::Base.send :include, ViewHelpers
end
end
end
end
and the view helpers:
# lib/marxjs/view_helpers.rb
require 'erb'
module Marxjs
module ViewHelpers
include ActionView::Helpers::OutputSafetyHelper
def render_marxjs options={}, dev_only=true
if dev_only == false || (dev_only && ::Rails.env.development?)
binding.local_variable_set(:options, options.to_json)
template_file = ::File.read(::File.expand_path('../templates/marxjs.erb', __FILE__))
raw ERB.new(template_file).result(binding)
end
end
end
end
biggest thing to take away here is the include ActionView::Helpers::OutputSafetyHelper
and also the require 'erb'
This gives us the ability to load a template erb file and use ERB.new
to render it and use raw
to keep rails from escaping the html. I also bound an options variable to the binding
object to send it to the template.
<script src="assets/marx.js"></script>
<script>
var marx = new Marx(<%= options %>);
</script>
and finally in my main rails application I call render_marxjs(controls: 'toggle-all')
in the application.html.haml (or .erb if you like)
Again I'm still looking for someone to help me handle this without a view helper method and also to be able to set some configurations via an environment file, but I hope this may help some...
You can achieve this without creating an engine.
Add a file called lib/marxjs/script_inserter.rb
module Marxjs
module ScriptInserter
BODY_TAG = %r{</body>}
JS_SCRIPT = %q{
<script src='marx.js'></script>
<script>
var marx = new Marx()
</script>
}
def insert_marxjs
if (
response.content_type == 'text/html' &&
response.body.match(BODY_TAG)
)
response.body = response.body.gsub(BODY_TAG, JS_SCRIPT + '\\0')
end
end
end
end
Add lib/marxjs/railtie.rb
module Marxjs
class Railtie < Rails::Railtie
initializer "marxjs-rails" do |app|
ActionController::Base.send :include Marxjs::ScriptInserter
ActionController::Base.after_filter :insert_marxjs
end
end
end
Update lib/marxjs/rails.rb
require "marxjs/rails/version"
require "marxjs/view_helpers"
require "marxjs/script_inserter"
# move rails initialization code to railtie.rb
Add the gem to Gemfile
gem 'marxjs-rails', group: :development
The rack-mini-profiler gem does something like this, where it adds UI elements to your screen but only in development (by default). See https://github.com/MiniProfiler/rack-mini-profiler/blob/master/lib/mini_profiler_rails/railtie.rb
For me the best way is to add the engine on all environments, but require it separately on application.html.haml
:
= javascript_include_tag "mark.js" if Rails.env.development?
Be sure to add it to your config/application.rb as well to be compiled:
config.assets.precompile += %w( mark.js )
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With