Mathieu Mathieu - 1 month ago 16
Ruby Question

Rails - Store html templates in filesystem or database

I'm building what can be described as a CMS (at least on some parts it operates as a CMS).

I read that "of course you should never put html code in the database" but reading this and seeing some actually do it (this gem, or here), I am doubting the best way to solve my problem.

Below is explained my current issues with my current solution. Maybe the best way is to put it in database, maybe it's to keep in filesystem but in anotherway than what I do.

The administrators of the back office (on Active Admin) I build (ie: developers but also "marketers" => not the general public/internet visitors) can go to Active Admin and create "Modals".

For example I can create in Active Admin's 'create new Modal' a modal like this: name =>"Mix of 2 texts, 1 image, 1 video" and components => { text1, text2, image1, video 1 }

This will create in my table 'Modals' a new modal

id= 37 (it's an example), name: "Mix of 2 texts, 1 image, 1 video", components = components => { text1, text2, image1, video 1 }


Then in active Admin, the administrator can go and create a new 'Page' (there's a Page model too in my database):
He can set for example
title: "example of title"
modals: there he will choose in a select drop down one of the modals. Let's say now he chooses the modal 37.
Active Admin will then ask him, ok then please choose the following components for this modal which are (important: the app asks him this because I stored in the database Modal table that the components for modal = 37 are text1, text2, image1 and image2):



This will create in Active Admin a Page id=8 (example) and in the database Page has an attribute column 'Modal' that will look like this

Page.modal(:id =>8) =
[{"modal_id":"37",
"text1":"this is the intro sentence","text2":"some text",
"image1": "http://example.com/image1.png",
"image2":"http://example.com/image2.png"},
{ here we could have another modal for the same Page}
]


So when the internet users will load the Page id = 8, and user clicks on a specific butto, it will load modal 8.

The code on page.html.erb

<% @page.modal.each_with_index do |modal, index| %>
<% index_plus_one = index + 1 %>

<div>
<span onclick="loadModalContent<%= modal['modal_id'] %>()">
<i class="fa fa-camera" aria-hidden="true"></i>
</span>
</div>
<script>
function loadModalContent<%= modal['modal_id'] %>() {
var msg;
msg = Messenger().post({
message: '<%= j render partial: "pages/modal#{ modal['modal_id'] }",
locals: { modal: modal, index: index_plus_one } %>'
});
}
</script>
<% end %>


As you see, now the user clicked on the button, and the app will look into the column 'modal' and will check the first in the array which is an id= 37. so as a developer, when a new template is created in the back office (active admin), we must create a new partial _modal37.html.erb in the filesystem with the correct id:

_modal37.html.erb

<div>this is the first text <%= modal['text1'] %></div>
<div>this is the first image : <%= modal['image1'] %></div>
<div>this is the second text <%= modal['image1'] %></div>
<div>this is the second image <%= modal['image 2'] %></div>


Coming back to my internet user who loaded Page 8 and then clicked the button, the app will load the modal's content by loading partial _modal37.html.erb.

So all is working well today :) and even though there are some risks (not the scope of the question but if administrators of the Back office ( Active Admin )change the structure of the modal, then we have in the file system also to change it, for example they add a 'image3'...), but my main problem is the following:

It's how to coordinate and keep this system while not breaking the LOCAL environment / PRODUCTION environment development.

Indeed, maybe you did not notice but there is a big issue. I know because I faced it:)

When I did all the above, I was in LOCAL development. This means that I created in my filesystem a partial _modal37.html.erb. But the problem is that in production, who knows, maybe the 37th created modal will not have the same structure, maybe it will be (text1, video1) and no image and so in production the partial _modal37.html.erb must be different than the one I used in local mode.

So if I keep things like now, I need to be VERY rigorous , almost god-strict level, and I think this shows me this solution is not right: I 'd need every time


  • if i create in the local 'active admin' a new modal (let's say the newly created has id=37)

  • create in my filesystem the partial _37.html.erb

  • go into the active admin in Production and create the SAME modal (for Modal model) which will be also hopefully 37 if from the beginning of time i have replicated each time what I do in local, also in Production...



If i follow this EVERY single time, local and production will always be sync' and have the same id/components but it's hell:)

Same when I do Deletes or Edit make any change in local Active Admin the structure of a Modal, I must do it in Production too...That's never ending and not realistic to comply with:)

So what should I do ?


  • put the html template in database, instead of having it inside my partials ? How to, in that case, to tell Rails to execute the code inside the database: 'this is the first text <%= modal['text1'] %>'. how would the database "understand"/be "conscious" that each modal in <%= modal['text1'] %> is inside the ruby loop you can see in 'page.html.erb' above ? Hard...

  • keep the set up like today and put the html modal content in the partials: how to solve my very "logistic" local/production coordination problem ?


Answer

How about you have a modal object that has_one :template? The template in this case is a linked list of the partials that you want with it's arguments.

Example:

 Modal.first.template
 # => {1: [
 #         [partial1, {user: 12, pet: 'dog'}], 
 #         [partial3, {title: "Hello world}]
 #        ], 
 #     2: [
 #         [partial7, {text: 'This is the intro sentence}]
 #        ], 
 #     ...
 #     }

So now, as long as your options and the variables match up and the partial's name doesnt change, youre good to go. The maintenance does seem high but I dont see how your local/production servers would be out of sync this way.

The database then would not need to hold any HTML as long as it knew the name of the partials or perhaps the route to the partial.