Trouble understanding controllers
mrtryhard opened this issue · comments
Hi,
I started (finally) to write my website with Moonshine, and I have little trouble understanding how the controllers work. Note that I am coming from a C# ASP MVC 4 background and I have absolutely , therefore I am used to something that looks like:
HomeController < BaseController
# index is returned by "/Home" and "/Home/index"
def index
end
#. . .
I tried several things such as binding like this :
@router = {
"GET /Home" =>
->(req : Request) { index() },
"GET /Home/index" =>
->(req : Request) { index() }
} of String => (Request -> Response)
But it didn't work. Any help would be greatly appreciated !
Thanks
you have to override the call method of the controller too
Like this
def call(req : Moonshine::Request)
@router.each do |route, block|
if Route.new(route.split(" ")[0],
route.split(" ")[1]).match? req
return block.call(req)
end
end
return Moonshine::Response.new(404, "unhandled route on controller")
end
This is because, by default, a Controller object responds to http verb methods (get, post, etc).
I will sort out this controller mess as soon as possible.
In the mean time, check examples/restful.cr for a better way to do controllers (It doesn't involve the controller class).
Okay, now I'm at home, so I got real code with me.
HomeController:
class HomeController < Moonshine::Controller
def initialize()
@viewcount = 0
@router = {
"GET /Home" =>
->(req : Request) { index() },
"GET /Home/index" =>
->(req : Request) { index() }
} of String => (Request -> Response)
end
def call(req : Request)
@router.each do |route, block|
if Route.new(route.split(" ")[0],
route.split(" ")[1]).match? req
return block.call(req)
end
end
return Response.new(404, "unhandled route on controller")
end
def index()
ok("test")
end
# Override individual HTTP methods
def get(req)
@viewcount += 1
ok("This page has been visited #{@viewcount} times.")
end
end
Then I have my app.cr :
app = Moonshine::App.new
app.controller([
"/",
"/Home"
] of String, HomeController.new)
app.run
When I do access "localhost:8000/" it returns "test"
When I do access "localhost:8000/Home" => page not found
When I do access "localhost:8000/Home/index" => page not found
Perhaps I am missing something ?
Thanks
With the help of the restful example, I've got something working:
app.cr
home_cont = HomeController.new
routes = {
"GET /home" =>
->(req : Request) {
home_cont.index
},
"GET /home/index" =>
->(req : Request) {
home_cont.index
},
"GET /" =>
->(req : Request) {
home_cont.index
}
} of String => Request -> Response
app.add_router(routes)
app.run
HomeController:
class HomeController < Moonshine::Controller
def initialize()
@viewcount = 0
end
def index()
ok("test")
end
end
It gives the exact result I am wishing for. Now, if it's the way to accomplish it, I don't know, but for now, it works for my mini web app :^)
Thanks !
P.S. I'm open to do it any way you feel is better
Use this pattern for defining controllers
class HomeController < Moonshine::Controller
actions :index # Do this for each controller method
@router = { # Routing logic
"GET /home" => "index",
"GET /home/index" => "index",
"GET /" => "index",
}
def initialize
@viewcount = 0
end
def index(req) # Make sure this takes a request argument
ok("test")
end
end
app = App.new
app.controller(HomeController.new)
I think it's readable enough. Can I close this now?
Sure, it is more than readable, understandable, and easy.