GithubHelp home page GithubHelp logo

yosiat / panko_serializer Goto Github PK

View Code? Open in Web Editor NEW
536.0 13.0 35.0 1.23 MB

High Performance JSON Serialization for ActiveRecord & Ruby Objects

Home Page: https://panko.dev

License: MIT License

Ruby 67.68% C 32.32%
ruby serialization activerecord serializer performance oj json-serialization

panko_serializer's Introduction

Panko

Build Status

Panko is a library which is inspired by ActiveModelSerializers 0.9 for serializing ActiveRecord/Ruby objects to JSON strings, fast.

To achieve its performance:

  • Oj - Panko relies on Oj since it's fast and allows for incremental serialization using Oj::StringWriter
  • Serialization Descriptor - Panko computes most of the metadata ahead of time, to save time later in serialization.
  • Type casting — Panko does type casting by itself, instead of relying on ActiveRecord.

To dig deeper about the performance choices, read Design Choices.

Support

License

The gem is available as open source under the terms of the MIT License.

panko_serializer's People

Contributors

bbay avatar bradbajuz avatar brunoarueira avatar byroot avatar charlieamer avatar codingspartan avatar danielmalaton avatar deanpcmad avatar dependabot[bot] avatar elthariel avatar henrypoydar avatar hkdnet avatar jolekszyk avatar khall avatar nerzh avatar oyeanuj avatar phelios avatar ryoung avatar sferik avatar sufendy-rea avatar thomasklemm avatar tnir avatar watson1978 avatar yosiat avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

panko_serializer's Issues

Undefined method ArraySerializer

I've followed the Getting Started guide but having issues with serializing. In my Events controller, I keep on getting the error:

undefined method 'ArraySerializer' for Panko:Module

Created a serializers folder under app and named my files:

event_serializer.rb
office_serializer.rb

Here's my json render:

render json: Panko::ArraySerializer(events, each_serializer: EventSerializer).to_json

serialize carrierwave mounted field

Hello

I am using carrierwave gem to store the file into s3.

Album model has cover field and mounted with carrierwave.
It has several versions like large, thumb and default.

attributes :cover

when I use Active Model Serializer, it gives all versions in response
{ cover: {
large: { url: full_url },
thumb: { url: full_url },
url: full_url
}}

but when I use panko, it just response the value in table. like
{ cover: 'xxx.jpg (not_full_url)` }

Thanks :)

how to customize association sorting?

Hi, I would like to know how to add customize sorting logic in has_many association?

class UserSerializer < Panko::Serializer
  has_many :posts, each_serializer: PostSerializer
  # posts array need to be order by published_at, for exmaple
end

class User < ApplicationRecord
  has_many :posts
end

How to use a raw JSON string inside a serializer?

Hi
I have seen this example on Panko docs:

  posts = Cache.get("/posts")

   render json: Panko::Response.new(
     success: true,
     total_count: posts.count,
     posts: Panko::JsonValue.from(posts)
   )

But I currently need to use JsonValue on an attribute inside a serializer. Like this:

class PostSerializer < Panko::Serializer
  attributes :id, :text ## other attributes
  attributes :some_raw_json_array
  
  def some_raw_json_array
     Panko::JsonValue.from('[{ "a": 1}, {"a": 2}]')
  end
end

But, when I call PostSerializer.new.serialize_to_json(OpenStruct.new(id: '1', text: 'foo')) I get this JSON:

{"id":"1","text":"foo","some_raw_json_array":{"value":"[{ \"a\": 1}, {\"a\": 2}]"}}

instead of getting:

{"id":"1","text":"foo","some_raw_json_array": [{ "a": 1}, {"a": 2}]}

Is this behaviour right? Is there any way to obtain my desired ouput?

Inference: detect serializer for associations

I want to be able not to specify specific serializers in associations and it will find automatically.

class PostSerailizer < Panko::Serializer
  has_many :comments
end

