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方法的文字复制粘贴
我有两个问题:
我发现,通过这种方式编码(即引发错误并挽救它们)可以更容易地将实际的业务逻辑分离开来,并处理业务逻辑中出现的不同错误/案例。到目前为止,它是有效的,但我想收集意见,看看这是最佳做法还是我没有按预期使用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是另一回事。很高兴我能帮上忙!如果我的回答有用,请投赞成票和/或接受!谢谢