Rails:在更新记录时以编程方式预编译资产

时间:2017-03-10 12:49:31

标签: ruby-on-rails ruby sass


我的Informations模型具有plain_keywords属性。更新此属性后,我想预编译我的SASS样式表,因为有一个SASS变量是根据此属性计算的。 This question似乎与我的相似,所以我这样做了:

的Gemfile

gem 'rake'


配置/初始化/ rake.rb

Rake.load_rakefile Rails.root.join('Rakefile')


应用程序/模型/ informations.rb

require 'rake'

class Informations < ApplicationRecord

    after_save :precompile, if: :plain_keywords_changed?

    private
        def precompile
            Rake::Task['assets:precompile'].invoke
        end
end


更新precompile属性时实际调用plain_keywords方法,但我的样式表看起来没有变化。

你有什么想法吗?

编辑:

要回答问题我为什么要这样做?plain_keywords属性中包含的关键字会被CSS(SASS)动画化以使其滚动。但是动画需要有一个$keywords-length SASS变量来计算,以便完全同质并且每个关键字的持续时间相同。

我的研究结果表明,每次更新此属性时,预编译样式表实际上是错误的。

所以我创建了一个stylesheets控制器,其keywords动作。它只生成我的CSS动画的动态部分。从控制器编译SASS真的很难(也许可能更慢)所以我决定直接生成CSS:

class StylesheetsController < ApplicationController
    def keywords
        length = Informations.get.keywords.length
        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

0 个答案:

没有答案