Search code examples
ajaxruby-on-rails-3has-manybelongs-to

How to include an associated object in a render action


I have a story model that has many posts:

story.rb:

  has_many      :posts, :dependent  =>  :destroy

post.rb:

  belongs_to    :story, :touch => true

I use AJAX to make a get request to my stories#index action, and in that action I generate a response consisting of an array of Stories that conform to my search parameters. I include some additional data in my response, like whether or not there is a current_user, and the date through which my the search looked for stories:

  def index
    ajax_response = {}
    ajax_response[:currentUser] = user_signed_in? ? current_user : "no current user"
    searched_through_date = Stories.last.created_at
    @stories = get_stories(params,searched_through_date)
    if @stories && @stories.length << 200
      ajax_response[:stories] = @stories 
      ajax_response[:searched_through_date] = searched_through_date
    else #only happens if there are too many responsive stories
      ajax_response[:error] = {:type => "Response too large", :number_of_stories => @stories.length }
    end 
    render :json => ajax_response
  end

Now I want to change the response so that each story that I return has an additional attribute, :latest_post, which consists of the most recent post belonging to that story. As a relative nOOb, I am having trouble modifying my story objects so that they include this new attribute/association, which is then rendered with the story object as part of the response.

Any help would be greatly appreciated!

EDIT:

Here is the relevant portions of the get_stories method:

  def get_stories(params)
    q = get_story_search_params(params) 
    Story.search_with_params(q).limit(q[:limit]).offset(q[:offset])
  end

  def get_story_search_params(params)
    q = {}
    q[:limit] = params[:limit].blank? ? 25 : params[:limit].to_i 
    q[:text_to_search] = params[:text_to_search].blank? ? nil : params[:text_to_search]
    q[:offset] = params[:offset].blank? ? 0 : params[:offset]
    return q
  end

Solution

  • I solved this problem with the help of the rabl gem. Coming up with the correct DSL syntax proved a little trial-and-error prone. The key was using object false in the stories/index.json.rabl view and making good use of rabl partials. In hopes that it might help someone out, I've attached my working code here.

    #stories/index.json.rabl
    
    object false
    
    node(:currentUser) do
      if user_signed_in?
        partial('users/show', :object => current_user)
      else
        "no current user"
      end
    end
    
    node(:stories) do 
      partial('stories/list', :object => @stories )
    end
    
    node(:searched_through_date) { |m| @searched_through_date }
    

    #stories/show.json.rabl
    
    object @story
    
    attributes  :address, :category, :created_at, :username 
    
    node :latest_post do |story| 
      { :post => partial("posts/show", :object => story.posts.first) }
    end
    

    #stories/list.json.rabl
    
    collection @stories, :object_root => "story"
    
    extends "stories/show"
    

    #user/show.json.rabl
    
    object @user
    
    node :user do |u|
      { :email => u.email, :username => u.username, :preferred_post_to_facebook => u.preferred_post_to_facebook, 
        :preferred_tweet_to_twitter => u.preferred_tweet_to_twitter, :home_address => u.home_address, 
        :home_lat => u.home_lat, :home_lng => u.home_lng, :suspended => u.suspended }
    end