Ruby / Rails: определение переменных из простого текста для обновления через форму - PullRequest
0 голосов
/ 26 октября 2010

Я создаю приложение, в котором пользователи могут редактировать свой собственный CSS (в синтаксисе SCSS ). Это прекрасно работает, однако, я в конечном итоге хочу, чтобы эти CSS-файлы были «программируемыми», чтобы пользователи, которые не знают CSS, могли редактировать их в основном виде. Как?

Если я могу пометить некоторые вещи как редактируемые, мне не нужно создавать невозможную схему базы данных. Например, у меня есть файл scss с именем style.scss:

// @type color
$header_bg_color: #555;

// @type image
$header_image: "http://someurl.com/image.jpg";

Тогда я могу сделать это:

SomeParser.parse(contents of style.scss here)

Это вернет хеш или что-то похожее из переменных:

{:header_bg_color => {:type => "color", :value => "#555"}, :header_image => {:type => "image", :value => "http://someurl.com/image.jpg"} }

Я могу использовать вышеупомянутый хеш для создания формы, которую может использовать начинающий пользователь для изменения данных и отправки. Я верю, что знаю, как выполнить GET и POST.

Как лучше всего создать / настроить свой собственный анализатор, чтобы я мог читать комментарии и извлекать «переменные» из этого? А потом снова легко обновить текстовый файл?

Другой возможный способ - что-то вроде этого:

o = SomeParser.new(contents of style.scss here)
o.header_bg_color #returns "#555"
o.header_image = "http://anotherurl.com/image2.jpg" # "updates" or replaces the old header image variable with the new one
o.render # returns the text with the new values

Заранее спасибо!

1 Ответ

0 голосов
/ 28 октября 2010

Я не использовал это полностью, но мои тесты проходят.Я думаю, что этого достаточно, чтобы понять идею :) Мне потребовалось несколько часов обучения, а затем еще несколько, чтобы реализовать его.

Кстати, я здесь не проводил никакой оптимизации.Для меня это не должно быть быстро

Посмотрите на мой файл спецификаций:

require 'spec_helper'

describe StyleParser do
  describe "given properly formatted input" do
    it "should set and return variables properly" do
      text = %{# @name Masthead Background Image
# @kind file
# @description Background image.
$mbc2: "http://someurl.com/image.jpg";

# @name Masthead BG Color
# @kind color
# @description Background color.
$mbc: #555;}
      @s = StyleParser.new(text)

      @s.mbc.name.should == "Masthead BG Color"
      @s.mbc.kind.should == "color"
      @s.mbc.description.should == "Background color."
      @s.mbc.value.should == "#555"

      @s.mbc2.name.should == "Masthead Background Image"
      @s.mbc2.kind.should == "file"
      @s.mbc2.description.should == "Background image."
      @s.mbc2.value.should == %Q("http://someurl.com/image.jpg")
    end
  end

  describe "when assigning values" do
    it "should update its values" do
      text = %{# @name Masthead Background Image
# @kind file
# @description Background image.
$mbc2: "http://someurl.com/image.jpg";}
      @s = StyleParser.new(text)
      @s.mbc2.value = %Q("Another URL")
      @s.mbc2.value.should == %Q("Another URL")

      rendered_text = @s.render
      rendered_text.should_not match(/http:\/\/someurl\.com\/image\.jpg/)
      rendered_text.should match(/\$mbc2: "Another URL";/)

      @s.mbc2.value = %Q("Some third URL")
      @s.mbc2.value.should == %Q("Some third URL")
      rendered_text = @s.render
      rendered_text.should_not match(/\$mbc2: "Another URL";/)
      rendered_text.should match(/\$mbc2: "Some third URL";/)
    end

    it "should render the correct values" do
      text_old = %{# @name Masthead Background Image
# @kind file
# @description Background image.
$mbc2: "http://someurl.com/image.jpg";}
      text_new = %{# @name Masthead Background Image
# @kind file
# @description Background image.
$mbc2: "Another URL";}
      @s = StyleParser.new(text_old)
      @s.mbc2.value = %Q("Another URL")
      @s.render.should == text_new
    end
  end
end

Затем следующие 2 файла:

# Used to parse through an scss stylesheet to make editing of that stylesheet simpler
# Ex. Given a file called style.scss
#
# // @name Masthead Background Color
# // @type color
# // @description Background color of the masthead.
# $masthead_bg_color: #444;
#
# sp = StyleParser.new(contents of style.scss)
#
# # Reading
# sp.masthead_bg_color.value # returns "#444"
# sp.masthead_bg_color.name # returns "Masthead Background Color"
# sp.masthead_bg_color.type # returns "color"
# sp.masthead_bg_color.description # returns "Background color of the masthead."
#
# # Writing
# sp.masthead_bg_color.value = "#555"
# sp.render # returns all the text above except masthead_bg_color is now #555;

class StyleParser
  def initialize(text)
    @text = text
    @variables = {}

    @eol = '\n'
    @context_lines = 3
    @context = "((?:.*#{@eol}){#{@context_lines}})"
  end

  # Works this way: http://rubular.com/r/jWSYvfVrjj
  # Derived from /1953110/rubinovyi-ekvivalent-grep-c-5-chtoby-poluchit-kontekst-strok-vokrug-sovpadeniya
  def get_context(s)
    regexp = /.*\${1}#{s}:.*;[#{@eol}]*/
    @text =~ /^#{@context}(#{regexp})/
    before, match = $1, $2
    "#{before}#{match}"
  end

  def render
    @variables.each do |key, var|
      @text.gsub!(/^\$#{key}: .+;/, %Q($#{key}: #{var.value};))
    end
    @text
  end

  def method_missing(method_name)
    if method_name.to_s =~ /[\w]+/
      context = get_context(method_name)

      @variables[method_name] ||= StyleVariable.new(method_name, context)
    end
  end
end
class StyleVariable
  METADATA = %w(name kind description)

  def initialize(var, text)
    @var = var
    @text = text
  end

  def method_missing(method_name)
    if METADATA.include? method_name.to_s
      content_of(method_name.to_s)
    end
  end

  def value
    @text.each do |string|
      string =~ /^\${1}#{@var}: (.+);/
      return $1 if $1
    end
  end

  def value=(val)
    @text.gsub!(/^\$#{@var}: .+;/, "$#{@var}: #{val};")
  end

  private

  def content_of(variable)
    @text.each do |string|
      string =~ /^# @([\w]+[^\s]) (.+)/
      return $2 if $1 == variable
    end
  end
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...