I have an Informations
model which has a plain_keywords
attribute. When this attribute is updated, I would like to precompile my SASS stylesheets because there is a certain SASS variable which is computed in terms of this attribute.
This question seemed similar to mine so I did this:
Gemfile
gem 'rake'
config/initializers/rake.rb
Rake.load_rakefile Rails.root.join('Rakefile')
app/models/informations.rb
require 'rake'
class Informations < ApplicationRecord
after_save :precompile, if: :plain_keywords_changed?
private
def precompile
Rake::Task['assets:precompile'].invoke
end
end
The precompile
method is actually called when the plain_keywords
attribute is updated, but my stylesheets look unchanged.
Do you have any idea ?
Edit:
To answer the question Why do I want to do that ?, the keywords contained in the plain_keywords
attribute are animated by CSS to make them scroll. But the animation need to have a $keywords-length
SASS variable to be computed, in order to be perfectly homogeneous and with the same duration for each keywords.
I got that it is actually a wrong idea to precompile my stylesheets each time this attribute is updated.
So I created a stylesheets controller which has a keywords
action. It generates just the dynamic part of the CSS animation:
class StylesheetsController < ApplicationController
def keywords
length = Informations.first.keywords.length # There is only one record for Informations
duration = 2.0
transition = 0.4
height = 40
animation_duration = (duration + transition)*length
css = '.keywords strong {animation: keyword '+animation_duration.to_s+'s infinite}'
length.times do |n|
css += '.keywords strong:nth-of-type('+(n + 1).to_s+'){animation-delay:'+(-n*(transition + duration)).to_s+'s}'
end
css += '@keyframes keyword{'
[
{
p: 0,
properties: {
opacity: 0,
transform: 'translateY('+((-height).to_s)+'px) rotateX(90deg)',
:'transform-origin' => 'center bottom'
}
},
{
p: transition/animation_duration,
properties: {
opacity: 1,
transform: 'translateY(0) rotateX(0)',
:'transform-origin' => 'center bottom'
}
},
{
p: (transition + duration)/animation_duration,
properties: {
opacity: 1,
transform: 'translateY(0) rotateX(0)',
:'transform-origin' => 'center top'
}
},
{
p: (transition*2 + duration)/animation_duration,
properties: {
opacity: 0,
transform: 'translateY('+height.to_s+'px) rotateX(-90deg)',
:'transform-origin' => 'center top'
}
},
{
p: 1,
properties: {
opacity: 0,
transform: 'translateY('+height.to_s+'px) rotateX(-90deg)',
:'transform-origin' => 'center top'
}
}
].each do |keyframe|
css += (keyframe[:p]*100).to_s+'%{'
css += keyframe[:properties].to_a.map{ |v| v.join ':' }.join ';'
css += '}'
end
css += '}'
render text: css, content_type: 'text/css'
end
end