Amber: render text / plain text in controller response?

Created on 16 Oct 2017  路  21Comments  路  Source: amberframework/amber

What is the amber equivalent of render text: 'asfasdf' (or in newer rails: render body: 'asdfasdf')? I need to render raw text as part of an API.

enhancement

Most helpful comment

My suggestion would be that we add them but don't require them.

class Amber::Controller::Base
  protected def text(body, status_code = 200)
    context.response.status_code = status_code
    context.response.content_type = "text/plain"
    # We need to use content instead of response.print so that we don't close down the response object before session are written, in chunking mode.
    context.content = body
  end
end

Then we can modify the controller proc to not set content from the return value if it's already been set.

@drujensen WDYT?

All 21 comments

def text_api
  "hello world!"
end

omg why didn't rails do it this way so simple!! :+1:

Yeah I love rails but this is definitely one of the things I wanted to do differently.

And don't forget response.content_type = "test/plain" or other Content-Type you need.

@c910335 is there a way I can do that in my base ApiController or do I need to do it in every single method. Also would super appreciate a JSON example?

Custom Pipe or Filters should be good for you.

Yeah. Just write a simple custom pipe to do that.

For JSON just write

def api_action
  {"name" => "elorest"}.to_json
end

Also make sure to set the response type to json.

excellent, thanks all

@sam0x17 Here's an example handler/pipe you could use to set content_types for you.

    class TextType
      include HTTP::Handler
      def call(context : HTTP::Server::Context)
        content.response.content_type = "test/plain"
        call_next context
      end
    end

@elorest thanks!

Don't know how anyone else feels about this, but for purposes of readability and ease of use it could be nice to have a similar functionality to Rails here by using the render method with a named json attribute. That way the render method could take the hash, variable, etc, apply to_json if necessary, set the content type, and render the json response.

@drujensen something like that would work. Did that code not get ported over when kemalyst became amber?

correct, Amber and Kemalyst had different approaches on this and it's been in discussion if we should port this more rails'ish style over or have the simpler style where you just return what you want as the body and use a handler or before filter to specify the content-type.

_[insert "why not both" gif here]_

I feel like it would be really nice to have the ease of using a helper function like that, but also have the ability to just return whatever I want. Maybe I just want to have my cake and eat it too haha.

My suggestion would be that we add them but don't require them.

class Amber::Controller::Base
  protected def text(body, status_code = 200)
    context.response.status_code = status_code
    context.response.content_type = "text/plain"
    # We need to use content instead of response.print so that we don't close down the response object before session are written, in chunking mode.
    context.content = body
  end
end

Then we can modify the controller proc to not set content from the return value if it's already been set.

@drujensen WDYT?

@elorest great idea.

For Web/REST API currently i create a class with method helper to handle http response.
Each controller api then inherits that class. It's inspired from aspnet API methods.
I set all response in json or plain text.

lass ApiController < Amber::Controller::Base
  protected def response(status_code : Int32 = 200, content = "")
      @context.response.status_code = status_code
      @context.content = to_json(content)
    end

    private def to_json(content : String | NamedTuple)
      if content.is_a?(NamedTuple) ? 
        @context.response.content_type = "application/json"
        content.to_json
      else 
        @context.response.content_type = "text/json" 
        content
      end
    end

    macro ok(content = "")
      return response 200, {{content}}
    end

    # Other macros with predefined status code for created, updated, not_found etc
end    

So when i need to send plain 200 response, simply i just write ok("Success")
Others : ok(someNamedTupleFromDB), not_found("Resource not found")

Resolved with #367

Was this page helpful?
0 / 5 - 0 ratings

Related issues

drujensen picture drujensen  路  6Comments

aarongodin picture aarongodin  路  7Comments

conradwt picture conradwt  路  3Comments

blankoworld picture blankoworld  路  7Comments

faustinoaq picture faustinoaq  路  5Comments