Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 干涸开始救援结束_Ruby On Rails_Ruby_Design Patterns - Fatal编程技术网

Ruby on rails 干涸开始救援结束

Ruby on rails 干涸开始救援结束,ruby-on-rails,ruby,design-patterns,Ruby On Rails,Ruby,Design Patterns,我有以下创建方法: def create ... grid = Tag.find_by_id(story[:tag_id]) or raise GridNotFoundError ... event = Event.find_by_id(story[:event_id]) or raise EventNotFoundError ... rescue GridNotFoundError flash.now[:error] = "Please se

我有以下创建方法:

def create
    ...
    grid = Tag.find_by_id(story[:tag_id]) or raise GridNotFoundError
    ...
    event = Event.find_by_id(story[:event_id]) or raise EventNotFoundError
    ...
  rescue GridNotFoundError
    flash.now[:error] = "Please select a category"
    @item = item
    @years = story[:years]
    @event_name = race[:name]
    @country = race[:country]
    @classification = race[:class]
    @events = Event.all
    @countries = Tag.countries
    @classifications = Classification.all
    @grids = Tag.grids.find(:all, :conditions => ["value != ?", "Channel Creation Grid"])
    render "home/race_updates"
  rescue EventNotFoundError
    flash.now[:error] = "Please select an event or create a new one if you don't find your event"
    @item = item
    @event = story[:event_id]
    @years = story[:years]
    @events = Event.all
    @countries = Tag.countries
    @classifications = Classification.all
    @grids = Tag.grids.find(:all, :conditions => ["value != ?", "Channel Creation Grid"])
    render "home/race_updates"
  rescue CreateEventError
    flash.now[:error] = "There has been a problem creating your event."
    params[:expand] = true
    @item = item
    @years = story[:years]
    @event_name = race[:name]
    @country = race[:country]
    @classification = race[:class]
    @events = Event.all
    @countries = Tag.countries
    @classifications = Classification.all
    @grids = Tag.grids.find(:all, :conditions => ["value != ?", "Channel Creation Grid"])
    render "home/race_updates"
  rescue ActiveRecord::RecordNotSaved, ActiveRecord::RecordInvalid, ActiveRecord::RecordNotFound
    flash.now[:error] = item.errors.full_messages.join(" ,")
    @item = item
    @event = story[:event_id]
    @years = story[:years]
    @events = Event.all
    @countries = Tag.countries
    @classifications = Classification.all
    @grids = Tag.grids.find(:all, :conditions => ["value != ?", "Channel Creation Grid"])
    render "home/race_updates"
  end
正如你所看到的,救援行动几乎是一样的。救援行动也是home#race#u updates方法的文字复制粘贴