it will use CommentsSerializer here

How do I selectively display a key/value pair?

Say I have a serializer like this :

class Device < Panko::Serializer
  attributes :id, :name
  has_many :lights, serializer: LightSerializer
  has_many :fans, serializer: FanSerializer
  has_many :curtains, serializer: CurtainSerializer
end

now every device need not have all three, some might have just a fan and a light, some might have just a light.

I don't want to display empty arrays every single time. How do I selectively hide them if the array size is zero? I tried adding if: -> { object.fans.count > 0 } but that didn't seem to work, I still got an empty array.

Issue with boolean types

Hello,

I started using your serializer gem and am running into a weird issue.

Whenever the model attribute is of type boolean i'm getting a '/panko_serializer-0.4.0/lib/panko/serializer.rb:92: [BUG] Segmentation fault at 0x00000000000003' error and the entire ruby/rails process crashes.

Whenever I remove the boolean attribute from the serializer it is working fine. Also when I use a custom method in the serializer like the following example it actually works (in the example 'admin' is a boolean):

class UserSerializer < Panko::Serializer
  attributes :id, :email, :name, :admin

  def admin
    object.admin
  end
end

So when I remove the admin method in the above example it produces the error.

Is this a known issue or am I doing something wrong?

I'm calling the serializer with:

UserSerializer.new.serialize_to_json(User.first)

More info:
Database; MySQL
Rails: 5.0.6
Ruby: 2.5.1

With kind regards,
Snowy Leopard

Attrribute methods not running

Posted this one to Slack, but haven't noticed activity there in a few months so reposting into an issue for brevity. Using latest tag 0.7.3, Ruby 2.6.6.

I've been beating my head against an issue all day long that I just can't figure out. I'm looking for some guidance or tips on how to debug this.

Panko is serializing json differently between different containers on both CircleCI and Heroku Production. I have three Serializers, one of them (ContactSerializer) is returning nil instead of the result of the method:

class CommentSerializer < Panko::Serializer
  has_one :user, serializer: UserSerializer, only: %i[id scoped_contact]
end

class UserSerializer < Panko::Serializer
  has_one :scoped_contact,
          serializer: ContactSerializer,
          name: :contact,
          only: %i[id photo_url full_name]
end

class ContactSerializer < Panko::Serializer
  attributes(*Contact.attribute_names.map(&:to_sym))
  attributes(:photo_url, :full_name)

  has_one :user, serializer: UserSerializer

  def photo_url
    ContactDecorator.new(object).photo_or_gravatar_url(88)
  end

  def full_name
    object.full_name
  end
end

