Active Model Serializer customize json response - ruby-on-rails

So I'm having a problem with ams. I'm using Rails 5.2 and I read lots of tutorials and even when I did exactly what they showed I still have something that they don't and I didn't find answer on google.
I have model Course, Video, Quiz and Segment.
Course has many segment, segment can be video or quiz (I'm using sti).
This is how I wrote it:
app/models/course.rb
class Course < ApplicationRecord
validates :title ,presence: true
validates :author ,presence: true
has_many :videos
has_many :quizs
has_many :segments
end
app/models/segment.rb
class Segment < ApplicationRecord
belongs_to :course
end
app/models/quiz.rb
class Quiz < Segment
validates :course_id ,presence: true
validates :name ,presence: true
belongs_to :course
end
app/models/video.rb
class Video < Segment
validates :course_id ,presence: true
validates :name ,presence: true
belongs_to :course
end
app/controllers/courses_controller.rb
class CoursesController < InheritedResources::Base
def show
#course = Course.find(params[:id])
render json: #course.attributes
end
def index
#courses = Course.all
render json: #courses
end
end
app/serializers/course_serializer.rb
class CourseSerializer < ActiveModel::Serializer
attributes :title, :author
has_many :segments
end
and this is what is showed me
I have couple of problems:
I don't know where this data name come from and I don't know how to change it or hide it.
even when I request to see one course I get the created date and other stuff I didn't want, although I configured it so I only see title and author.
I want to know if I can custom the json response so I won't see the title of the relations or change it's name.

You haven't created a SegmentSerializer. By default, AMS will serialize all fields.
class SegmentSerializer < ActiveModel::Serializer
attributes :name
end
Remove the attributes method call. It returns a Hash and then your serializer is not used.
```
class CoursesController < InheritedResources::Base
def show
#course = Course.find(params[:id])
render json: #course
end
def index
#courses = Course.all
render json: #courses
end
end
```
Use the key option
has_many :segments, key: :your_key

Related

how to define association in ActiveModel::Serializer

I have following Serializer
class BookSerializer < ActiveModel::Serializer
attributes :id, :name, :publisher, :author, :cover_url
has_many :chapters
end
I have two method in bookscontroller.rb file as follows:
def index
books = Book.select(:id, :name, :publisher, :publisher, :cover, :author)
if books.present?
render json: books
end
end
def show
book = Book.find_by_id params[:id]
render json: book
end
Actually everything is working fine but the problem is I want chapters records in show page not on index page, but right now query for fetching chapters are running in both action but I only want to include has_many :chapters in show action.
So Is there any way that can I use association for particular method in rails controller?
You can use different serializers for different actions. For example, remove has_many :chapters from BookSerializer and create a separate BookWithChaptersSerializer. Use it as follows:
class BookWithChaptersSerializer < ActiveModel::Serializer
attributes :id, :name, :publisher, :author, :cover_url
has_many :chapters
end
def show
book = Book.find_by_id params[:id]
render json: book, serializer: BookWithChaptersSerializer
end

Two different classes using accepts_nested_attributes of one class

I have a class Addresse where Organismereferent and Organisme have a has_many belongs_to relationship with. Also Organismereferent and Organisme can accepts_nested_attributes_for :addresses
My problem is when I only had the Organismereferent class everything was working fine and I was able to create a new Organismereferent with an addresse but as soon as I created and added the same relation to Organisme , they both stopped working without giving any error message I only get this in the console:
My model:
class Organismereferent < ApplicationRecord
has_many :addresses
has_many :referents
accepts_nested_attributes_for :addresses
end
class Organisme < ApplicationRecord
has_many :addresses
accepts_nested_attributes_for :addresses
end
class Address < ApplicationRecord
belongs_to :organismereferent
belongs_to :organisme
end
Controller for Organisme
def new
#organisme = Organisme.new
#organisme.addresses.build
end
def create
#organisme = Organisme.new(organisme_params)
#organisme.status = true
#organisme.save
redirect_to #organisme
end
private
def organisme_params
params.require(:organisme).permit(:nom, :telephone, :courriel, :fax, addresses_attributes: [:id, :no_civique, :rue, :ville, :province, :etat, :code_postal])
end
Controller for Organismereferent:
def new
#organisme = Organismereferent.new
#organisme.addresses.build
end
def create
#organisme = Organismereferent.new(organisme_params)
#organisme.active = true
#organisme.save
redirect_to #organisme
end
private
def organisme_params
params.require(:organismereferent).permit(:nom_organisation, :bureau, :telecopie, :courriel, :site_web, addresses_attributes: [:id, :no_civique, :rue, :ville, :province, :etat, :code_postal])
end
I'm not sure what else information might be important so I'll be glad to add anything.
Try to change address model like
class Address < ApplicationRecord
belongs_to :organismereferent, optional: true
belongs_to :organisme, optional: true
end

Return multiple includes on object Ruby on Rails JSON

I have three models and am trying to output all of them as JSON in a single object.
The models and associations are as follows:
class Customer < ApplicationRecord
has_one :subscription
has_one :address
end
class Address < ApplicationRecord
belongs_to :customer
end
class Subscription < ApplicationRecord
belongs_to :customer
end
I am trying to return all of the associated data as JSON using the following:
class HomeController < ApplicationController
def index
#customers = Customer.all
render json: #customers, :include => :address, :subscription
end
end
However this is returning a syntax error where ruby is expecting => somewhere. Any help on how I can output all of this data would be much appreciated.
Incase anyone is looking I've just answered this question with the following syntax.
class HomeController < ApplicationController
def index
#customers = Customer.all
render json: #customers, :include => [:address, :subscription]
end
end
address and subscription needed to be passed in an array :)