我有两个问题:

  • 我有没有办法把它擦干
  • 一般来说,这是控制器的好模式吗
  • 我曾想过将它作为一个函数分离出来,但我需要传入flash消息、item、story和race变量。我觉得这不是一个优雅的解决方案,但肯定会更干净


    我发现,通过这种方式编码(即引发错误并挽救它们)可以更容易地将实际的业务逻辑分离开来,并处理业务逻辑中出现的不同错误/案例。到目前为止,它是有效的,但我想收集意见,看看这是最佳做法还是我没有按预期使用begin/rescue?

    如果它仍然100%正确,你必须自己验证,因为我可能遗漏了一些东西,但也许这就是你想要的

    def create
        ...
        grid = Tag.find_by_id(story[:tag_id]) or raise GridNotFoundError
        ...
        event = Event.find_by_id(story[:event_id]) or raise EventNotFoundError
        ...
    rescue Exception => e
        flash.now[:error] = e.is_a?(GridNotFoundError) ? "Please select a category" :
                            e.is_a?(EventNotFoundError) ? "Please select an event or create a new one if you don't find your event" : 
                            e.is_a?(CreateEventError) ? "There has been a problem creating your event." :
                            e.is_a?(ActiveRecord::RecordNotSaved) or e.is_a?(ActiveRecord::RecordInvalid) or e.is_a?(ActiveRecord::RecordNotFound) ? item.errors.full_mesages.join(", ") : e.to_s
        @item = item
        @years = story[:years]
        @event_name = race[:name] unless e.is_a?(EventNotFoundError) or e.is_a?(ActiveRecord::RecordNotSaved) or e.is_a?(ActiveRecord::RecordInvalid) or e.is_a?(ActiveRecord::RecordNotFound)
        @events = Event.all
        @countries = Tag.countries
        @classifications = Classification.all
        @grids = Tag.grids.find(:all, :conditions => ["value != ?", "Channel Creation Grid"])
        @event = story[:event_id] if e.is_a?(EventNotFoundError) or e.is_a?(ActiveRecord::RecordNotSaved) or e.is_a?(ActiveRecord::RecordInvalid) e.is_a?(ActiveRecord::RecordNotFound)
    
        if e.is_a?(GridNotFoundError) or e.is_a?(CreateEventError) 
            @country = race[:country]
            @classification = race[:class]
    
        end
    
        params[:expand] = true if e.is_a?(CreateEventError)
    
        render "home/race_updates"
    end
    

    如果您能够做到这一点,那么将其晾干是一个很好的想法,也是rails设计(以及测试驱动开发/TDD)中的一个很好的教训

    理想情况下,您可以这样做:

    def create
        ...
        grid = Tag.find_by_id(story[:tag_id]) or raise GridNotFoundError
        ...
        event = Event.find_by_id(story[:event_id]) or raise EventNotFoundError
        ...
      rescue GridNotFoundError
        flash.now[:error] = "Please select a category"
        process_grid_not_found(item, story, race, etc...)
      rescue EventNotFoundError
        flash.now[:error] = "Please select an event or create a new one if you don't find your event"
        process_event_not_found(item, story, race, etc...)
      rescue CreateEventError
        flash.now[:error] = "There has been a problem creating your event."
        process_event_create_error(item, story, race, etc...)
      rescue ActiveRecord::RecordNotSaved, ActiveRecord::RecordInvalid, ActiveRecord::RecordNotFound
        flash.now[:error] = item.errors.full_messages.join(" ,")
        process_other_error(item, story, race, etc...)
      end
      render 'home/race_updates'
    
    然后,您应该在模型中创建相关的新方法(
    process\u event\u not\u found
    等)作为单独的(可能是
    private
    )方法

    这两者都使代码更具可读性,但其最大的优点是更容易编写测试代码

    因此,您应该编写测试代码(使用
    test::Unit
    rspec
    或其他方法)来测试每个异常方法所需的独立功能。您会发现,这不仅可以生成更好的代码,而且还可以将异常方法分解为更小、更模块化的方法

    当您听到Ruby和Rails开发人员谈论测试驱动开发的好处时,这种方法的一个主要好处是,它不太可能产生像您在这里看到的那样长而复杂的方法。更可能的是,您的代码更加枯燥,使用更小、更简单的方法


    我还建议,一旦你完成了这个,你再看一眼,并尝试进一步简化它。简化的空间会更大,但我建议迭代重构,并从我所描述的分解开始,开始测试。

    我结合了Kevin Bedell的答案和Victor Moroz的见解,以及以下事实。我想到了这个:

    def create
        ...
        grid = Tag.find_by_id(story[:tag_id]) or (render_race_updates(item, "Please select a category") and return)
        ...
        event = Event.find_by_id(story[:event_id]) or (render_race_updates(item, "Please select an event or create a new one if you don't find your event") and return)
        ...
        if item.save
          ...
        else
          render_race_updates item, item.errors.full_messages.join(", ")
        end
      rescue CreateEventError
        params[:expand] = true
        render_race_updates item, "There has been a problem creating your event."
      end
    private
      def render_race_updates(item, message)
        flash.now[:error] = message
        # etc.
        render "home/race_updates"
      end
    
    这样,我就可以在不引发异常的情况下在线处理异常情况,同时捕获由其他方法引发的异常


    然而,我还没有编写测试。目前,我只编写单元测试。仍然掌握着RSpec的窍门,慢慢地将我的“wing it”开发更改为TDD,但这是一个完全不同的对话。

    谢谢!这是一个很好的起点。你对这是否是一个好方法有什么看法吗?-1当你只知道如何处理少数例外时,拯救所有例外是一个糟糕的想法。例如,此代码将无法生效!不是我的问题。他想为他的代码示例提供一个简单的解决方案,他得到了一个。并且您不会在RoR应用程序tbh中调用exit,这是他的。您需要
    raise
    做什么?这可以通过正常的流量控制(
    if
    case
    )以及将分支逻辑分离成更小的方法来实现
    raise
    用于异常,而不是流控制。@维克托:在web应用程序的上下文中如何使用raise?我根本不会使用
    raise
    ,在某些罕见的情况下,它可能用于深度嵌套的方法。@Victor:我发现使用正常的流控制来处理错误(
    if
    case
    )很快就会变得笨拙。或者这意味着我应该重构它吗?我接受了你的建议,并将其与Victor Moroz的结合起来进入TDD是另一回事。很高兴我能帮上忙!如果我的回答有用,请投赞成票和/或接受!谢谢