Creating FormTag as Shopify using Liquid Block

If you using Liquid Filter do you know the Shopify is reference to Ecommerce platform on the web and they created and using Liquid Markup

To create like the same behave using simple form ou form_for on the RoR using the Liquid do you must need to created a Liquid Block

In shopify’s explanation {% form ‘example’ %} is informed it only generate elements html to submit but looking carefully the shopify’s form tag does more than that.

a) add  the value post when the render is back

b) add “error” on the class element in the inputs

Screen Shot 2015-12-27 at 13.54.35

This is the way I generate html input with my form block

#/customers/new.html.liquid

{% form 'form_customer' %}
form id=create_customer method=post action=/customers accept-charset=UTF-8
  input type=hidden value={{ _csrf_token }} name=authenticity_token/
  input name=_method type=hidden value=post
  input type=hidden value= name=utf8/
  input name=customer[name] title=Please enter your username (at least 3 characters) type=text class=form-control placeholder=Enter name required minlength=3
{% endform %}

#form_tag.rb on gist

require 'i18n'

class FormTag < Liquid::Block
  Syntax     = /(#{Liquid::QuotedFragment})\s*(by\s*(\d+))?/
  def initialize(tag_name, markup, tokens)
     @param_name = Liquid::Expression.parse(markup).name.gsub(form_, )
     super
  end

  def form_nested(params, index, object, html_name)
    attribute = index.gsub(_attributes, )
    object = object.send(attribute)
    params[index].each do |index, key|
      html_name = html_name << [#{index}]
      element = @doc.at(input[@name='#{html_name}'])
      form_nested(params[index], index, object, html_name) if index.include?(attributes)
      form_error(object, index, element)
    end
  end

  def form_error(object, index, element)
    if object.respond_to?(index) and object.errors[index].any? and not element.nil?
      klass = element.get_attribute(:class)
      element.set_attribute(:class, error #{klass})
    end
  end

  def render(context)
    params = context.registers[:controller].env[rack.request.form_hash]
    unless params.nil?
      @object = context.registers[:action_view].assigns[@param_name]
      @doc = Hpricot(super)  # calling `super` returns the content of the block
      params[@param_name].each do |index, key|
        if params[_method].downcase == post
          html_name = #{@param_name}[#{index}]
          unless @object.valid?
            if index.include?(attributes)
              form_nested(params[@param_name], index, @object, html_name)
            else
              element = @doc.at(input[@name='#{html_name}'])
              form_error(@object, index, element)
            end
          end
          @doc.search(input[@name='#{@param_name}[#{index}]']).each do |element|
            element.set_attribute(:value, key) unless element.get_attribute(:type) == radio
          end
        else
          next
        end
      end
      @doc
    else
      super
    end
  end
end

Liquid::Template.register_tag('form', FormTag)