RocketPants and ActiveModelSerializers custom serializer - ruby-on-rails

Damn, that's me again...
Quote from RocketPants git:
Support for active_model_serializers - If you want to use ActiveModelSerializers, we'll take care of it. Even better, in your expose call, pass through :serializer as expected and we'll automatically take care of invoking it for you.
So that's what I try to do:
def friends
#user = User.find_by_id(params[:id])
expose #user.friends.first(params[:limit].to_i), serializer: UserJustNameSerializer
end
And that's how I implement my serializers in user_serializer.rb:
class UserSerializer < ActiveModel::Serializer
....
end
class UserJustNameSerializer < ActiveModel::Serializer
attributes :id, :first_name, :last_name, :full_name, :avatar_thumb
def avatar_thumb
object.avatar.url(:thumb)
end
end
Using expose without serializer option is properly preparing JSON according to UserSerializer. Trying to use UserJustNameSerializer gives this error:
NameError (uninitialized constant Api::V1::UsersController::UserJustNameSerializer)
So the question is: how to properly show RocketPants the way to my serializer? Now it's trying to find it in UsersController.

So, as always, only after posting the question I get to answer =)
The solution is:
Place UserJustNameSerializer into its own file user_just_name_serializer.rb and use each_serializer: instead of serializer:, as I'm trying to serialize an array, not a single object.
For those who google: If I use serializer: UserJustNameSerializer on array, I get
NoMethodError (undefined method `read_attribute_for_serialization' for []:Array):

Related

Rails - serializer passing parametr

I use active_model_serializers (0.9.2). I've been studying documention, stack and source code and still cant find some way to pass some parameter to serializer. The only one workaround is using default scope
def default_serializer_options
{
scope: some_param
}
end
#options, options orserialization_options seems to be not working for me.
This is the link which will help you with it link
First create a serializer in the serializer folder.
class AttachmentSerializer < ActiveModel::Serializer
attributes :id, :attachment_url
def attachment_url
object.attachment_url
end
end
Then in your controller you can do something like this
params.require(:model-name).permit( :attachment)

How can I extend ActiveRecord model with new propery?

I'm developing a REST API and before send results (fetched from DB with ACtiveRecord) to client I need to extend it with some additional data. Here is how I suppose it to be:
def index
(categories = Category.all()).each() do |category|
category.image = "some image"
end
render json: categories
end
It seems like Ruby does not add object proporties on the fly, like JS would do, so this code ends up with error message
undefined method `image=' for #<Category:0x007f89f0513d40>
I read a lot and found solution to add attr_accessor :image in my Category model. Now it does not throw error but also image property does not appeared in JSON output.
Instead of playing with the object it self, you might want to take a few mins and learn how jbuilder works, it's very simple and it would make your life a lot easier, especially when the json format includes a little extra/different data from your original database object,
Here's a simple format of what you might do
# app/views/categories/index.json.jbuilder
json.array! #categories do |category|
json.prop1 category.prop1
json.prop2 category.prop2
json.image whatever_image_function_here
end
Other solution would be overriding the as_json method of the class
Use as_json method with attr_accessor :image in category model.
def index
categories = Category.all.each do |category|
category.image = 'some image'
end
render json: categories.as_json(methods: :image)
end
In rails < 4.2 it has different name - to_json

How to define a Sparse Fieldset in a Rails request

Is there a simple way to implement requesting a Sparse Fieldset in a rails JSON request?
/some/endpoint.json?fields=id,name,favourite_colour
One solution I've found is to do it within a serialiser.
module V2
class BaseSerializer < ActiveModel::Serializer
self.root = true
def include?(field)
if #options.key?(:fields)
return #options[:fields].include? field.to_s
end
super field
end
end
end
In your controller you can do something like
render json: #sth, only: params[:fields].split(',').map(&:to_sym)
you should also wrap it in some strong params, to disallow non existing attributes
(but I doubt for it to be best possible solution)

Rails: do non-ActiveRecord models need to include ActiveModel::Serializers, or just respond to #as_json?

Using Rails 3.2, I'm working on an API backed model (not ActiveRecord). I want to be able to call to_json on this model in Rails controllers. After reading through a bunch of the ActiveModel docs I'm still not clear on one thing:
Given a model like this:
class MyModel
attr_accessor :id, :name
def initialize(data)
#id = data[:id]
#name = data[:name]
end
def as_json
{id: #id, name: #name}
end
end
Should this work as expected, or do I also need to include ActiveModel::Serializers::JSON? I'm having a hard time figuring out where the as_json / to_json methods are normally defined and when Rails calls which ones automatically in different circumstances...
Thanks for any insight!
Yes this does work, however not quote as you've written in.
When you render json in a controller using
def action
render :json => #my_model
end
Then Rails will automatically call to_json on your object and as long as you've defined to_json this will work as expected.
If your controller uses the Rails 3 content negotiation shenanigans, ie.
class Controller < ApplicationController
respond_to :json, :html
def action
respond_with(#my_model)
end
Then you will need to override as_json on your class, but the method signature requires an optional hash of options to be compatible with ActiveSupport so in this case you want
def as_json(options={})
...
end
Alternatively If you include ActiveModel::Serializers::JSON into your Class and your class supports the attributes method that returns a hash of attrs and their values - then you'll get as_json for free - but without the control of the resultant structure that you have if you just override the method by hand.
Hope this helps.

Rails: attr_accessor doesn't show up when try to render as JSON

In my application I have a model that is below;
class Init < ActiveRecord::Base
attr_accessor :clientAvailability
attr_accessible :returnCode, :returnMessage, :tokenCode, :updateURL
end
In here when I've added the **attr_accessor** later on and when I try to apply **render json: init** it doesn't show the **clientAvailability** property even though I've set it as;
init=Init.new
init.clientAvailability="3"
When I debug it I can see that it is set, but doesn't simply show up when I try to render it as json. What could be the thing I'm missing?
Is clientAvailability a column in the DB? If not, then I suppose it is the default way - to serialize only the DB attributes. But you can do:
render json: init, methods: [:clientAvailability]
to include clientAvailability attribute.

Resources