In some containers, it is returning {:contact=>{:full_name=>nil, :id=>131, :photo_url=>nil} and in other containers, it returns valid values for full_name and photo_url. On the failing containers, I can comment out has_one :user, serializer: UserSerializer and it works fine, but why would this behavior be different on identical environments?

My best hunch right now is that there is a race condition when my gems are installed with bundle install --jobs=4, possible that Panko native extensions are conflicting with another library? Again, just need some direction on how to troubleshoot this. I have tried to reinstall gems without concurrent install with bundle install --force, but this does not resolve the issue on the failed containers. Any help would be much appreciated!

Memoized methods cause attributes to leak into other records

In the example below, the first user record's complex_attribute will override the second.

class FooSerializer < Panko::Serializer
  attributes :name, :address, :complex_attribute

  def complex_attribute
    # in reality, something time-consuming
    @complex_attribute ||= [object.name, object.address].join(', ')
  end
end

Panko::ArraySerializer.new(@users, each_serializer: FooSerializer)

Missing support for rendering hash in Panko::Response

Hi,

Using Panko::Response.new, we are not able to render a hash in the response as we get an error thrown Can not push onto an Object without a key..

For example, doing it with normal render json works as follows:

my_hash = {
  foo: 'bar',
  bar: 'foo'
}

render json: { my_hash: my_hash }

This will give a response looking like: {"my_hash":{"foo":"bar","bar":"foo"}}.

However using Panko::Response, the error is thrown:

my_hash = {
  foo: 'bar',
  bar: 'foo'
}

render json: Panko::Response.new( my_hash: my_hash )

Will give error: Can not push onto an Object without a key..

Please let me know if any additional info is required.

Thanks for this awesome gem!
Laith

camelCase method attributes

Hello,

I need to use camelCase for my API, what's the best way using Panko?

Right now I uses aliases for most of my attributes and camelCased method names but that feels wrong.

class ObjectSerializer < Panko::Serializer
  attributes :title, :methodAttribute
  aliases first_attr: :firstAttr, second_attr: :secondAttr

  def methodAttribute
     compute(object)
  end
end

Filter on array serializer?

Right now we are able to filter on singular serializer

class UserSerializer < Panko::Serializer
  attributes :id, :name, :email
end

# this line will return { 'name': '..' }
UserSerializer.new(only: [:name]).serialize(User.first)

# this line will return { 'id': '..', 'email': ... }
UserSerializer.new(except: [:name]).serialize(User.first)

But do you think we can apply that filter if we are using ArraySerializer?

Panko::ArraySerializer.new(users, each_serializer: UserSerializer)

Using with a Hash object?

I'm receiving hashes back from some database calls and serializing the results, this means my object that is getting serialized is a Hash. For every item on the attributes list, I have to define:

def my_attribute
  object["my_attribute"]
end

Could panko_serializer support this in a nicer way? Perhaps define a method that does the "getting of an attribute value", instead of using send(attribute) - so I could do something like this:

class MySerializer < Panko::Serializer
  attributes :cat_name

  private

  def read_attribute(name)
    object[name]
  end
end

An alternative would be for me to create a Struct for each type of Hash result I have, but that would lead to extra allocations and mapping between Hash and Struct that isn't really necessary.

I'd be happy to work on a PR if you think it would be worth including?

Aliases for custom method

We want to implement a custom method with payload key name as metricValues, but the proper ruby method name should be snake_case.

class MetricPeriodSerializer < Panko::Serializer
        attributes :period, :metricValues

        def metricValues
           [{
            'name' => 'metric1',	
            'value' => object.metric_1	
          },	
           {	
             'name' => 'metric2',	
             'value' => object.metric_2	
           }]
        end

end

We have tried the following way, but having no luck. Just wondering does panko support alias for custom method by any chance?

class MetricPeriodSerializer < Panko::Serializer
        attributes :period, :metricValues
        aliases metric_values: :metricValues

        def metric_values
           [{
            'name' => 'metric1',	
            'value' => object.metric_1	
          },	
           {	
             'name' => 'metric2',	
             'value' => object.metric_2	
           }]
        end

end

Rendering serializers with additional parameters

AMS has facility to pass additional parameters to serializer
i.e, render json: user, include_token: true, current_user_id: user.id

It would be nice if we have similar feature to add additional parameters on Panko for both single object serializer and array serializers,

render json: Panko::UserSerializer.new.serialize_to_json(user)
render json: Panko::ArraySerializer.new(users, each_serializer: Panko::UserSerializer)

Currently it just accepts 1 parameters to be passed on

Tried using,
render json: Panko::Response.new(
      current_user_id: user.id,
      include_token: true,
      user: Panko::UserSerializer.new.serialize_to_json(user)
)

But it's returning null response, and doesn't seem to be working.
[active_model_serializers] Rendered ActiveModel::Serializer::Null with Panko::Response.

Rendering JSON in a belongs_to relationship

I have an Events controller that renders JSON data but have a belongs_to relationship with another model, Offices, and need to render the company attribute in the Event's JSON data.

In my EventSerializer, I can't add:

belongs_to :office, serializer: OfficeSerializer

But I need the :company attribute from the Office model and need to turn it into an alias:
class EventSerializer < Panko::Serializer
aliases company: :title

Is there a way to do this?

undefined symbol: RB_INTEGER_TYPE_P for Fixnum

Hi,

I get this error when trying to serialize an object with Fixnum field attribute :

symbol lookup error: /usr/local/bundle/gems/panko_serializer-0.5.9/lib/panko/panko_serializer.so: undefined symbol: RB_INTEGER_TYPE_P

If I use a method attribute to transform it in a String it works fine.

Using ActiveRecord's pluck when possible

Some serializers or associations are simple enough to use ActiveRecord's pluck function to retrieve objects. pluck is much faster than retrieving objects with plain ActiveRecord.

I created a gem, Plucker Serializer, that uses this technique to improve performance. It also has built-in single object and collection caching.
Benchmarks show that plucking can improve memory consumption and throughput, especially for large collections.

Adding custom type casting and using Oj::StringWriter like Panko does in addition with this technique could really boost performance in my opinion.

Serializing data from belongs_to and has_many relationship

I have an Events controller that renders JSON data but have a belongs_to relationship with another model, Offices, and need to render the company attribute in the Event's JSON data.

Office Model:
has_many :events

Event Model:
belongs_to :office

In my EventSerializer, I can't add:
belongs_to :office, serializer: OfficeSerializer

But I need the :company attribute from the Office model and need to turn it into an alias:

class EventSerializer < Panko::Serializer
  aliases company: :title
end

Is there a way to do this?

Render json for resource

Hello there 👋

I'm getting this error undefined method _descriptor' for nil:NilClass and I have no idea why 🤔

Here's my line:
render json: Panko::ArraySerializer.new(@school, serializer: SchoolSerializer).to_json

I did not see any example in the documentation for single resource but only for collections am I doing it right ?

Thanks !

Serialize attributes which is used `serialize` in active model definition

Context:
Suppose I have User model like this:

class Rot13JSON
  def self.rot13(string)
    string.tr("a-zA-Z", "n-za-mN-ZA-M")
  end

  # Serializes an attribute value to a string that will be stored in the database.
  def self.dump(value)
    rot13(ActiveSupport::JSON.dump(value))
  end

  # Deserializes a string from the database to an attribute value.
  def self.load(string)
    ActiveSupport::JSON.load(rot13(string))
  end
end

class User < ActiveRecord::Base
  serialize :preferences, Rot13JSON
end

and UserSerializer class definition:

class UserSerializer < Panko::Serializer
  attributes :preferences
end

When serializing user instances:

# create user with non-nil preferences
user = User.create!(preferences: {...})

# serialize
UserSerializer.new.serialize(user) # { preferences: nil }

Expected

{ "preferences": {...} }

Got

{ "preferences": null }

Question:
Will you have the plan to fix it soon? I'm migrating from AMS to Panko and getting in trouble with it

Reference:
Serialize function in Active model

Trouble detecting polymorphic relations

Hi @yosiat, As I was migrating from AMS to this excellent serializer, I keep running into an error where Panko is unable to determine the serializer for a polymorphic relation:

class DrinkSerializer < Panko::Serializer
  has_one :drinkable
  # Since it belongs to either Tea or Coffee, I can't use 'serializer: option'
  # AMS detected it automatically, so how do I tell Panko which one to use? 
end

I couldn't find polymorphic relations mentioned in the docs, so let me know the best way to work with polymorphic relations in Panko.

Thank you!

Custom methods on an ActiveRecord model object don't get serialized

I defined a few custom methods on my AR model, but when I add them as attributes to the serialization, it ignores them. I worked around it for now by adding a no-op method in the serializer:

attributes :photos

doesn't put anything in the final JSON, but:

attributes :photos
def photos
  object.photos
end

does.

Has_many method 'xxx_ids'

Hello,

Variables of type 'xxx_ids' (has_many) built automatically by ActiveRecord do not work in attributes mode

Exemple:

This example works

Model:

has_many :pankos

Serializer:

attributes :panko_ids
def panko_ids
  object.panko_ids
end

###############

This example does not work

Model:

has_many :pankos

Serializer:

attributes :panko_ids #return always null

However the variable panko_ids is well regarded as an attribute because I can do record.panko_ids or record.send(:panko_ids)

Ruby: 2.5.1
Rails: 5.2.1

Thx :)

