I am trying to form a json response that looks like this:
{
"user": {
"birthday": "2013-03-13",
"email": "example#example",
"id": 1,
"name": null,
"username": "example"
},
"other_data": "foo"
}
Before, when I was just returning the user, I used
render :json => #user, :except => [:hashed_password, :created_at, :updated_at]
to keep the hashed_password, created_at, and updated_at attributes from being sent. Is there a way to do this, but also allow additional data to be sent along with the user? Right now I'm just adding the attributes I want to send to the hash one by one, but this is obviously not ideal.
Rendering json data first automagically calls 'as_json' on your model, which returns a ruby hash. After that, 'to_json' is called on that to get a string representation of your hash.
To achieve what you wanted, you can call something like this:
render :json => {
:user => #user.as_json(:except => [:hashed_password]),
:some_other_data => {}
}
In this case, there is no object which responds to 'as_json', so the controller just calls 'to_json' to turn your hash to a string.
I would recommend to use this gem: https://github.com/fabrik42/acts_as_api
Related
I was wondering whether Grape Entity would work for rendering arrays of hashes, I thought I remebered it worked but somehow I cannot get it to work right now, am I doing some obvious mistake? Here's my Entity:
class V1::Entities::Searchresult < Grape::Entity
expose :_type, as: :type
expose :_id, as: :id
expose :_score, as: :score
expose :highlight
end
In my API I call the rendering like this:
present result['hits']['hits'], with: V1::Entities::Searchresult, :params => params
The 'result['hits']['hits']' is filled with 10 hashes that contain the data. The data is present. However when I look at the result I get:
[
{
"type": null,
"id": null,
"score": null,
"highlight": null
},
{
"type": null,
"id": null,
"score": null,
"highlight": null
},
......
Am I doing something wrong, or is this simply not possible. I can't seem to dig up any documentation on the array toppic.
Cheers
Tom
I found the error, Grape::Entity::Delegator::HashObject fails to work with hashes that have string keys and not symbols. It cannot extract the values.
data = []
result['hits']['hits'].each do |item|
data << item.symbolize_keys
end
present data, with: V1::Entities::Searchresult, :params => params
This workaround ommits the problem. I will also open a github Issue for a fix since a simple
object[attribute] || object[attribute.to_s]
would solve the whole problem instead of only using
object[attribute]
to read the attribute.
My model has a custom_fields column that serializes an array of hashes. Each of these hashes has a value attribute, which can be a hash, array, string, or fixnum. What could I do to permit this value attribute regardless of its type?
My current permitted params line looks something like:
params.require(:model_name).permit([
:field_one,
:field_two,
custom_fields: [:value]
])
Is there any way I can modify this to accept when value is an unknown type?
What you want can probably be done, but will take some work. Your best bet is this post: http://blog.trackets.com/2013/08/17/strong-parameters-by-example.html
This is not my work, but I have used the technique they outline in an app I wrote. The part you are looking for is at the end:
params = ActionController::Parameters.new(user: { username: "john", data: { foo: "bar" } })
# let's assume we can't do this because the data hash can contain any kind of data
params.require(:user).permit(:username, data: [ :foo ])
# we need to use the power of ruby to do this "by hand"
params.require(:user).permit(:username).tap do |whitelisted|
whitelisted[:data] = params[:user][:data]
end
# Unpermitted parameters: data
# => { "username" => "john", "data" => {"foo"=>"bar"} }
That blog post helped me understand params and I still refer to it when I need to brush up on the details.
I have an association between ProcessingStatus and Order that looks like this:
Order belongs_to ProcessingStatus
ProcessingStatus has_one Order
When I return an Order, I want to be able to get the ProcessingStatus 'name' attribute as the 'status' attribute of my JSON response.
So, right now, for the following GET call at /orders/73,
render :json => #order.to_json(:only => [:id], :include => {:processing_status => {:only => [:name]}})
I get this:
{
"id": 73,
"processing_status": {
"name": 'processing'
}
}
And I am looking for a way to get this:
{
"id": 73,
"status": 'processing'
}
Anyway on doing that?
You could define a method on your model that returns the status as the value of processing_status.name and then include that in your json:
class Order < ActiveRecord::Base
def status
self.processing_status.try(:name)
end
end
And then include that in your to_json call:
#order.to_json(only: :id, methods: :status)
Alternatively you could add the status to a hash that gets converted to json:
#order.as_json(only: :id).merge(status: #order.processing_status.try(:name)).to_json
I've used .try(:name) in case processing_status is nil but you might not need that. The behaviour is slightly different in the two cases as the first will not include status in the json and the second will include "status":null.
I am trying to return a JSON representation of an ActiveRecord but instead of having the JSON string contain the model's column names for the Keys I would like to have it display something different per column. Is there a way to do this? here is my example line
record.as_json(root: false, :only => [:message, :user])
I basically want it to return the message and the user columns, but I want to call them something else when it gets them.
I think you're overcomplicating this. You only want two columns so why not just do it by hand?
def some_controller
#...
json = {
new_name_for_message: r.message,
new_name_for_user: r.user
}
render json: json, status: :ok
end
Build a two element Hash and hand it off to the JSON rendering system.
record.as_json(root: false, :only => [:user], :methods => [:message_html])
and define that method on record.
I'm sure there's an easy solution for this but I'm new to Rails and need help with syntax.
In my controller I have:
#products = Product.all
format.json { render :json => #products }
And it works fine, returning data with the default column names used in the DB:
"product": {
"created_at": "2010-10-08T17:24:27Z",
"id": 24,
"product_date": "2010-08-08",
"product_name": "Product One",
"updated_at": "2010-10-08T17:36:00Z"
}
What I need is something like:
"product": {
"created_at": "2010-10-08T17:24:27Z",
"id": 24,
"start": "2010-08-08",
"title": "Product One",
"updated_at": "2010-10-08T17:36:00Z"
}
That is, changing product_date to start and product_name to title, but only in the JSON output.
It seems like an easy problem to solve but I'm not sure how to express it in Ruby/Rails syntax, so I would really appreciate any help. I cannot rename the database columns.
If you want to alter the JSON output for all Products, everywhere and all the time, simply override the to_json method on your Product model.
Here's the simple way to do that (in your Product class definition):
def to_json
ActiveSupport::JSON.encode({
:created_at => created_at
:id => id
:start => product_date
:title => product_name
:updated_at => updated_at
})
end
You could get fancier and plug in a custom Serializer, but this should suffice for your purposes. One drawback of doing this so explicitly is that if your schema changes, this will have to be updated. This will also break the options usually available to the to_json method (:include, :only, etc) so, maybe it's not too hot.