Ruby on rails 帮助器中的Rails表单块-如何包括“如何”;防止伪造”;

Ruby on rails 帮助器中的Rails表单块-如何包括“如何”;防止伪造”;,ruby-on-rails,forms,ruby-on-rails-4,liquid,csrf-protection,Ruby On Rails,Forms,Ruby On Rails 4,Liquid,Csrf Protection,我正在尝试为我的液体主题语言构建一个表单块。我的方法是基于。答案似乎是不完整的 问题是防伪和其他一些方法是不可用的。导致错误的原因: Liquid error: undefined method `protect_against_forgery?' for # 这是我的代码: class LiquidFormTag < Liquid::Block include ActionView::Context include ActionView::Hel

我正在尝试为我的液体主题语言构建一个表单块。我的方法是基于。答案似乎是不完整的

问题是防伪和其他一些方法是不可用的。导致错误的原因:

Liquid error: undefined method `protect_against_forgery?' for #
这是我的代码:

   class LiquidFormTag < Liquid::Block

        include ActionView::Context
        include ActionView::Helpers::FormHelper

        def initialize(tag_name, markup, tokens)

            super
        end

        def render(context)
            form_tag("#") do

                super
            end
        end
    end

    Liquid::Template.register_tag('liquid_form', LiquidFormTag)

方法
防止伪造
来自
ActionController::RequestForgeryProtection
模块。但是在class
Liquid::Block
中包含这个模块似乎不是一个好的做法

我使用的解决方案是:

class LiquidFormTag < Liquid::Block
  include ActionView::Context
  include ActionView::Helpers::FormHelper

  attr_reader :controller

  def initialize(tag_name, markup, tokens)
    super
  end

  def render(context)
    @controller = context.registers[:controller]
    form_tag('#') do
      super(context).html_safe
    end
  end

  delegate :form_authenticity_token, :request_forgery_protection_token, :protect_against_forgery?, to: :controller

end

Liquid::Template.register_tag 'liquid_form', LiquidFormTag
class LiquidFormTag
要执行此代码,您需要为液体渲染方法提供当前控制器:

class OffersController < ApplicationController

   def create
      @offer = Offer.new
      Liquid::Template.parse(template).render 'offer' => @offer, registers: {controller: self}
   end

end
class-OffersController@offer,寄存器:{controller:self}
结束
结束

我同意Rodrigo,但很难识别将被删除到控制器的方法名

这就是为什么我更喜欢扩展
Liquid::Block
类,并在响应时将缺少的方法委托给控制器

class LiquidFormTag < Liquid::Block
  include ActionView::Context
  include ActionView::Helpers::FormHelper

  attr_reader :controller

  def initialize(tag_name, markup, tokens)
    super
  end

  def render(context)
    @controller = context.registers[:controller]
    form_tag('#') do
      super(context).html_safe
    end
  end

end


Liquid::Block.class_eval do
  # This delegates missing - including private & protected - methods (like protect_against_forgery?) to controller.
  def method_missing(*args)
    begin
      if controller.respond_to?(args.first, true)
        controller.send(args.first)
      else
        super
      end
    rescue
      super
    end
  end
end
class LiquidFormTag
我这几天遇到了同样的问题,我用这种方法解决了:

class LiquidForm < Liquid::Block
  include ActionView::Context
  include ActionView::Helpers::FormHelper

  attr_reader :csrf_token

  def initialize(tag_name, markup, options)
   super
   @model = markup.strip
  end

  def render(context)
    csrf = context.registers[:csrf_token]

    form_tag "/new_obj", authenticity_token: false do
      "#{hidden_field_tag('authenticity_token', csrf)}
       #{super(context)}".html_safe
    end

  end
end
因为我们不能在
LiquidForm
类中调用它。我们需要手动生成令牌,就像我们的液体渲染方法中的这个方法一样。这可以在您的视图或控制器中。例如:

=Liquid::Template.parse(template).render('offer' => @offer, registers: {:csrf_token => session[:_csrf_token] ||= SecureRandom.base64(32)})

美好的差不多了。现在唯一的问题是表单内容呈现得很奇怪。输出中有t\r\n\r\n\r\n的分配。它说:控制器为零。是的。但是,液体块类可能会阻止它?或者你在液体块里也用这个?还有什么方法可以测试attr_阅读器是否工作?请用表单类和液体代码更新您的答案表单类是什么意思?你是指提供模型的位置吗?还要注意:我编写的代码与你的答案非常相似,因此如果:controller应该是我为其构建类的类控制器,那么这可能是错误的。
# File actionpack/lib/action_controller/metal/request_forgery_protection.rb, line 249
  def form_authenticity_token
    session[:_csrf_token] ||= SecureRandom.base64(32)
  end
=Liquid::Template.parse(template).render('offer' => @offer, registers: {:csrf_token => session[:_csrf_token] ||= SecureRandom.base64(32)})