I am currently working through Michael Hartl’s Rails Tutorial while experimenting with some other things not covered in the book. After completing Chapter 5, where the static pages are created, I decided change the view code to HAML, internationalize the pages, and put the static content into separate (non-partial) Markdown files, using the RDiscount gem to render them. For example:
app/views/static_pages/about.html.haml
- provide(:title, t('.about_us'))
:markdown
#{render file: "static_pages/about.#{params[:locale]}.md"}
Under the static_pages directory, I have Markdown files like about.en.md, about.it.md, about.ja.md etc, so interpolating in the :locale parameter is what determines which language Markdown file gets rendered.
My questions are:
- The static_pages directory is a bit crowded with Markdown files, so are there any sensible default/best practice locations (perhaps outside of the app directory) to keep these Markdown files, where they could be presumably be edited by people who don’t need to know about the inner workings of the app?
- What better ways are there to implement rendering multi-lingual Markdown files in views? My use of
:localeand the double string-interpolation seems inelegant. -
Is there a way to change this code so that I can pass Ruby variables into the Markdown file? I know I can, for example, use a
#{language}variable in the Markdown by just changing about.en.md into a HAML partial (_about.en.html.haml) and change the code to look something like:app/views/static_pages/about.html.haml
- provide(:title, t('.about_us')) :markdown #{render "about.#{params[:locale]}", language: 'Markdown!'}But, is there a way to do this without changing the Markdown file into another type of file? If such a way exists, is it recommended/feasible?
After having a look at this StackOverflow answer, it seemed that the best location for i18n Markdown files would be their own action name directories under the config/locales directory, and that there was a good opportunity to refactor the
rendercode on all views for theStaticPagesController. So, using about.html.haml as an example below, the call torenderin the home, help, about, and contact views has been changed to the exact same code:app/views/static_pages/about.html.haml
The
localized_page_formethod is defined in theStaticPagesHelper:app/helpers/static_pages_helper.rb
So, now all the Markdown files have been taken out of the app/views/static_pages directory and are called from their respective logical directories (eg. config/locales/about/about.en.md etc) using
ActionController‘saction_nameattribute and the locale, making for less clutter.As for question 2 above, string-interpolation seems to be common enough for this kind of problem, so I’ll consider it “elegant” enough as well.
As for question 3 above, after exhaustive searching, I haven’t found a way anyone has passed in variables in to a pure Markdown file, and the documentation doesn’t seem to say anything about supporting them, so I’m going to conclude that it’s not possible. If passing Ruby variables in to Markdown is absolutely necessary, the file will need to be run through another interpreter, kind of like is described in this StackOverflow answer.
Update:
After running security scanner Brakeman against the app, it came up with a potential Dynamic Render Path security warning (albeit a weak one) due to dynamically passing in
params[:locale]to therendercall instead of passing it a static string. So, I moved the call to thelocalized_pagemethod out of the views, moved the method itself out of theStaticPagesHelper(so that file is now empty) and in to theStaticPagesControllerand then instantiated a@pageinstance variable in each method to pass to the view. In summary, the code now looks like this, which doesn’t get the security warning:app/controllers/static_pages_controller.rb
app/views/static_pages/about.html.haml