ActiveModel Serializers: How do I serialize a resource collection?

10,366

Solution 1

turns out I need to include v0.9 of the gem

gem 'active_model_serializers', github: 'rails-api/active_model_serializers', branch: '0-9-stable'

Solution 2

you could try change:

def index
  user = User.find_by(username: params[:username])
  bookmarks = user.bookmarks
  bookmarks.map { |bookmark| ::BookmarkSerializer.new(bookmark)}.to_json #updated line
end

to:

def index
  user = User.find_by(username: params[:username])
  bookmarks = user.bookmarks
  render json: bookmarks.map { |bookmark| ::BookmarkSerializer.new(bookmark)}
end
Share:
10,366
Amit Erandole
Author by

Amit Erandole

I am the content head of my very own web marketing agency, based out of Mumbai. I am a writer by profession but the dark side of my nature seems to have turned towards programming. I will have my vengeance!! I love learning javascript and ruby and amazed by the power of meta programming and shit I don't know but am very curious about.

Updated on June 09, 2022

Comments

  • Amit Erandole
    Amit Erandole almost 2 years

    I have a bookmarks resource and have mapped it to serve json by default under my api namespace like so in my routes.rb:

      namespace :api, defaults: {format: 'json'} do
        resources :bookmarks
        get ':username', to: 'users#index'
        get ':username/bookmarks/:id', to: 'users#show'
      end
    

    I have a Api::UsersController controller and a supporting BookmarkSerializer that works just fine on an individual bookmark resource like http://localhost:3000/api/emma_carter/bookmarks/87

    But when I try to hit http://localhost:3000/api/emma_carter which is supposed to serve all bookmarks owned by the user, I get all different kinds of errors. Here is my Api::UsersController

    module Api
        class UsersController < ApplicationController
            respond_to :json
    
            def index
                user = User.find_by(username: params[:username])
                bookmarks = user.bookmarks
                render json: bookmarks
            end
    
            def show
                user = User.find_by(username: params[:username])
                bookmark = user.bookmarks.find_by(params[:id])
                render json: bookmark
            end
        end
    end
    

    The show method works but the index method gives me ArgumentError in Api::UsersController#index

    wrong number of arguments (1 for 0)
    

    UPDATE: Full stack trace here: https://gist.github.com/amite/b79fc42bfd73de5a07bd

    screenshot

    enter image description here

    Here is the serializer:

    class BookmarkSerializer < ActiveModel::Serializer
        attributes :id, :url, :title, :domain, :notes, :image, :created, :username
        belongs_to :user
    
        def created
            object.created_at
        end
    
        def username
            user.username
        end
    end
    

    Looking at other solutions on stack overflow, I have also tried other versions of my index method:

            def index
                user = User.find_by(username: params[:username])
                bookmarks = user.bookmarks
                bookmarks.map { |bookmark| ::BookmarkSerializer.new(bookmark)}.to_json #updated line
            end
    

    This gives me the error:

    Missing template api/users/index, application/index with {:locale=>[:en], :formats=>[:json], :variants=>[], :handlers=>[:erb, :builder, :raw, :ruby, :coffee, :jbuilder]}.
    

    Next the last version of my index method looks like this:

    def index
      user = User.find_by(username: params[:username])
      bookmarks = user.bookmarks
      ActiveModel::ArraySerializer.new(bookmarks, each_serializer: ::BookmarkSerializer).to_json
    end
    

    This gives me the error uninitialized constant ActiveModel::ArraySerializer

    What am I doing wrong? I am using rails 4.1.5 and the github version of the active_model_serializers gem.

    gem 'active_model_serializers', github: 'rails-api/active_model_serializers'
    

    UPDATE: Since I am trying to output a collection of bookmarks I also tried using a separate serializer BookmarksSerializer but I am getting the same error: ArgumentError in Api::UsersController#index wrong number of arguments (1 for 0)

    UPDATE2: Here is a version of the index method that kinda works in the sense that it renders the resource collection in json format:

        def index
            user = User.find_by(username: params[:username])
            bookmarks = user.bookmarks
    
            respond_with bookmarks.to_json
        end
    

    But this still does not use the BookmarksSerializer

    class BookmarksSerializer < ActiveModel::Serializer
        attributes :id, :title
    end
    

    It just outputs the default hash

    Full Gemfile

    source 'https://rubygems.org'

    # Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
    gem 'rails', '4.1.5'
    # Use mysql as the database for Active Record
    gem 'mysql2'
    # Use SCSS for stylesheets
    gem 'sass-rails', '~> 4.0.3'
    # Use Uglifier as compressor for JavaScript assets
    gem 'uglifier', '>= 1.3.0'
    # Use CoffeeScript for .js.coffee assets and views
    gem 'coffee-rails', '~> 4.0.0'
    # See https://github.com/sstephenson/execjs#readme for more supported runtimes
    # gem 'therubyracer',  platforms: :ruby
    
    gem 'bourbon'
    gem 'neat'
    gem 'bitters'
    gem 'refills'
    
    gem 'wisper'
    gem 'rails-ioc'
    gem 'reform'
    gem 'cells'
    gem "pundit"
    
    gem 'active_model_serializers', github: 'rails-api/active_model_serializers'
    
    gem "font-awesome-rails"
    
    gem 'simple_form'
    
    # Use jquery as the JavaScript library
    gem 'jquery-rails'
    
    # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
    gem 'jbuilder', '~> 2.0'
    # bundle exec rake doc:rails generates the API under doc/api.
    gem 'sdoc', '~> 0.4.0',          group: :doc
    
    group :development, :test do
      # Call 'debugger' anywhere in the code to stop execution and get a debugger console
      gem 'byebug'
      gem 'ffaker'
      gem 'pry-rails'
    
      gem 'capybara'
      gem 'factory_girl_rails'
      gem 'database_cleaner'
      gem 'capybara-webkit'
      gem 'rspec-cells'
    
      # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
      gem 'spring'
    
      gem 'spring-commands-rspec'
      gem 'rspec-rails'
      gem 'guard-rspec'
      gem 'rb-fsevent' if `uname` =~ /Darwin/
    end
    
    # Use ActiveModel has_secure_password
    gem 'bcrypt', '~> 3.1.7'
    
    # Use unicorn as the app server
    # gem 'unicorn'
    
    # Use Capistrano for deployment
    # gem 'capistrano-rails', group: :development
    
    # Use debugger
    # gem 'debugger', group: [:development, :test]
    
  • Amit Erandole
    Amit Erandole over 9 years
    tried that - it returns the default json hash map - the serializer simply does not have any affect
  • Igor Guzak
    Igor Guzak over 9 years
    even with }.to_json in the end
  • Amit Erandole
    Amit Erandole over 9 years
    yup I tried with that too - wasted entirety of last night with this - see simplified version of the same question: stackoverflow.com/questions/25578786/…
  • Igor Guzak
    Igor Guzak over 9 years
    just for check, could you try leave just few attributes in BookmarkSerializer (id, title) and then render json: bookmarks?