Multiple NoMethod error on serializers

Hi there 👋
First of all I've been using Panko for a while and it's really great !

What happened ?

I've been encounting some weird errors recently. It seems Panko can't find my main object and its attributes. Even if the main object exists and is valid.

Context

This is my serializer method 👇

def template_colour
    object.template.colour.hex_code
 end

I get from time to time NoMethodError: undefined method template' for nil:NilClass` which is weird because if I reload or do something it disappears. It's not triggering every time.

Plus, when I go into my console I can find my template, the colour association and the hex_code without any problem.
It feels like Panko can't get the main object fast enough to render it.

Did you have any king of errors like mine and do you have any idea how to fix it ?

Thanks ! 🤚

Reusing serializer instance?

I was under the impression that I should be creating a context, then a serializer, then using that serializer many times with many different objects, but when i do that, all results have the same data in them.. Is this a bug?

It works fine if I create a new instance of serializer for each object I want to serialize.

Alias declaration is ignored when method is added

Step to reproduce

require "panko_serializer"
require "active_support"
require "active_support/core_ext"
require "active_record"

class S1 < Panko::Serializer
  aliases({ created_at: :createdAt })
end

class S2 < Panko::Serializer
  aliases({ created_at: :createdAt })

  def created_at
    "2023-04-18T09:24:41+00:00"
  end
