Rails 7引擎如何使未编译的样式表可用于宿主应用程序



所以我有一个文件未找到的问题。我在引擎测试/虚拟应用程序中有一个以开发模式工作的引擎,该引擎允许编辑sass变量并将其存储在主题表中,变量由sass分部(如_banner.scss(使用,该分部包含主样式表中使用的变量(如$banner_color(,然后将其导入主样式表,主样式表又使用engine.rb文件中的初始值设定项进行预编译,并包含在app/config/engine_name_manifest.js中。

这些文件都可以在本地虚拟应用程序的开发中使用,但由于正在编译资产,因此无法在最终的主机应用程序中使用。

我有一个rake任务,它获取数据,用主题表中的数据更新相关的部分,例如_banner.scs,但当然,这些部分在主机应用程序中不可用,因为引擎已经编译了它们。我正在寻找一个解决方案,允许我编辑原始的、未编译的样式表,然后重新编译它们。显然,我的Capistrano部署脚本需要在每次部署时重新应用样式表更改,但这只是一个rake任务调用。我应该采取什么方法?我应该在引擎初始化器中找到将css文件复制到主机应用程序的方法吗?如果我使用完全不同的方法,我已经开始考虑传动轴,但这是取代sass导轨的重要一步,我不确定这将如何帮助

发动机

require "deface"
require 'ccs_cms_admin_dashboard'
require 'ccs_cms_custom_page'
require 'ccs_cms_core'
require 'css_menu'
#require 'tinymce-rails'
require 'delayed_job_active_record'
require 'daemons'
require 'sprockets/railtie'
require 'sassc-rails'
module CcsCms
module PublicTheme
class Engine < ::Rails::Engine
isolate_namespace CcsCms::PublicTheme
paths["app/views"] << "app/views/ccs_cms/public_theme"
initializer "ccs_cms.assets.precompile" do |app|
app.config.assets.precompile += %w( public_theme_manifest.js )
end
initializer :append_migrations do |app|
unless app.root.to_s.match?(root.to_s)
config.paths['db/migrate'].expanded.each do |p|
app.config.paths['db/migrate'] << p
end
end
end
initializer :active_job_setup do |app|
app.config.active_job.queue_adapter = :delayed_job
end
config.to_prepare do
Dir.glob(Engine.root.join("app", "decorators", "**", "*_decorator*.rb")) do |c|
Rails.configuration.cache_classes ? require(c) : load(c)
end
end
config.generators do |g|
g.test_framework :rspec,
fixtures: false,
request: false,
view_specs: false,
helper_specs: false,
controller_specs: false,
routing_specs: false
g.fixture_replacement :factory_bot
g.factory_bot dir: 'spec/factories'
end
end
end
end

编写Css 的Css类

class Css
def get_stylesheet_path
Rails.root.join("app/assets/stylesheets/ccs_cms/public_theme")
end
def write_css(theme)
update_css_files_for(theme.banner, '_public_banner.scss', BANNER_ARRAY, BANNER_FIELD_MAP)
update_css_files_for(theme.banner.font, '_public_banner_font.scss', BANNER_FONT_ARRAY, BANNER_FONT_FIELD_MAP)
end
private
def update_css_files_for(model_record_to_use, css_file, array_to_use, field_map)
amended_css = amend_css_for(model_record_to_use, css_file, array_to_use, field_map)
create_css_files_for(css_file, amended_css)
end
def amend_css_for(model_record_to_use, file_name, array_to_use, field_map)
original_css_array = IO.readlines("#{get_stylesheet_path}/#{file_name}")
new_array = []
original_css_array.each do |line|
new_line = line
array_to_use.each do |ma|
if line.start_with?(ma)
field_name = field_map[ma.to_sym]
new_line = ma + ": #{model_record_to_use[field_name.to_sym]};"
#puts("@@@@ original line: #{line}, ma: #{ma}, Field name: #{field_name}, value: #{theme[field_name]}")
break
end
end
new_array << new_line
end
new_array
end
# ---- File and I/O Handling ---- #
def create_css_files_for(file_name, css_array)
File.open("#{get_stylesheet_path}/#{file_name}", "w") do |file|
file.puts css_array
end
end
end

感谢您的澄清。如果我理解正确的话,我对它的看法。

部分在主机应用程序中不可用,因为引擎已经编译了

Partials仍然存在,预编译只是将*.{css/js}文件输出到app/assets/config/manifest.js中声明的public/assets/中。

要获取引擎文件,请使用而不是Rails.root

CcsCms::PublicTheme::Engine.root

Css类中,例如:

def get_stylesheet_path
CcsCms::PublicTheme::Engine.root.join("app/assets/stylesheets/ccs_cms/public_theme")
end

支持更改主题引擎。主题根可以在引擎初始值设定项中设置为类似Rails.configuration.theme_root的内容,并在主应用程序中使用。

因为您的主题也是可配置的,所以我认为最好读取主题的原始sass文件,但不要修改它们,将它们复制到tmp文件夹中,并使用主题表中的值进行更新,然后在主应用程序中使用sass输出theme.css。https://sass-lang.com/documentation/cli/dart-sass

​# Compiles all Sass
$ sass tmp/theme/application.scss:app/stylesheets/theme.css

然后让Rails接管预编译过程。

另一种选择是有一个sass配置文件,并且只更新这个文件。这样就不依赖于任何特定主题的文件结构。

import 'configuration' // sass variables with values from theme table
import 'banner'        // uses sass variables only
...

此外,如果可以的话,只需使用css变量,并避免所有上述复杂性;主题表更改时不进行预编译,也不进行重新部署。

为css变量更新

只是为了让我们在同一页上。我指的是这些css变量:https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties.如果Internet Explorer不是您的优先选择,这是最好的解决方案。设置是这样的:

<!-- app/views/layouts/application.erb -->
<!-- NOTE: with turbo this loads only once; full page refresh is needed when @theme changes -->
<head>
<style>
:root { --text-color: <%= @theme.text_color %>; }
</style>
<%= stylesheet_link_tag 'application' %>
</head>
/* app/assets/stylesheets/application.css */
p { color: var(--text-color); }

可能的修复程序可以避免修改css文件。在sass文件中使用erb插值。无需每次更改主题配置时都进行修改。在开发过程中,动态编译。在生产中,当主题配置发生更改时,必须重新进行预编译;没有修改。

// _banner.scss.erb
p { color: <%= Theme.text_color %>; }

您甚至可以使用amend_css_for函数来插入文字erb代码,从而节省一些时间。例如

new_line = ma + ": <%= Theme.#{model_name}.#{field_name} %>;" 

最后,如果您不想接触引擎文件,并且因为这些文件不是主/主机应用程序的一部分(就像文件系统中的两个单独文件夹一样(。修改时必须复印一份;从CCD_ 10读取到CCD_。

def get_stylesheet_path
CcsCms::PublicTheme::Engine.root.join("app/assets/stylesheets/ccs_cms/public_theme")
end
# but save to main app
def create_css_files_for(file_name, css_array)
File.open("#{Rails.root.join("app/assets/stylesheets/ccs_cms/public_theme")}/#{file_name}", "w") do |file|
file.puts css_array
end
end

最新更新