从另一个类访问Sinatra范围

时间:2011-04-04 19:56:25

标签: ruby scope sinatra

我正在运行一个Sinatra应用程序,其中包含一些额外的类,用于创建用户和其他一些用户(没有数据库,它从Web服务提供)。我正在尝试从我的用户模型中发送一个闪存通知(使用https://github.com/nakajima/rack-flash),但无法弄清楚如何访问flash方法/变量,因为我已超出范围。

类似的东西:

class User
  def something
    if true
      flash[:notice] = 'Good job'
    else
      # nope
    end
  end
end

通过简单的require 'models/user'

进入Sinatra应用程序

2 个答案:

答案 0 :(得分:2)

这是一个XY问题[1]。 Sinatra负责发送Flash消息,而不是您的User对象,因此设置Flash的代码应该在Sinatra应用程序中,而不是在User类中。

[1] http://www.perlmonks.org/index.pl?node_id=542341

答案 1 :(得分:1)

您不应要求您的用户(型号)与UI(视图)对话。这很糟糕/不是MVC清洁。这就是控制器的用途。

您可以使用返回值,例外或throw/catch(非异常处理)将信息从模型传递到控制器。例如,使用返回值:

post "/create_user" do
  flash[:notice] = case User.something
    when User   then "User Created!"
    when :nono  then "That's not allowed"
    when :later then "User queued to be created later."
  end
end

class User
  def self.something
    if authorized
      if can_create_now
        new(...)
      else
        queue_create(...)
        :later
      end
    else
      :nono
    end
  end
end

自从我在上面提到它们之后,以下是使用 throw / catch begin / rescue (例外)的示例。由于使用其中任何一种结构的可取性值得怀疑,如果这是一个好主意,让我们花一点时间沉默思考。


以下是使用 throw / catch

的示例
post "/create_user" do
  result = catch(:msg){ User.something }
  flash[:notice] = case 
    when :nono  then "That's not allowed"
    when :later then "User queued to be created later."
    else             "User Created!"
  end
end

class User
  def self.something
    throw :msg, :nono unless authorized
    if can_create_now
      new(...)
    else
      queue_create(...)
      throw :msg, :later
    end
  end
end

最后,这是使用例外的示例,但我不相信这适用于您希望向用户发送唯一消息的所有(非灾难性)情况:

post "/create_user" do
  flash[:notice] = "User Created!" # Assume all good
  begin
    User.something
  rescue User::Trouble=>e
    flash[:notice] = case e
      when Unauthorized  then "That's not allowed"
      when DelayedCreate then "User queued to be created later."
      else                    "Uh...Something bad happened."
    end
  end
end

class User
  class Trouble < RuntimeError; end
  class Unauthorized  < Trouble; end
  class DelayedCreate < Trouble; end
  def self.something
    raise Unauthorized unless authorized
    if can_create_now
      new(...)
    else
      queue_create(...)
      raise DelayedCreate
    end
  end
end

例外允许您传递其他数据(例如raise Unauthorized.new "No such account"或您要添加到类中的任何自定义属性),因此可能更有用(适当时)。只需记住将模型中的语义结果传递给控制器​​,然后将其转换为面向用户的消息。