end

result1 = S1.new.serialize({ "created_at" => "2023-04-18T09:24:41+00:00" })
result2 = S2.new.serialize({})

p result1
p result2

Expected Behavior

S2's result should have createdAt instead of created_at because it has the alias.

$ bundle exec ruby a.rb
{"createdAt"=>"2023-04-18T09:24:41+00:00"}
{"createdAt"=>"2023-04-18T09:24:41+00:00"}

Actual Behavior

created_at is used.

$ bundle exec ruby a.rb               
{"createdAt"=>"2023-04-18T09:24:41+00:00"}
{"created_at"=>"2023-04-18T09:24:41+00:00"}

Filtering keys at serializer level

Hi @yosiat, another question about an AMS as I analyze my code to estimate effort to migrate:

I use the following two patterns quite a bit to ensure the user gets data consistent with their level of authorization:

#1 Pattern: Utilizing the fact that AMS calls `filter` for each serializer

class PostSerializer < ActiveModel::Serializer
     # ..attributes comes here

	def filter(keys)
		if scope && scope.is_admin?
			keys
			
		else
			keys - [:draft, :created_at, :notes]

		end
	end
end
#2 Pattern: Using AMS `initialize` and `attributes` method

class PostSerializer < ActiveModel::Serializer

  #.. basic attributes come here

  def initialize(object, options = {})
		@owner = scope && (object.id == scope.id) ? true : false
		@logged_in = scope
		super(object, options)
	end

	def attributes(*args)
		return super if @owner
		if @logged_in
			attributes_to_remove = [
				:preview,
			]

		else
			attributes_to_remove = [
				:is_published
			]

		end
		filtered = super.except(*attributes_to_remove)
		filtered
	end
end

How can I achieve the same with Panko so that whenever Post Serializer is called, it renders appropriately?

Thank you!

Setting different key

What would the best way to use a different key for has_one or has_many association?

Benchmarks task not working

Hello,

rake benchmarks is not working. I fixed some file requirements but looks like something is still wrong:

panko_serializer/benchmarks/type_casts/bm_panko.rb:7:in panko_type_convert': undefined method _type_cast' for Panko:Module (NoMethodError)

