【问题标题】:Rails4 How to define variable values in before_filter or private action when define in other UI process method?Rails4 在其他 UI 处理方法中定义时如何在 before_filter 或私有操作中定义变量值?
【发布时间】:2014-12-05 19:34:46
【问题描述】:

我发布了一个关于如何在同一控制器中跨操作共享变量的问题。我发现这个 Q/A 主要回答了我的问题,但仍然在此提交中提出了一个悬而未决的问题。 这是我发现的可能对其他人有帮助的问答链接:Same instance variable for all actions of a controller

这是我最初用上面的链接回答的问题的链接:In Rails4 How to assign variables in one controller action and use the value of it in another controller action

现在我知道我可以使用 before_filter 并创建一个私有操作,然后可以从控制器中的各种操作中引用该操作,这对于已知的常量变量似乎非常有用,我如何在我的特定情况下设置它值会根据用户操作而变化并被定义 在用户交互动作中?

我有一个名为“evaluate_media”的方法。此方法允许用户从各种目录路径中选择文件,然后在所选视频文件上运行媒体信息,并解析 xml 的某些属性(如比特率、aspect_ratio)并将值分配给操作中的变量。有什么方法可以在此操作中与其他操作(如 common_components)共享查找和分配的变量,而不是私有的并且仅用于变量分配?你能告诉我一个如何做到这一点的例子吗?我确实尝试了 before_filter ,它甚至没有调用插入。它只是刷新页面。 before_filter :evaluate_media, :only => [:save_file]

就像我第一个问题的复习一样,在我在评估媒体操作中收集此信息后,我有一个保存按钮,该按钮调用 save_file 方法,该方法将存储在评估媒体操作中收集的此信息。

这里有两个定义的方法:

def save_file    

        src_location = @radio_button_value
        directory = "#{@dir_path_choice}"
        full_path = @filepathname
        full_filename = "#{@filepath}"
        alias_code = "#{@file_alias}"
        validate_status = "#{@file_status}" 
        error_msg = "#{@file_msg}"
        video_alias_match = "#{@msg_dtl1}" 
        audio_alias_match = "#{@msg_dtl2}" 
        video_format = "#{@video_format}" 
        video_bitrate = "#{@video_bitrate}" 
        video_width = "#{@video_width}"
        video_height = "#{@video_height}" 
        video_framerate = "#{@video_framerate}" 
        video_aspect_ratio = "#{@video_aspectratio}" 
        video_scan_type = "#{@video_scantype}"
        video_scan_order = "#{@video_scanorder}" 

        @file_alias_tfile = FileAliasTfile.new( :src_location => src_location, :directory => directory, :full_path => full_path, :full_filename => full_filename, :file_ext => '', 
                                                      :assigned_status => 'Unassigned', :file_status => 'Saved', :alias_code => alias_code, :validate_status => validate_status, :error_msg => error_msg, 
                                                      :video_alias_match => video_alias_match, :audio_alias_match => audio_alias_match, :video_format => video_format, :video_bitrate => video_bitrate, 
                                                      :video_width => video_width, :video_height => video_height, :video_framerate => video_framerate, :video_aspect_ratio => video_aspect_ratio, 
                                                      :video_scan_type => video_scan_type, :video_scan_order => video_scan_order, :video_alias_code => '', :audio_alias_code => '', 
                                                      :bus_prod_initiative_id => 0, :status => 'Active', :start_date => DateTime.now.to_date, :end_date => '', :deleted_b => 0, 
                                                      :created_by => 'admin', :updated_by => 'admin')


    if @file_alias_tfile.save
      redirect_to mainpages_home_path, :notice => "The file alias validation has been saved."
    else
      redirect_to alias_mainpages_home_path, :notice => "The file alias validation has not been saved."
    end
  end

 def evaluate_media

     @state = 'post'
     @radio_button_value = params[:location]

     @stored_file = FileAliasTfile.where(:full_path => params[:filepath2], :deleted_b => 0).first

     if @stored_file.present?
        @file_exists_flag = 'Y'
        @file_exists_msg = 'This File and Alias has been saved in application.'
     else
        @file_exists_flag = 'N'
        @file_exists_msg = 'This File and Alias has NOT been saved in application yet.'
      end

          root_dir = '/watchfolder/miniprod/hot/'
          provider_dir = ""

       @selected_filepath = params[:filepath2]
       @filepath = params[:filepath2]

       @media_xml = ::MediaInfo.call(@filepath)  
       @alias_xml = ::AliasGenerator.call(@media_xml)

       @media_xml_for = ""
       @alias_xml_for = ""
       REXML::Document.new(@media_xml).write(@media_xml_for, 1)
       REXML::Document.new(@alias_xml).write(@alias_xml_for, 1)
       alias_parse_doc = ""
       media_parse_doc = ""
       alias_parse_doc = REXML::Document.new(@alias_xml)  
       media_parse_doc = REXML::Document.new(@media_xml) 


       #parse Alias XML Doc   
       @aliasgen_ver = REXML::XPath.each(alias_parse_doc, "/aliasGenerator vr=/text()") { |element| element }    
       @file_alias = REXML::XPath.each(alias_parse_doc, "*//alias/text()") { |element| element }
       @file_status = REXML::XPath.each(alias_parse_doc, "*//error/text()") { |element| element }
       @file_msg = REXML::XPath.each(alias_parse_doc, "*//error_m/text()") { |element| element }
       @msg_dtl1 = REXML::XPath.each(alias_parse_doc, "*//closestvideoalias/text()") { |element| element }
       @msg_dtl2 = REXML::XPath.each(alias_parse_doc, "*//closestaudioalias/text()") { |element| element }

       #parse Video Media Info XML Doc  
        @filepathname = REXML::XPath.each(media_parse_doc, "*//Complete_name/text()") { |element| element }  
        @video_format = REXML::XPath.each(media_parse_doc, "//track[@type='Video']/Format/text()") { |element| element }
        @video_bitrate = REXML::XPath.each(media_parse_doc, "//track[@type='Video']/Bit_rate/text()") { |element| element }  
        @video_width = REXML::XPath.each(media_parse_doc, "//track[@type='Video']/Width/text()") { |element| element } 
        @video_height = REXML::XPath.each(media_parse_doc, "//track[@type='Video']/Height/text()") { |element| element }
        @video_aspectratio = REXML::XPath.each(media_parse_doc, "//track[@type='Video']/Display_aspect_ratio/text()") { |element| element } 
        @video_framerate = REXML::XPath.each(media_parse_doc, "//track[@type='Video']/Frame_rate/text()") { |element| element } 
        @video_scantype = REXML::XPath.each(media_parse_doc, "//track[@type='Video']/Scan_type/text()") { |element| element } 
        @video_scanorder = REXML::XPath.each(media_parse_doc, "//track[@type='Video']/Scan_order/text()") { |element| element }   

       render :action => :index
   end

