Ember serializers not working with Rails 4.2 - ruby-on-rails

Updated to Rails 4.2 and now I cannot for the life of me get the ActiveModel::Serializer configuration to work correctly.
ActiveModel::Serializer.setup do |config|
config.embed = :ids
config.embed_in_root = true
end
Previously, this worked great with:
respond_with #thing
With 4.2 (and 0.9.2 AMS), you have to say:
respond_with #thing, root: true
explicitly. Anyone understand why the global embed_in_root config no longer works?

I had the same trouble...
It appears that active model serializers 0.9.2 is not compatible with Rails 4.2.
What I think may be happening in your case is when you call:
respond_with #thing, root: true
you are not using the Active Model Serializers gem at all. I tested this by adding a custom attribute in my active model serializer, like this:
class ThingSerializer < ActiveModel::Serializer
attributes :this_is_a_test
def this_is_a_test
"and it does not work"
end
end
The this_is_a_test attribute was not turning up in my JSON so I realized that the active model serializer was not in use.
I followed igagnidz and added this to my application controller:
def _render_with_renderer_json(json, options)
serializer = build_json_serializer(json, options)
if serializer
super(serializer, options)
else
super(json, options)
end
end
This is what finally got me through it: https://github.com/rails-api/active_model_serializers/issues/641

Related

Active Model Serializer not responding with the correct attributes

I am working on a rails-api project where I am using active model serialiazer. But unfortunately its not working as expected. This is my V1::HuntsController
class V1::HuntsController < V1::MainController
def index
render json: Hunt.all
end
end
My hunts serializer looks like this
class HuntSerializer < ActiveModel::Serializer
belongs_to :user
attributes :id,:title,:picture_url,:clue
private
def picture_url
object.picture.url
end
end
But in my response i am getting all the attributes from hunt. I tried to explicitly define serializer to avoid versioning issues as well.
render json: {data: Hunt.all } ,each_serializer: HuntSerializer
But nothing seems to work. In the logs I can see,
[active_model_serializers] Rendered V1::HuntSerializer with Hash (32.36ms)
Whats happening here. Any help would be appreciated.
try
render json: Hunt.all, each_serializer: HuntSerializer (no need for data root)
then to verify that the serializer gets hit, put a byebug in the body of the picture_url function. if the byebug gets hit, you are indeed using your serializer. (must have gem byebug included in gemfile)

ActiveModelSerializers gem: how to pass parameter to serializer

I'm updating the gem active_model_serializers from version 0.9.5 to 0.10.1. For version 0.9.5 the code below worked.
Controller:
def create
...
render json: #dia, app_rights: app_rights(#dia)
end
Serializer:
class Api::V1::SerializerWithSessionMetadata < ActiveModel::Serializer
attributes :app_rights
def app_rights
serialization_options[:app_rights]
end
end
The method serialization_options has been deprecated in version 0.10.1.
Here it is suggested to use instance_options instead.
Here it is suggested to use options: "instance_options is only available in the master branch, not in the current RC. In the current RC, you have to use options instead".
There are also suggestions for #options and #instance_options.
I have tried replacing serialization_options with all the above options. However, in all cases, after updating the gem, the json produced does not include app_rights. What am I doing wrong?
Using instance_options, your serializer should look like this:
class Api::V1::SerializerWithSessionMetadata < ActiveModel::Serializer
attributes :app_rights
def app_rights
#instance_options[:app_rights]
end
end
To ensure that the correct serializer gets called, you can render a specific serializer like this (otherwise it will render whatever is defined for the class on #dia):
render json: #dia, serializer: SerializerWithSessionMetadata, app_rights: app_rights(#dia)

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 do I make to_json work in Rails as it works in plain Ruby?

This issue will surface for many who depend on Ruby's JSON serialization outside of a Rails projects. When they try to use their code in a Rails project, it will not work as expected.
The following code run from Ruby (no Rails), prints A.
When run from rails console, it prints Hash.
That means my json serialization works in my command line lib/app, but not when it's imported into a Rails project.
What is the reason/workaround for this?
require 'json'
class A
def to_json(*a)
{:json_class => self.class.name}.to_json(*a)
end
def self.json_create(o)
A.new
end
end
class B
attr_accessor :value
def initialize(value)
#value = value
end
def to_json(*a)
{:json_class => self.class.name, :value => value}.to_json(*a)
end
def self.json_create(o)
B.new(o['value'])
end
end
b = JSON.parse(B.new(A.new).to_json)
puts b.value.class
Ruby is 1.9.3, Rails is 3.2.10
The problem is that Rails uses ActiveSupport::JSON.
For serializing, it uses as_json, not to_json. So the line
{:json_class => self.class.name, :value => value}.to_json(*a)
does not include a JSON version of value in the hash because Class A does not have a as_json method. To get your code to work the same in both Ruby and Rails, you need to explicitly call your A::to_json and A::json_create methods, like this:
def to_json(*a)
{:json_class => self.class.name, :value => JSON.dump(value)}.to_json(*a)
end
def self.json_create(o)
B.new(A.json_create(o['value']))
end
Then call, b = JSON.parse(JSON.dump(B.new(A.new)))
This wlll fix the example, but I think you may want to read this explanation of to_json vs as_json and revise your code appropriately.
According to others, the answer is yes.
http://www.rubyhood.com/2011/06/rails-spoiled-standard-json-library.html
In short, make as_json do what to_json does. That got me what I wanted/expected (and what I've been getting from pure Ruby - Rails).
For those still wandering why the strange behavior is occurring in rails the explanation can be found in:
https://github.com/flori/json/compare/v1.6.7...v1.6.8
and
https://github.com/intridea/multi_json/compare/v1.5.0...v1.5.1
Since in these version upgrades JSON.parse works different. JSON.load might still be helpful. The fastest fix would be:
gem 'json', '1.6.7'
gem 'multi_json', '1.5.0'
but leave some security issues open. Explicitly supplying create_additions: true to JSON parse when needed is recommended.

Rails 3 scoped finds giving ActiveRecord::ReadOnlyRecord

I am upgrading a Rails application from 2.3.10 to 3.0.4 and am running into an issue with updating models in my controller. I have been "scoping" model finds in order to prevent users from updating objects that don't belong to them. It works as expected in 2.3, but I get an ActiveRecord::ReadOnlyRecord error with update_attributes in Rails 3.
What is the right way to do this in Rails 3?
Project controller:
def update
#project = current_user.projects.find(params[:id])
if #project.update_attributes(params[:project])
# saved
else
# not saved
end
end
It turns out it was related to using scopes to impersonate active record associations. I was able to fix it by adding .readonly(false) to my scopes.
One possible solution is create new file config/active_record_monkey_patch.rb and add following content in it.
module ReadOnlyFalse
def self.included(base)
base.class_eval do
def readonly?
false
end
end
end
end
ActiveRecord::Base.send(:include, ReadOnlyFalse)
above code work for all models readonly(false).

Resources