I was unable to locate a working version :(

Delegate + aliases not working as expected

I have a AR model that has a db column called state, and I want to transform it before serializing the data. That method that transforms data lives on the AR model

When delegating the method to the AR object + aliasing it, panko is not working the way I would expect. it's returning the actual persisted database value for object#state

class StateSerializer  < Panko::Serializer
  attributes :state

  aliases friendly_state: :state
  delegate :friendly_state, to: :object
end
class ActivityLog < ApplicationRecord
   def friendly_state
    case state
    when "error"
      "User Error"
    else
      state
    end
  end
end

I can accomplish what I want by doing but I think it would be a better approach to be able to rely on aliases + method delegation

class StateSerializer  < Panko::Serializer
  attributes :state

  def state
	object.friendly_state
  end
end

Option to camelize keys

Is there an option to convert all property names to camelCase by default?

Aliases will be too much repetition, and changing all property names to camelCase will break the convention.

Can't compile on windows. Fix seems easy.

Hello, one of my dependencies for a project is panko_serializer, and I am using Windows. I wasn't able to compile because there is an enum value Unknown used somewhere in the project, but there is also an enum value Unknown in windows' networking headers. When I temporarily renamed windows' Unkown to _Unknown library compiled successfuly. So I believe fix for this issue is very easy, just rename your Unknown enum value to something else. You can see more info in logs bellow.

Installing panko_serializer 0.7.3 with native extensions
Gem::Ext::BuildError: ERROR: Failed to build gem native extension.

current directory:
C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/panko_serializer-0.7.3/ext/panko_serializer
C:/Ruby27-x64/bin/ruby.exe -I C:/Ruby27-x64/lib/ruby/2.7.0 -r
./siteconf20201021-13060-2iokr6.rb extconf.rb
creating Makefile

current directory:
C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/panko_serializer-0.7.3/ext/panko_serializer
make "DESTDIR=" clean

current directory:
C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/panko_serializer-0.7.3/ext/panko_serializer
make "DESTDIR="
generating panko_serializer-x64-mingw32.def
compiling ./attributes_writer/active_record.c
./attributes_writer/active_record.c: In function
'active_record_attributes_writer':
./attributes_writer/active_record.c:122:70: warning: passing argument 3 of
'read_attribute' discards 'volatile' qualifier from pointer target type
[-Wdiscarded-qualifiers]
122 |     volatile VALUE value = read_attribute(attributes_ctx, attribute,
&isJson);
|
^~~~~~~
./attributes_writer/active_record.c:68:84: note: expected 'VALUE *' {aka 'long
long unsigned int *'} but argument is of type 'volatile VALUE *' {aka 'volatile
long long unsigned int *'}
68 | VALUE read_attribute(struct attributes attributes_ctx, Attribute
attribute, VALUE* isJson) {
|
~~~~~~~^~~~~~
In file included from ./attributes_writer/active_record.h:9,
                 from ./attributes_writer/active_record.c:1:
At top level:
./attributes_writer/type_cast/type_cast.h:65:25: warning: 'type_casts' defined
but not used [-Wunused-variable]
   65 | static struct _TypeCast type_casts[] = {
      |                         ^~~~~~~~~~
compiling ./attributes_writer/attributes_writer.c
In file included from ./attributes_writer/attributes_writer.c:1:
./attributes_writer/attributes_writer.h:10:19: error: redeclaration of
enumerator 'Unknown'
   10 | enum ObjectType { Unknown = 0, ActiveRecord = 1, Plain = 2, Hash = 3 };
      |                   ^~~~~~~
In file included from
C:/Ruby27-x64/msys64/mingw64/x86_64-w64-mingw32/include/winscard.h:11,
from
C:/Ruby27-x64/msys64/mingw64/x86_64-w64-mingw32/include/windows.h:97,
from
C:/Ruby27-x64/msys64/mingw64/x86_64-w64-mingw32/include/winsock2.h:23,
                 from C:/Ruby27-x64/include/ruby-2.7.0/ruby/win32.h:41,
                 from C:/Ruby27-x64/include/ruby-2.7.0/ruby/defines.h:371,
                 from C:/Ruby27-x64/include/ruby-2.7.0/ruby/ruby.h:29,
                 from C:/Ruby27-x64/include/ruby-2.7.0/ruby.h:33,
                 from ./attributes_writer/attributes_writer.h:3,
                 from ./attributes_writer/attributes_writer.c:1:
C:/Ruby27-x64/msys64/mingw64/x86_64-w64-mingw32/include/winioctl.h:526:3: note:
previous definition of 'Unknown' was here
526 |
Unknown,F5_1Pt2_512,F3_1Pt44_512,F3_2Pt88_512,F3_20Pt8_512,F3_720_512,F5_360_512,F5_320_512,F5_320_1024,F5_180_512,F5_160_512,
      |   ^~~~~~~
In file included from ./attributes_writer/active_record.h:9,
                 from ./attributes_writer/attributes_writer.h:5,
                 from ./attributes_writer/attributes_writer.c:1:
./attributes_writer/type_cast/type_cast.h:65:25: warning: 'type_casts' defined
but not used [-Wunused-variable]
   65 | static struct _TypeCast type_casts[] = {
      |                         ^~~~~~~~~~
make: *** [Makefile:244: attributes_writer.o] Error 1

make failed, exit code 2

Gem files will remain installed in
C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/panko_serializer-0.7.3 for inspection.
Results logged to
C:/Ruby27-x64/lib/ruby/gems/2.7.0/extensions/x64-mingw32/2.7.0/panko_serializer-0.7.3/gem_make.out

An error occurred while installing panko_serializer (0.7.3), and Bundler cannot
continue.
Make sure that `gem install panko_serializer -v '0.7.3' --source
'https://rubygems.org/'` succeeds before bundling.

In Gemfile:
  panko_serializer

Model methods

Hello,

I'm trying to add a model method as a value/attribute to the serializer, like it is possible in AMS.

I have a method defined on the model:

class Product < ApplicationRecord
  ...
  def display_name
    ...
  end
end

In AMS I was able to add this method to the attributes list in the serializer and this would work.
I can make it work in panko by calling the method within a method in the serializer:

class ProductSerializer < ApplicationSerializer
  attributes :id, :display_name

  def display_name
    object.display_name
  end
end

Is this something you would be able to and willing to add? Would be much appreciated!
Loving the serializer so far!

Regards,
Snowy Leopard

Setting context globally

Hi @yosiat, a question about translating an AMS pattern to panko:

serialization_scope: AMS allows you to set serialization scope at ApplicationController level which commonly seems to be used for passing in the current user.

serialization_scope :current_user

Now I notice that there is context provided in Panko which would serve the same purpose but wondering if that can be set at a global or per-controller level? Or is that something to be set with each render call?

Adding a custom root name for array serializer

In ActiveModelSerializer you can specify a custom root name for an array like so:

render json :@items, root: 'custom item list'

With the following result:

{
  "custom item list": [
    {
      "item_id": 1,
      "item name": "item 1"
    },
    {
      "item_id": 2,
      "item_name": "item 2"
    }
  ]
}

Is there any way do this in panko??

Specify serializer inside serializer file

Hi there ☀️

Is there a way I can choose inside a serializer to render another serializer based on an attribute ?
Here is my code which is triggered into another serializer with has_many :activities, each_serializer: ActivitySerializer

class ActivitySerializer < Panko::Serializer
  attributes :id, :name, :max_capacity

  has_many :levels, each_serializer: LevelSerializer
end

But I'd like to filter has_many: levels based on another attribute called organization inside Level or at least to choose which levels I want to return.

Is it possible ?

Thanks again !

Given two serializers with `filters_for`, context isn't passed to the associated serializer

As title says, it seems like if I have SerializerA with a filters_for defined (and looking at the context argument), and SerializerA has a relationship defined with SerializerB who also has a filters_for defined, it seems that SerializerB is NOT passed the context object, which can cause errors.

I am not sure if this is expected, and or if I have something configured incorrectly, as the docs are kinda slim on filters_for

Edit: Further, as a suggestion, wouldn't it be appropriate to only call filters_for on the "entry" Serializer, or are there use cases where a context property should cascade through them

Escaped HTML characters in output

Even with Oj.mimic_JSON set, there doesn't seem to be a way to output the non-escaped characters.

{"other_serializer": {"body":"&nbsp;<p>..."}}
{"panko_serializer": {"body":"\u0026nbsp;\u003cp\u003e..."}}

It doesn't seem to be due to the Oj::StringWriter, so perhaps this is happening at a lower level:

puts Oj::StringWriter.new.tap{|w| w.push_json '"<p>&nbsp;</p>"', "body"}.to_s
# "body":"<p>&nbsp;</p>"

Issues with polymorphic associations

post.rb & comment.rb
has_many :attachments, dependent: :destroy, :as => :attachable

attachment.rb
belongs_to :attachable, polymorphic: true

Attachable is common to both post and comment. Attachment should be referring multiple serializers like PostSerializer and CommentSerializer. Is it possible?

It would be nice, if we Panko detects serializers automatically according to associations.

Handle missing attributes set

Panko is trying to read all attributes via iterating @attributes in ActiveRecord AttributeSet.

If AttributeSet doesn't have @attributes we need to have a fallback - may be iterating over and execute rb_funcall to get the values?

Examples & Comparison

Hi @yosiat, I came across this while looking for alternatives to AMS. This looks intriguing, and I am wondering if you have any documenation or examples of its usage anywhere?

I am also curious on the motivations behind this library, and how it compares to AMS?

Thank you!

Migration from AMS

Hi! Sorry about opening an issue, I tried to find other forms of contact but it appears the links to the Slack community are broken.

I have a large project using AMS that should benefit a lot from more efficient serializers. Is Panko a drop-in replacement for AMS at this point? Is there a migration guide of any sort? I'm trying to gauge/estimate the work to migrate and that would greatly help me.

If I had a simple list of what works and what doesn't I could just go the "install Panko, replace AMS references, replace non-compatible methods, and run the specs" route. :)

Thank you!

Serialization of single object with context / options

We already discussed serialization of a single object and the docs were updated with the example here.

Now, I face the situation where I need to pass some options and I noticed it is not possible due to the implementation in ResponseCreator (response.rb)

wdyt about adding this change?

   # in lib/panko/response.rb
    def self.serializer(data, serializer, options = {})
      json serializer.new(options).serialize_to_json(data)
    end

So I can then do something like this:

render(
  json: Panko::Response.create do |r|
    {
      status: 'active',
      user: r.serializer(user, UserSerializer, context: {index: true})
    }
  end
)

I could send a Pull Request if you think this is a good idea.

How can I use Panko::Response with a single object?

The example uses an ArraySerializer as a sample use of Panko::Response, but I couldn't figure out how to use the same for a single item. Right now, I have:

render json: Panko::Response.new(
      status: 'active',
      user: Panko::JsonValue.from(UserSerializer.new.serialize_to_json(user))
)

which works, but feels like I'm doing something wrong. Is there a better/cleaner way?

Serialization level setting

Serialization level in AMS is set to ‘One level’ by default, which we can change it to deep nesting from config globally.

Do we have similar setting in Panko? If I'm not wrong, it seems Panko does deep nesting by default unless mentioned while invoking serializer like below

Panko::ArraySerializer.new(posts, only: {
instance: [:title, :body, :author, :comments],
author: [:id],
comments: {
instance: [:id, :author],
author: [:name]
}
})

It would be great, if we have config kind of stuff to set serialization level globally.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.