trailblazer / roar-rails

Use Roar's representers in Rails.
http://roar.apotomo.de
MIT License
235 stars 65 forks source link

Capybara test failing with undefined method `collect' for nil:NilClass thrown by representable-1.8.5/lib/representable/bindings/hash_bindings.rb:40:in 'serialize' #69

Closed reconstructions closed 10 years ago

reconstructions commented 10 years ago

I have persistent intermittent undefined method 'collect' for nil:NilClass failures in rSpec/Capybara request specs. Different tests fail, but it is usually the failure to find a button or the failure to reach a page with a button click which causes them. Their are some other weird failures as well, but this one is the only stack trace I have right now.

I can point you to the app if it would help. Thanks!

Failures:

  1) User Pages & Sessions: new registration with invalid email and password 
     Failure/Error: page.find(:xpath, '//input[@name="sign_up_new_registration"]').click
     NoMethodError:
       undefined method `collect' for nil:NilClass
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/representable-1.8.5/lib/representable/bindings/hash_bindings.rb:40:in `serialize'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/representable-1.8.5/lib/representable/bindings/hash_bindings.rb:22:in `write'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/representable-1.8.5/lib/representable/hash/collection.rb:23:in `create_representation_with'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/representable-1.8.5/lib/representable/hash.rb:39:in `to_hash'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/roar-0.12.7/lib/roar/representer/json.rb:26:in `to_hash'
     # /Users/reconstructions/.rvm/rubies/ruby-2.1.0/lib/ruby/2.1.0/tmpdir.rb:126:in `try_convert'
     # /Users/reconstructions/.rvm/rubies/ruby-2.1.0/lib/ruby/2.1.0/tmpdir.rb:126:in `create'
     # /Users/reconstructions/.rvm/rubies/ruby-2.1.0/lib/ruby/2.1.0/tempfile.rb:136:in `initialize'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/capybara-2.2.1/lib/capybara/rack_test/form.rb:8:in `new'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/capybara-2.2.1/lib/capybara/rack_test/form.rb:8:in `initialize'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/capybara-2.2.1/lib/capybara/rack_test/form.rb:42:in `new'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/capybara-2.2.1/lib/capybara/rack_test/form.rb:42:in `block in params'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/nokogiri-1.6.2.1/lib/nokogiri/xml/node_set.rb:237:in `block in each'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/nokogiri-1.6.2.1/lib/nokogiri/xml/node_set.rb:236:in `upto'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/nokogiri-1.6.2.1/lib/nokogiri/xml/node_set.rb:236:in `each'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/capybara-2.2.1/lib/capybara/rack_test/form.rb:27:in `map'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/capybara-2.2.1/lib/capybara/rack_test/form.rb:27:in `params'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/capybara-2.2.1/lib/capybara/rack_test/form.rb:74:in `submit'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/capybara-2.2.1/lib/capybara/rack_test/node.rb:56:in `click'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/capybara-2.2.1/lib/capybara/node/element.rb:118:in `block in click'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/capybara-2.2.1/lib/capybara/node/base.rb:81:in `synchronize'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/capybara-2.2.1/lib/capybara/node/element.rb:118:in `click'
     # ./spec/requests/users_pages_spec.rb:140:in `block (4 levels) in <top (required)>'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/example.rb:237:in `instance_eval'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/example.rb:237:in `instance_eval'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/hooks.rb:21:in `run'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/hooks.rb:85:in `block in run'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/hooks.rb:85:in `each'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/hooks.rb:85:in `run'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/hooks.rb:446:in `run_hook'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/example_group.rb:345:in `run_before_each_hooks'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/example.rb:294:in `run_before_each'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/example.rb:113:in `block in run'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/example.rb:179:in `call'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/example.rb:179:in `run'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/extensions/instance_eval_with_args.rb:16:in `instance_exec'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/extensions/instance_eval_with_args.rb:16:in `instance_eval_with_args'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/example.rb:247:in `instance_eval_with_args'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/hooks.rb:106:in `block (2 levels) in run'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/example.rb:179:in `call'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/example.rb:179:in `run'
     # ./spec/spec_helper.rb:36:in `block (2 levels) in <top (required)>'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/extensions/instance_eval_with_args.rb:16:in `instance_exec'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/extensions/instance_eval_with_args.rb:16:in `instance_eval_with_args'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/example.rb:247:in `instance_eval_with_args'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/hooks.rb:106:in `block (2 levels) in run'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/hooks.rb:108:in `call'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/hooks.rb:108:in `run'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/hooks.rb:446:in `run_hook'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/example_group.rb:340:in `run_around_each_hooks'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/example.rb:256:in `with_around_each_hooks'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/example.rb:111:in `run'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/example_group.rb:390:in `block in run_examples'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/example_group.rb:386:in `map'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/example_group.rb:386:in `run_examples'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/example_group.rb:371:in `run'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/example_group.rb:372:in `block in run'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/example_group.rb:372:in `map'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/example_group.rb:372:in `run'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/example_group.rb:372:in `block in run'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/example_group.rb:372:in `map'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/example_group.rb:372:in `run'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/command_line.rb:28:in `block (2 levels) in run'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/command_line.rb:28:in `map'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/command_line.rb:28:in `block in run'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/reporter.rb:58:in `report'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/command_line.rb:25:in `run'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/runner.rb:80:in `run'
     # /Users/reconstructions/.rvm/gems/ruby-2.1.0@sfrc/gems/rspec-core-2.14.8/lib/rspec/core/runner.rb:17:in `block in autorun'
