Karina Kozarova
Karina Kozarova

Reputation: 1215

return partial pg database entry as JSON in rails

I have a RoR app with postgresql as database

Currently, I have this code:

def return_mssg_as_json
    id = params[:id].to_i
    @message = Message.find(id)
    render json: @message
end

and it returns this JSON:

{"id":13,"created_at":"2017-10-27T19:03:52.196Z","updated_at":"2017-10-27T19:03:52.196Z","text":"ASDF"}

How can I make it return only {"text":"ASDF"}

Upvotes: 1

Views: 45

Answers (3)

jvillian
jvillian

Reputation: 20263

A few things here...

First, you don't need to do to_i here:

def return_mssg_as_json
  id = params[:id].to_i
  @message = Message.find(id)
  render json: @message
end

You can just do:

def return_mssg_as_json
  @message = Message.find(params[:id])
  render json: @message
end

Now, if there's any chance that you might receive an id that doesn't have a matching record, you might want to do something like:

def return_mssg_as_json
  begin
    @message = Message.find(params[:id])
    render json: @message
  rescue ActiveRecord::RecordNotFound
    render json: {errors: :not_found}, status: :not_found
  end
end

Otherwise, if your record doesn't exist, you'll have an unhandled critical error. Instead, however, you could do:

def return_mssg_as_json
  if @message = Message.find_by(id: params[:id])
    render json: @message
  else
    render json: {errors: :not_found}, status: :not_found
  end
end

Now, back to your main question, you could do (as in the accepted answer)

def return_mssg_as_json
  if @message = Message.find_by(id: params[:id])
    render json: { message: @message[:text] }
  else
    render json: {errors: :not_found}, status: :not_found
  end
end

Although, to save yourself three characters, it seems you could do:

def return_mssg_as_json
  if @message = Message.find_by(id: params[:id])
    render json: { message: @message.text }
  else
    render json: {errors: :not_found}, status: :not_found
  end
end

Which is a great answer! But, in the future, if you want to return multiple values from @message (for example), you could do something like (assuming @message responds to foo and bar):

def return_mssg_as_json
  if @message = Message.find_by(id: params[:id])
    render json: @message.attributes.with_indifferent_access.slice(:text, :foo, :bar)
  else
    render json: {errors: :not_found}, status: :not_found
  end
end

This bit:

@message.attributes

converts the record into a hash of its values. This bit:

.with_indifferent_access

allows you to select key-value pairs using symbols instead of strings. And this bit:

.slice(:text, :foo, :bar)

specifies which key-value pairs to return. So, this would return something along the lines of (in JSON format, naturally):

{text: 'blah', foo: 'blah', bar: 'blah'}

Now, in your example, you didn't want text, you wanted message. So, you could do:

def return_mssg_as_json
  if @message = Message.find_by(id: params[:id])
    attr = @message.attributes.with_indifferent_access
    render json: attr.slice(:foo, :bar).merge!(message: attr[:text])
  else
    render json: {errors: :not_found}, status: :not_found
  end
end

Which would return something along the lines of (in JSON format, naturally):

{message: 'blah', foo: 'blah', bar: 'blah'}

Upvotes: 2

Alex Tepliashin
Alex Tepliashin

Reputation: 61

Also you can use jbuilder to achieve such behavior, check an example here https://richonrails.com/articles/getting-started-with-jbuilder

Upvotes: 1

user4932805
user4932805

Reputation:

Simply use the following:

render json: { message: @message[:text] }

Upvotes: 1

Related Questions