0

I am creating a web application that utilizes Rails 3 to serve up JSON. I use AngularJS' ngResource to interact with the RESTful server-side data.

On the rails side, I have two models: Genre and Book.

  • Each Genre has_many Books
  • Each Book belongs_to a Genre
  • In routes.rb, my resources are listed as resources :genres, :books. They are not nested.

As I'm sure you know, this allows me to do things like call Genre.where(name: "sci-fi").first.books that returns me an array.

I'd like to do something like this from the Rails controller and the Angular ngResource factory. It's working properly for me for the standard REST operations...

However, I'm trying to define a custom REST operation where I could call something like this: Genre.books({ id: 1 }) and have it return an array of books that belongs to the Genre with an id of 1.

Here's my genres_controller.rb:

class GenresController < ApplicationController
  respond_to :json

  ... 

  def books
    @genre_books = Genre.where(id: params[:id]).first.books
    respond_with @genre_books
  end
end

Here's my Angular ngResource for genre (written in coffeescript):

app = angular.module("ATWP")

app.factory "Genre", ($resource) ->
  $resource "/genres/:id",
    id: "@id"
  ,
    ....

    books:
      method: "GET"

I've tried tacking on isArray: true to the REST operation to no avail. I simply get back the Genre resource itself but not an array of books that belong to the Genre.

So, what am I missing? Is it a bad idea in the first place to do something like what I'm trying to do in the above examples? Any input is appreciated.

1 Answer 1

1

If you created new controller action 'books', route resources will not pick it up. You should define custom route like match '/genrebooks/:id', to: 'genres#books', via: :get . Aafter that you should update your factory to match the new route.

Sign up to request clarification or add additional context in comments.

4 Comments

I rewrote my Angular resource, which can be found here in a Plunker. Is this the correct way to update the resource? I just tried doing it this way and I get a TypeError whenever I try to access Genre.index().
My bad, I should of told you to create new factory for the new route as well. app.factory "GenreBooks" $resource "/genrebooks/:id", id: "@id" , books: method: "GET" isArray: true When that is done call the new factory from the controller.
So it works. Thank you for your help! Thinking about it though, would it make more sense to nest the Book resource under Genre in the Rails routes file? The only problem I have is that there are times I'd like to get all Books, regardless of Genres.
It all depends on the app your building, personally in your case I'll keep it separate since you need Books without Genre. It will be easier to maintain and read later on.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.