apotonick commented 10 years ago

This is most probably because you use representers as modules. They in turn get extended into a model and then stay there. This model, for whatever reasons, now slips into the capybara workflow and Tempfile calls to_hash - which is the "wrong" method from Roar.

That is just a guess, but that should be it.

Either find out how your object remains extended with a representer and why it ends up in the Capybara flow, or use Decorators instead of module representers.

A weird problem, I have to admit. Would be interesting to see how your representers are used in the app?!

reconstructions commented 10 years ago

Thanks for your helpful response. Sounds convincing about module vs. class representers. How representers are getting called from Capybara I can't tell. As far as I can tell I am only referencing the representers in controller specs, not request specs. Here is some of my code:

app/representers/songs_representer.rb:

module SongsRepresenter
  include Representable::JSON::Collection
  include Roar::Representer::JSON

  self.representation_wrap = :songs

  collection :songs do
    property :id
    property :song_name
  end
end

app/controllers/songs_controller.rb

 class SongsController < ApplicationController

  include Roar::Rails::ControllerAdditions
  respond_to :json, :html

  def index
    @search = Sunspot.search(Song) do
      fulltext params[:search]
      paginate(page: params[:page])
    end
    @songs = @search.results

    respond_with @songs,
      :represent_with => SongsRepresenter
  end
end

app/spec/controllers/songs_controller_spec

  require "spec_helper"
  describe SongsController do

    include Representable::JSON::Collection

    before do
      @valid_session = {}
      @valid_attributes = attributes_for(:song)
      @invalid_params = attributes_for(:song, song_name: nil)
    end

    before(:each) do
      create_signed_in_user(no_capybara: true)
      @song = create(:song, :song_album => "Metallica") # :song_name => "Sandman"
    end 

    describe "GET #index" do
      before(:each) do
        @dead_flowers = create(:song, 
          :song_name => "Dead Flowers",
          :song_album => "Sticky Fingers", 
          :song_author => "The Rolling Stones" )
      end

      context "html with no search term" do
        before { get :index, {search: ""}, @valid_session }

        it "performs a sunspot Song search" do
          Sunspot.session.should be_a_search_for(Song)
          Sunspot.session.should have_search_params(:fulltext, "")
        end

        # this correctly assigns @songs with two songs, :song_name => ["Sandman", "Dead Flowers"]
        it "return all records as @songs" do
          expect(assigns(:songs)).to match_array(Song.solr_search.results)
        end

        it "and render the #index template" do  
          expect(response).to render_template :index
        end
      end

      context "in .json format" do
        before do
          @songs_expected = %({"songs":[{"song_name":"Dead Flowers"}, {"song_name":"Sandman"}]})
        end

        # Here is where I am extending with representers in tests
        it "formats .json using a SongsRepresenter, testing using extend" do

          # this is a passing test, but perhaps the one causing the failures?
          songs_json = [@dead_flowers, @song].extend(SongsRepresenter).to_json
          expect(songs_json).to be_json_eql(@songs_expected)
        end

        # And there is more trouble down here...
        describe "with no search term" do
          before do
           # this is the same sunspot search which works fine in html above...
           get :index, {search: ""}, :format => :json
           # and in the browser it returns the same json string as @songs_expected:
           #=> {"songs":[{"song_name":"Dead Flowers"}, {"song_name":"Sandman"}]}
         end

        # but even though these are passing
        it "performs a sunspot Song search" do
          Sunspot.session.should be_a_search_for(Song)
          Sunspot.session.should have_search_params(:fulltext, "")
        end

        # this fails and says that the response.body does not eql @songs_expected
        # see details of test failure below
        it "responds with .json for an array of @songs" do
          expect(response.body).to be_json_eql(@songs_expected)
        end
      end
    end
  end
