Tali Luvhengo
Tali Luvhengo

Reputation: 359

Rest Api Ruby On Rails Nested Models

I'm kinda new to the whole rails/ruby thing. I've built a restful API for an invoicing app. Summary of models is below.

class Invoice < ActiveRecord::Base
    has_many :pages
end

class Page < ActiveRecord::Base
    belogs_to :invoice
    has_many :rows
end

class Row < ActiveRecord::Base
    belogs_to :page
end

I would like to be able to include related models in one rest call. I can currently do one level of nesting. For example i can get an Invoice with all its pages /invoices?with=pages is the call i would make. In controller i would create a hash array from this as per below(probably not the best code you've seen):

def with_params_hash
  if(params[:with])
    withs = params[:with].split(',')
        withs.map! do |with|
        with.parameterize.underscore.to_sym
    end
    withs
  else
    nil
  end
end

This will return a hash as array e.g [:pages]

In the controller i use it as

@response = @invoice.to_json(:include => with_params_hash)

This works fine. I would like to be able to include nested models of say page.

As you know this can be done this way:

@invoice.to_json(:include => [:page => {:rows}])

The first question i guess is how do i represent this in the URL? I was thinking: /invoices?with=pages>rows. Assuming thats how I decide to do it. How do i then convert with=pages>rows into [:pages => {:rows}]

Upvotes: 0

Views: 502

Answers (2)

Tali Luvhengo
Tali Luvhengo

Reputation: 359

So i ended up going with the format below for url:

/invoices?with=pages>rows

The function below will generate the function required:

def with_params_hash
    final_arr = []
    with_array = params[:with].split(',')
    with_array.each do |withstring|
        if withstring.include? ">"
            parent = withstring[0..(withstring.index('>')-1)].parameterize.underscore.to_sym
            sub = withstring[(withstring.index('>')+1)..withstring.length].parameterize.underscore.to_sym
            final_arr << {parent => {:include => sub}}
        else
            final_arr << withstring.parameterize.underscore.to_sym
        end
    end
    final_arr
end

Usage in the controller looks like:

@invoice.all.to_json(:include => with_params)

Alternatively as per @DavidGuerra's idea https://github.com/rails/jbuilder is not a bad option.

Upvotes: 0

J. David Guerra
J. David Guerra

Reputation: 116

Why don't you use jbuilder? Will be easiest and you will can nest all models you want.

https://github.com/rails/jbuilder

Upvotes: 2

Related Questions