I have this method in my controller:
# GET /bios/1
# GET /bios/1.json
def show
if member_session?
#member = MemberPresenter.new(#bio.member)
# I need something here to add a flag to the json response to signal this is a member session.
else
#member = MemberPresenter.new(#bio.member)
end
end
I need to modify the json response to return something like:
{ member: #member, member_session: true }
Thanks in advance!
You can use json param for render functions:
render json: { member: #member, member_session: true }
But it's not the best way to render JSON in rails. I'd recommend you try to use https://github.com/rails-api/active_model_serializers
I'm not sure if you specifically want to return json all the time but here's an alternative to rendering other formats as well:
respond_to do |format|
format.html
format.json { render json: { member: #member, flag: #member.status } }
end
For small and simple objects, doing this is fine, but if you had to drag the associations along, you have the choice of using a serializer, or you could override the to_json method to something like this.
# member.rb
def as_json(options = {})
options = options.merge(
except: [
:updated_at,
:created_at,
],
include: { # Getting associations here
address: {
only: [:street, :zip_code],
include: {
neighbors: { only: :name }
}
}
}
)
super.as_json(options)
end
And finally within the controller, render json: #member.to_json and it will pull all the associations you want with it. This is the lazy man's way of serializing aka what I do :)
Related
I have implemented my own object creation logic by overriding the create action in a JSONAPI::ResourceController controller.
After successful creation, I want to render the created object representation.
How to render this automatically generated JSON API response, using the jsonapi-resources gem?
Calling the super method does also trigger the default resource creation logic, so this does not work out for me.
class Api::V1::TransactionsController < JSONAPI::ResourceController
def create
#transaction = Transaction.create_from_api_request(request.headers, params)
# render automatic generated JSON API response (object representation)
end
end
You could do something like this:
class UsersController < JSONAPI::ResourceController
def create
user = create_user_from(request_params)
render json: serialize_user(user)
end
def serialize_user(user)
JSONAPI::ResourceSerializer
.new(UserResource)
.serialize_to_hash(UserResource.new(user, nil))
end
end
this way you will get a json response that is compliant with Jsonapi standards
render json: JSON.pretty_generate( JSON.parse #transaction )
def render_json
result =
begin
block_given? ? { success: true, data: yield } : { success: true }
rescue => e
json_error_response(e)
end
render json: result.to_json
end
def json_error_response(e)
Rails.logger.error(e.message)
response = { success: false, errors: e.message }
render json: response.to_json
end
render_json { values }
so i have this controller and i want to add a dynamic attribute along with the other data in the #events instance variable
i have search and tried things like #events.attributes.merge(appointment: true)
appointment = true is what i want to add to the events object.
def find
params = event_params
current_user = 2
#events = Event.where('date LIKE ?',"%#{params[:month]}%")
def #events.as_json(options = { })
h = super(options)
h[:appointments] = false # Or combine with above h[:appointments] = self.appointments?
h
end
respond_to do |format|
if current_user == 1
if #events
format.json {
render json: #events.to_json
}
else
render 'index'
end
else
format.json {
render json: #events.to_json
}
end
end
end
ajax code here
function retrieve(date_partial) {
var jsondata = {
events: {
month: date_partial,
}
}
$.ajax({
cache: false,
type: "POST",
url: "/events/find",
data: jsondata,
success: function(data) {
console.log(data);
for (var i = 0; i < data.length; i++) {
var day = data[i].date.substring(0, 2);
$("td[data-day='" + day + "']").addClass('added');
}
},
error: function(xhr) {
alert("The error code is: " + xhr.statusText);
}
});
so how can i add that property?
This could work ? But then maybe the JSON output isn't what you expected ?
format.json { render :json => {events: #events, appointments: true} }
Because this property is view oriented, the model should not know about it. A better way to do this, is to use a decorator, which will allow you to add what ever attributes you want in the manner you want, without polluting the model.
you can create a PORO object
like this one
# this is by no means a complete implementation, but just for you
# to get the idea
class EventDecorator
# use ( delegate :event_attribute, to: :event ) to delegate
# all the event attributes and to be able to access them
# as if they were declared on the decorator itself
attr_reader :event
attr_accessor :appointment
def initialize(event)
#event = event
#appointment = false
end
def to_json
event.attributes.merge(appointment: appointment).to_json
end
end
a better way is to use the draper gem. You can find a good explanation in this railscat, #286 Draper
Two ways to do that I can think of: adding an instance variable or a custom method (or something hybrid)
EDIT : Forget what I said about creating an instance variable out of nowhere (see this answer)^^"
Method
#events.define_singleton_method(:appointments?){true/false}
#events.appointments? # => true/false
EDIT 2 : AJAX/JSON override
See this answer
def #events.as_json(options = { })
h = super(options)
h[:appointments] = true/false # Or combine with above h[:appointments] = self.appointments?
h
end
I'd like to have my json render in two different ways. I now have my as_json method overridden to display a full object in json form like this:
{
prop1: stuff,
prop2: stuff,
innerthings: {
{
prop1:stuff,
prop2:stuff
}
{
prop1:stuff,
prop2:stuff
}
}
}
And the as_json looks like:
#Renders json
def as_json(options={})
super(
:except => [:created_at, :updated_at],
:include => [{:innerthings = > {
:except => [:created_at, :updated_at]
}}]
)
end
I'd also like to have a second option to render like this:
{
prop1:stuff,
prop2:stuff,
countinnerthings:10
}
current when the code below is used, I get the first render:
respond_to do |format|
format.json { render json: #thing}
end
I'd also like to be able to render with something like as_list that I could use in a case like the below to render just a simple list of the objects.
respond_to do |format|
format.json { render json: #things.as_list }
end
Is there a simple way to do this in ruby on rails?
Instead of rolling your own as_json method. Take a look at ActiveModel Serializers. I think it will satisfy you use-case and help organize your code.
You can just define an as_list method
def as_list
{
prop1: "stuff"
}
end
If you need to use includes etc you can call as_json from your at_list method. As had been said serializers are a better option in general.
At the time my controller looks like this:
def search
#icd4 = Icd4Code.search_full(params[:search]).first(20)
render json: { icd: #icd4.as_json(:only => [:bezeichnung, :nummer, :id])}
end
What i would like to change is that my code does not return #icd4.id as :id but instead #icd4.icd3_code_id as :id
So render json: { icd: #icd4 } would look like this:
{"icd":[{"id":6,"nummer":"A00.1","bezeichnung":"Cholera","icd3_code_id":3,"created_at":"2014-02-28T19:38:20.530Z","updated_at":"2014-02-28T19:38:20.530Z"},{"id":7,"nummer":"A00.1","bezeichnung":"El-Tor-Cholera","icd3_code_id":3,"created_at":"2014-02-28T19:38:20.533Z","updated_at":"2014-02-28T19:38:20.533Z"}]}
My actual code render json: { icd: #icd4.as_json(:only => [:bezeichnung, :nummer, :id])} returns this:
{"icd":[{"id":6,"nummer":"A00.1","bezeichnung":"Cholera"},{"id":7,"nummer":"A00.1","bezeichnung":"El-Tor-Cholera"}]}
And i would like this output:
{"icd":[{"id":3,"nummer":"A00.1","bezeichnung":"Cholera"},{"id":7,"nummer":"A00.1","bezeichnung":"El-Tor-Cholera"}]}
How can i achieve this? Thanks
Without a serializer you can iterate through the items and their keys and rename the key when you find yours.
#icd4 = Icd4Code.search_full(params[:search]).first(20)
data = #icd4.as_json(:only => [:bezeichnung, :nummer, :icd3_code_id]).tap do |icd4_json|
icd4_json.each do |icd4_item|
icd4_item.each do |key|
icd4_item[ 'id' ] = icd4_item.delete( key ) if key == 'icd3_code_id'
end
end
end
render json: { icd4: data }
You should definitely take a look at draper and active_model_serializers gems.
http://railscasts.com/episodes/409-active-model-serializers
http://railscasts.com/episodes/286-draper
although I use Draper in a bit different way then Ryan Bates does, usually I do something like this:
render json: item.decorate.as_json
for example as a simplest solution you could have this class:
class Icd4CodeDecorator < Draper::Decorator
decorates :icd4_code
delegate_all
def as_json(options={})
{
id: icd3_code_id,
bezeichnung: bezeichnung,
nummer: nummer
}
end
end
and then in your controller you could just do:
render json: #icd4.decorate.as_json
Although I think it would be better to keep things correct in as_json method and have id value returned for id property and create a decorator class inherited from Draper::CollectionDecorator and define there your custom method, something like:
class Icd4CodesDecorator < Draper::CollectionDecorator
def as_search_json
object.map do |o|
{
id: icd3_code_id,
bezeichnung: bezeichnung,
nummer: nummer
}
end
end
end
and then in your controller you could do:
render json: Icd4CodesDecorator.new(#icd4).as_search_json
This way you can easily create and maintain any number of versions of json output for your models.
The simplest way is to cleverly change the value something like this
def search
#icd4 = Icd4Code.search_full(params[:search]).first(20)
r = icd: #icd4.as_json(:only => [:bezeichnung, :nummer, :icd3_code_id])
final_value = []
r["icd"].each do |h|
f = {}
h.map do |k,v|
if k == 'icd3_code_id'
f["id"] = v
else
f[k] = v
end
end
final_value << f
end
render json: final_value
end
In my controller i have:
#photo = Photo.find(:all)
respond_to do |format|
...
format.json { render :json => #photo.to_json)
end
so my response looks like:
{
"photo":
{
"updated_at":"2010-10-14T19:12:35Z",
"photo_file_size":206422,
"created_at":"2010-10-14T19:12:01Z"
}
},
{
"photo":
{
"updated_at":"2010-10-16T18:19:38Z",
"photo_file_size":83593,
"created_at":"2010-10-14T19:14:35Z"
}
}
how can i add an additional json key value pair for every photo block?
something like:
"photo":
{
"updated_at":"2010-10-14T19:12:35Z",
"photo_file_size":206422,
"created_at":"2010-10-14T19:12:01Z"
----> "created_at_b":"2010/10/14"
}
maybe :include option?
thanks!
to_json can be made to include the result of any method available on your model. For example you could add the following method to your model:
class Photo < ActiveRecord::Base
def created_at_b
# whatever you want to do
end
end
In your controller you add:
format.json { render :json => #photo.to_json(:methods=>[:created_at_b])
That should return the json that you're after.