nesquena / rabl

General ruby templating with json, bson, xml, plist and msgpack support
http://blog.codepath.com/2011/06/27/building-a-platform-api-on-rails/
MIT License
3.65k stars 335 forks source link

Error trying to cache RABL views #413

Open andrewhubbs opened 11 years ago

andrewhubbs commented 11 years ago

The basic error I am getting is this:

ActionView::Template::Error (no _dump_data is defined for class Proc):
    1: object @companies
    2: extends "companies/show"
  app/views/companies/show.json.rabl:5:in `block in render'
  app/views/companies/index.json.rabl:1:in `_app_views_companies_index_json_rabl___4497490218609257421_70338596442820'

My views look something like this:

# companies/index.json.rabl
object @companies
extends "companies/show"

# companies/show.json.rabl
object @company
attributes :name, owner_id, :id, :created_at, :updated_at
node :employees do |company|
  partial "employees/index", object: company.employees
end
# ...

# employees/index.json.rabl
collection @employees
extends "employees/show"

# employees/show.json.rabl
object @employee
cache [root_object, root_object.teams] # << Only cache line in project

attributes :email, :roles, :icon_url, :name, :phone_number, :id, :created_at, :updated_at
node :teams do |employee|
  partial "teams/index", object: employee.teams
end
# ...

Any thoughts on what is going on here?

Relevant config:

# RABL config
Rabl.configure do |config|
  config.cache_engine = Rabl::CacheEngine.new # Defaults to Rails cache
  config.include_json_root = false
end

# Rails config
App::Application.configure do
  config.action_controller.perform_caching = true
end
andrewhubbs commented 11 years ago

This may be a bug in Rails. The error is very similar to this bug and changing the objects I am passing into the partials into arrays seems to fix it.

cache [root_object, root_object.teams.to_a] # << Notice the `to_a`

node :teams do |employee|
  partial "teams/index", object: employee.teams.to_a # << Notice the `to_a`
end

Having to do this everywhere seems like a pretty lame solution. Any other thoughts?

andrewhubbs commented 11 years ago

So after more digging I think it is a little more complicated. I have narrowed it down to a specific has_many relation between a few of my models. The relation looks something like this:

class Employee < ActiveRecord::Base
  has_many :assigned_items, class_name: ChecklistItem, finder_sql: Proc.new {
    %Q{
      SELECT "checklist_items".* FROM "checklist_items"
      INNER JOIN "checklists" ON "checklists"."id" = "checklist_items"."checklist_id"
      WHERE "checklist_items"."employee_id" = #{id} AND "checklist_items"."active" = 't' AND "checklists"."active" = 't'
      ORDER BY "checklist_items".created_at
    }
  }
end

Looks like the finder_sql is the real culprit here. The to_a solution above doesn't seem to do the trick either.

andrewhubbs commented 11 years ago

While their could be a problem in Rails, I am starting to think this is a RABL issue with writing cache values that can't be fetched back out. See the issue, referenced above this comment too.

jharbert commented 10 years ago

@andrewhubbs did you ever find a solution to this? I'm running into the same issue

NoumanShahid commented 7 years ago

+1