end

This isn't too legible without code coloring, but basically the test gets null from response.body while the browser gets the expected json.

1) SongsController GET #index in .json format with no search term responds with .json for an array of @songs
   Failure/Error: expect(response.body).to be_json_eql(@songs_expected)
     Expected equivalent JSON
     Diff:
     @@ -1,11 +1,2 @@
     -{
     -  "songs": [
     -    {
     -      "song_name": "Dead Flowers"
     -    },
     -    {
     -      "song_name": "Sandman"
     -    }
     -  ]
     -}
     +null

I tried swapping out my SongsRepresenter module for a SongsRepresenter class:

class SongsRepresenter < Representable::Decorator
  include Representable::JSON
  include Representable::JSON::Collection
  include Roar::Representer::JSON

  self.representation_wrap = :songs

  collection :songs do
    property :id
    property :song_name
  end
end

And using it in my tests like this:

it "formats .json using a SongsRepresenter, testing using class decorator" do
  songs_json = SongsRepresenter.new([@dead_flowers, @song]).to_json
  expect(songs_json).to be_json_eql(@songs_expected)
end

Which produced apparently inconsistent results in the browser: #=> {"songs":[{"id":330,"song_name":"Dead Flowers","song_author":"The Rolling Stones","song_album":"Sticky Fingers","created_at":"2014-07-12T02:07:54.087Z","updated_at":"2014-07-12T02:07:54.087Z"}]}

And the shell, where only the attributes seemed to present, with all the brackets missing:

