Reputation: 185
I'm running a Sinatra application with a few extra classes pulled in for creating a User and a few others on the fly (no DB, it feeds in from a web service). I'm trying send out a flash notice (using https://github.com/nakajima/rack-flash) from within my User model but can't figure out how to get access to the flash method/variable because I'm out of scope.
Something like:
class User def something if true flash[:notice] = 'Good job' else # nope end end end
Which gets required into the Sinatra app by a simple require 'models/user'
Upvotes: 2
Views: 595
Reputation: 303244
You should not ask your User (model) to talk to the UI (view). That's bad/not MVC-clean. That's what a controller is for.
You can use either return values, exceptions, or throw/catch
(which is not exception handling) to pass information from your model to your controller. For example, using return values:
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
Since I mentioned them above, following are examples using throw/catch and begin/rescue (exceptions). As the advisability of using either of these constructs is questionable, let us take a moment of silence to ponder if this is a good idea.
Here is an example using 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
Finally, here's an example using exceptions, though I'm not convinced that this will be appropriate for all (non-disastrous) cases where you want to flash unique messages to the user:
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
Exceptions let you pass an additional data along (e.g. raise Unauthorized.new "No such account"
, or any custom properties you want to add to your class), and so may be more useful (when appropriate). Just remember to pass semantic results from your model to your controller, and let it translate them into user-facing messages.
Upvotes: 1
Reputation: 15605
This is an XY Problem[1]. Sinatra is responsible for sending out flash messages, not your User objects, so the code for setting the flash should be in your Sinatra app, not in your User class.
[1] http://www.perlmonks.org/index.pl?node_id=542341
Upvotes: 2