Undefined Method when .build new Object

I'm new to Ruby on Rails and currently trying to make a little test website for me.I've got an issue in my code that states an "undefined method `service_providers' for #"
The line of code which produces the error is the following:
def new
#service_provider = current_user.service_providers.build(serviceprovider_params)
end
My Database Model is Table "User" has_one "ServiceProvider" has_many "Services".
I use the rubygem "devise" for the user-model.
I've tried to transfer the idea of the micropost of the "Ruby on Rails Tutorial" (https://www.railstutorial.org/book/user_microposts) in my example app. In Listing 13.36 there's also this code because with this ruby knows the reference between the current_user and the micrrpost.
I don't have an idea why it isn't working with my code:
Model
class ServiceProvider < ApplicationRecord
belongs_to :user
has_many :service
validates :name, presence: true
validates :street, presence: true
validates :plz, presence: true
validates :location, presence: true
validates :user_id, presence: true
end
Controller
class ServiceProvidersController < ApplicationController
before_action :set_serviceprovider, only: [:show, :edit, :update]
before_action :authenticate_user!
def index
end
def show
end
def new
#service_provider = current_user.service_providers.build(serviceprovider_params)
end
def create
#service_provider = current_user.service_provider.build(serviceprovider_params)
if #service_provider.save
redirect_to #service_provider, notice: "Gespeichert"
else
render :new
end
end
def edit
end
def update
end
private
def set_serviceprovider
#service_provider = Service_Provider.find(params [:id])
end
def serviceprovider_params
params.require(:service_provider).permit(:name, :street, :plz, :location)
end
end
ServiceProvider-Helper
module ServiceProvidersHelper
def current_service_provider
#current_service_provider = service_provider.user_id.find(current_user.id)
end
end
If there's some coding missing which you need for your help, please ask. I'm a newbie in coding with ruby, but i think taht must be the relevant parts of the code which is involved.
Thanks for help.
If you have has_one association then you need to use build_ASSOCIATION_NAME so in this case, it will be build_service_provider
#service_provider = current_user.build_service_provider(serviceprovider_params)
Also, I think you need to take a look at this association
class ServiceProvider < ApplicationRecord
belongs_to :user
has_many :service
If you are building an association with has_many then the class name should be plural.
Change it to
has_many :services

Serialize JSON association for children of a model

I'm using active-model-serializers for my API.
I have a model (Task) that has many subtasks(always Task model), called children.
I do this recursive has_many association thanks to ancestry gem (https://github.com/stefankroes/ancestry)
It works all enough well, but I have this problem:
Task has an association with User, but while active-model-serializers, export user for the main object, it doesn't show user details for also all children.
This is my serializer:
class TaskSerializer < ActiveModel::Serializer
attributes :id, :name, :details, :user_id
belongs_to :user
has_many :children
end
This is my controller:
class Api::V1::TasksController < Api::V1::BaseController
respond_to :json
def index
#tasks = current_user.company.tasks
respond_with #tasks, location: nil
end
end
And this is my model:
class Task < ActiveRecord::Base
has_ancestry
belongs_to :user
end
I've also tried to do this in my model:
class Api::V1::TasksController < Api::V1::BaseController
respond_to :json
def index
#tasks = current_user.company.tasks
render json: #tasks,
each_serializer: TaskSerializer,
status: :ok
end
end
But doesn't work...I've the user details for the parent object, but not for the children(where he only show me user_id, without all User object)
Any suggestions ?
Have you tried adding a serializer for the Children model or querying them as a explicit attribute like so?
class TaskSerializer < ActiveModel::Serializer
attributes :id, :name, :details, :user_id, :children
def children
object.children
end
end

Resources