1) SongsController GET #index in .json format formats .json using a SongsRepresenter, testing using extend
   Failure/Error: expect(songs_json).to be_json_eql(@songs_expected)
     Expected equivalent JSON
     Diff:

     @@ -1,9 +1,13 @@
      {
        "songs": [
          {
     +      "song_album": "Sticky Fingers",
     +      "song_author": "The Rolling Stones",
            "song_name": "Dead Flowers"
          },
          {
     +      "song_album": "Metallica",
     +      "song_author": "Motorhead",
            "song_name": "Sandman"
          }
        ]

The undefined method 'collect' for nil:NilClass errors (which precede the use of sunspot) are an annoyance, and I would like to be able to easily swap out classes for modules, but the problem with my sunspot tests I have to solve, and on that one I am stumped. I would really appreciate some insight on that failure!

Thanks in advance for the help.

apotonick commented 10 years ago

Is using Decorator an option for you at the moment?

By the way, you're using JSON::Collection wrong. After including this module, you can't use ::collection anymore, but have to use ::items. The correct use is documented here.

I looked through your code, you should not include JSON::Collection. This module is meant to represent a bare "lonely" collection, whereas in your representation you want a songs: key. Why are you doing it so complicated :grin: - just do this.

class SongsRepresenter < Representable::Decorator
  include Roar::Representer::JSON

  collection :songs do
    property :id
    property :song_name
  end
end

Does that do the trick??

apotonick commented 10 years ago

BTW, using Decorator is the way to go. I will discourage modules in Representable - they still work, but are slower and pollute your domain objects - hence our discussion here, hahaha.

reconstructions commented 10 years ago

Thanks for the tips - I guess the answer is that I was running into a lot of problems working with collections, which went away when I started including JSON::Collection. I found it difficult to identify a best practice which just worked in the documentation, so there was a lot of trial error pulling from Roar and Representable involved in getting things to work at all, thus the use of extend. I will start refactoring and see if I can clean things up. Thanks a lot for the pointers.

reconstructions commented 10 years ago

Trying to get this working with classes is reminding me of why I ended up using modules. I had a fairly simple use case, but modules was the only way I get what I needed using Roar/Representable.

I was trying to get a JSON API working which would produce this result from a singular Rails #show controller action:

{"songs":[{"id":11,"song_name":"Dead Flowers","song_author":"The Rolling Stones","song_album":"Sticky Fingers"}]}

And this one from a plural Rails #index controller action:

{"songs":[{"id":11,"song_name":"Dead Flowers","song_author":"The Rolling Stones","song_album":"Sticky Fingers"},{"id":12,"song_name":"The Wind Cries Mary","song_author":"Jimi Hendrix","song_album":"Are You Experienced?"}]}

I was able to do this with some difficulty, but it wasn't easy because of the magic which goes on with plural and singular Representer names. This worked (albeit with modules not classes):

class SongsController < ApplicationController

  def index

    @songs = ....

    respond_with @songs,
      :represent_with => SongsRepresenter
  end

  def show

    @song = ....

    respond_with @song,
      :represent_with => SongRepresenter
  end

If I didn't do it this way, I would end up with the usual kinds of errors you have when you treat collections as instances or vice versa, or when names are plural when they should be singular.

I got around this by having two representers:

app/representers/song_representer.rb

module SongRepresenter
  include Roar::Representer::JSON

  collection :songs do
    property :id
    property :song_name
    property :song_author
    property :song_album
  end

  def songs
    [represented]
  end
end

app/representers/songs_representer.rb

require 'representable/json/collection' 

module SongsRepresenter
  include Representable::JSON::Collection
  include Roar::Representer::JSON

  self.representation_wrap = :songs

  collection :songs do
    property :id
    property :song_name
    property :song_author
    property :song_album
  end
end

This did produce the correct strings, but I am sure it is a terrific hack and not how your framework was intended to be used. My problem was really that I couldn't figure out how to use the same Representer with either a collection or an instance variable, but however hard I looked, I couldn't find that in the documentation. I feel like I am going down a similar road with Cells.

I suspect one Representer should be able to do this, and if you could show me how, that could be added to the Wiki as a JSON API example. I have a lot of modules to tear out in my app, but if I could just understand the proper use I think I would be good to go.

Thanks again for the help - I tried to tear out some modules but immediately ran into this collections vs. instances problem in my #show action...

reconstructions commented 10 years ago

I can get close like this:

require 'roar/decorator'

class SongRepresenter < Roar::Decorator
  include Roar::Representer::JSON

  self.representation_wrap = :songs

  property :id
  property :song_name
  property :song_author
  property :song_album

  def songs
    [represented]
  end

end

With this in my controller:

render :json => SongRepresenter.new(@song).to_json

But it still lacks the brackets that should be around the songs collection:

returned: {"songs":{"id":11,"song_name":"Dead Flowers","song_author":"The Rolling Stones","song_album":"Sticky Fingers"}}

wished for: {"songs":[{"id":11,"song_name":"Dead Flowers","song_author":"The Rolling Stones","song_album":"Sticky Fingers"}]}

I can't use represented like I was before now that I am not working with a collection?

If I do this:

require 'roar/decorator'

class SongsRepresenter < Roar::Decorator
  include Roar::Representer::JSON

  self.representation_wrap = :songs

  collection :songs do
    property :id
    property :song_name
    property :song_author
    property :song_album
  end
end

And this in my controller:

render :json => SongsRepresenter.new(@song).to_json

I get an undefined method error:

undefined method 'songs' for #<Song:0x000001088ea2e8>

Thanks in advance!

reconstructions commented 10 years ago

If I use a class:

require 'roar/decorator'

class SongsRepresenter < Representable::Decorator
  include Roar::Representer::JSON

  collection :songs do
    property :id
    property :song_name
  end
end

In my controller #index:


def index
  @songs = Song.order(:song_name)

  respond_with @songs do |format|
    format.json { render :layout => false, :text => SongsRepresenter.new(@songs).to_json }
    format.html
  end
end

Then I get this error:

undefined method 'songs' for #<ActiveRecord::Relation::ActiveRecord_Relation_Song:0x00000108f890e0>

Whereas using a module in #index:

require 'representable/json/collection' 

module SongsRepresenter
  include Representable::JSON::Collection
  include Roar::Representer::JSON

  self.representation_wrap = :songs

  collection :songs do
    property :id
    property :song_name
    property :song_author
    property :song_album
  end
end

And this in my controller:

def index
  @songs = Song.order(:song_name)

  respond_with @songs,
    :represent_with => SongsRepresenter
end

Everything works fine:

{"songs":[{"id":11,"song_name":"Dead Flowers","song_author":"The Rolling Stones","song_album":"Sticky Fingers"},{"id":12,"song_name":"The Wind Cries Mary","song_author":"Jimi Hendrix","song_album":"Are You Experienced?"},{"id":13,"song_name":"The Thrill is Gone","song_author":"B.B. King","song_album":"Completely Well"},{"id":14,"song_name":"Rock Me Baby","song_author":"B.B. King","song_album":"Rock Me Baby"},{"id":15,"song_name":"Pentatonic B*mb","song_author":"Recon Vancouver","song_album":"NA"}]}

apotonick commented 10 years ago

You're lucky :grin: I started working with @oliverbarnes on JSON-API about a week ago.

Also, I want to make it easier to automatically have a collection representer for a single representer. My next week is allocated for that.

but however hard I looked, I couldn't find that in the documentation. I feel like I am going down a similar road with Cells.

I do understand your frustration about "the lack of documentation". I'm with you and you can always email me, hit me up on IRC or Skype, and so on. Nevertheless, at the same time, I have to state that every feature of Representable is documented in the README. Same goes for Cells. Naturally, this doesn't explain all your open questions. That's why I started writing a book about that.

apotonick commented 10 years ago

Including JSON::Collection into a representer that also defines collection is wrong and please don't do it. It is very very simple: Defining a property or collection will always call that method on the represented object when rendering.

Including JSON::Collection treats the represented object as an array (usually..... dunno how you managed to get that working) :wink: .

reconstructions commented 10 years ago

No worries ( or drama ), really appreciate the feedback and help. I am one of the ones who has been waiting for the book for sure ( A New Architecture for Rails?). I like both Cells and Roar/Representable.

I have removed the extend from my tests and things have been really stable ever since and some other bugs and failures have gone away. I am starting to refactor Representers as you suggested, perhaps just pulling out all the #show responses and moving the #index responses over to classes.

I think it would be great to try and demonstrate all the functionality in your docs using class decorators instead of module extension, so perhaps I will play with that some after I am done refactoring. Thanks again for the help and direction, and sorry to take time away from your book project! - Dave

apotonick commented 10 years ago

Dave- your input is always very valuable to me and the projects, so please don't hesitate to email me when you're in trouble.

reconstructions commented 10 years ago

No worries, Nick, thanks for the help. Here is a little thing I wrote on using Paloma with jQuery UJS and link_to tags:

https://github.com/kbparagua/paloma/wiki/HTML-Page-Changes-using-AJAX-with-Paloma-and-jQuery-in-Rails-4:

I would love to try and do a step-by-step tutorial like this on some Cell use cases... Or perhaps we have that to look forward to when your book is out!

All the best,

On Jul 17, 2014, at 3:20 PM, Nick Sutterer notifications@github.com wrote:

Dave- your input is always very valuable to me and the projects, so please don't hesitate to email me when you're in trouble.

— Reply to this email directly or view it on GitHub.

apotonick commented 10 years ago

What exactly is Paloma, @reconstructions ? Is that a JS library to support page updates from a Rails controller? Looking good!