【问题讨论】:

    标签: variables ruby-on-rails-4 model-view-controller


    【解决方案1】:

    如何在我的特定情况下设置它 关于用户操作并在用户交互操作中定义?

    如果您在多个操作中执行相同的计算,并且唯一改变的是计算中使用的某个值,那么您不必在两个或更多操作中编写本质上相同的代码,您可以创建一个方法计算:

    def do_calculation(val1, val2)
      #Use val1 and val2 to perform some calculation
      result
    end 
    

    如果你把那个方法放在你的控制器中,那么这个方法就可以在任何动作中被调用。将方法设为私有的原因是没有路由可以访问该方法。因为没有路由可以命中该方法,所以该方法不称为动作——它只是称为辅助方法。这就是它的样子:

    class YourController < ApplicationController
    
      def index
        @files = do_calculations(params[:a], params[:b])
      end
    
      def show
        @files = do_calculation(params[:b], params[:c])
      end
    
      private
        def do_calculation(val1, val2)
          #Use val1 and val2 to perform some calculation...
          result
        end 
    
    end
    

    Rails 4 有一种更复杂的方法来做同样的事情——它涉及将辅助方法放在另一个文件中。在你的 app/controller/ 目录下,有一个名为关注/的目录,你可以这样做:

    app/controllers/concerns/file_methods.rb:

    module FileMethods
      extend ActiveSupport::Concern
    
      def do_calculation(x, y)
        x*y
      end
    end
    

    然后在你的控制器中,你这样做:

    class YourController < ApplicationController
      include FileMethods
    
      #Then you can call do_calculation() in any of the actions
    
    end
    

    如果您这样做,其他控制器也可以包含 FileMethods 模块,因此这种方式更加灵活。此外,由于它扩展了 ActiveSupport::Concern,因此您可以在 FileMethods 模块中执行其他操作。

    有什么方法可以共享查找和分配的变量 此操作与其他操作...而不是私有的?

    如果您说您的计算需要用户输入,因此 before_filter(Rails3)/before_action(Rails4) 将不起作用,并且您只想进行一次计算,那么这就是交易。网络是无状态的,这意味着每个请求开始时就好像它是第一个通过 Internet 发送的请求。 无状态 意味着没有状态,即变量,与后续请求共享。换句话说,一旦服务器完成处理请求,它就会删除与该请求相关的所有内容。因此,当您的浏览器询问“Server 先生,您能否检索上一个请求中的值并在此请求中使用它?”时,服务器会回复:“对不起,我不知道您在说什么。我有严重的失忆症,为此我很抱歉,但据我所知,你以前从未向我提出过​​要求。让我检查一下我的记录……不,这里什么都没有。抱歉,没有价值取回。再见。再来,随时。”

    无状态在 Rails 中的工作方式是,对于每个请求,rails 都会创建一个控制器实例,例如inst = YourController.new,然后 rails 调用 inst.actionA,这会创建在 actionA 中指定的 @variables,以及要 inst 的 @variables 本身。然后使用 inst 执行视图,这使得 inst 的 @variables 在视图中可用。对于后续请求,rails 执行inst = YourController.new 然后inst.actionB。结果,控制器的第一个实例与附加到实例的@variables 一起被删除。

    然而,事实证明,互联网的无状态特性给 Web 程序员带来了不便,因此人们发明了各种方案来使变量在请求之间保持不变。你听说过饼干吗? Cookie 用于在用户的计算机上存储小块数据,然后后续请求将该数据返回给服务器,因此 就像 在请求之间将值保留在服务器上。有一个更精细的方案称为 sessions,它允许您做同样的事情。通过 rails 中的会话,rails 会自动为您在用户计算机上设置 cookie。你所做的只是处理一个名为session 的对象,它是rails 自动为你创建的,就好像它是一个哈希一样。如果您在一个操作中(即针对一个请求)在 session 对象上设置了一个键/值对,则可以在另一个操作(即针对另一个请求)的会话对象中查找它。

    这是一个例子:

    class YourController < ApplicationController
    
      def action1
        val1 = params[:val1]
        val2 = params[:val2]
    
        #Use the user input to produce some data:
        dir_list = .........val1......val2.....
    
        session[:dir_list] = dir_list
      end
    
      def action2
        @dir_list = session[:dir_list] 
      end
    
    end
    

    但是...根据您最近提出的一系列问题,您可能希望查看以前问题的答案 - 从您的 ajax 问题开始。您可能会发现该问题的答案可以解决您现在尝试处理的许多问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-16
      • 2012-11-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多