graphiti-api / graphiti

Stylish Graph APIs
https://www.graphiti.dev/
MIT License
985 stars 141 forks source link

undefined method `build_scope' for User #15

Closed srghma closed 7 years ago

srghma commented 7 years ago

I am trying to build sample application using devise_token_auth and pundit (later)

class ApplicationController < ActionController::Base
  include DeviseTokenAuth::Concerns::SetUserByToken
  include JsonapiSuite::ControllerMixin

  protect_from_forgery with: :null_session

  rescue_from Exception do |e|
    handle_exception(e)
  end
end

class ProjectResource < ApplicationResource
  type :projects

  allow_filter :id
  allow_filter :name
end

class SerializableProject < JSONAPI::Serializable::Resource
  type :projects

  attribute :name
end

class ProjectsController < ApplicationController
  before_action :authenticate_user!

  jsonapi resource: ProjectResource

  def index
    projects = current_user.projects
    render_jsonapi(projects) # error here
  end
end

backtrace

I am trying render_jsonapi(projects, scope: false) and it raise #<NoMethodError: undefined methodtype' for #>`, backtrace

test with error here

richmolj commented 7 years ago

Thanks for providing a sample application...unfortunately I cannot reproduce. That test does not raise an error (for me it fails on the json_included_types assertion which should be expected at this point). I also manually seeded a user and a project, changed from current_user to User.first and did not have a problem actually hitting the endpoint. Full disclosure, I did this on ruby 2.3.0.

srghma commented 7 years ago

@richmolj Can't do the same on my computer P.S. I've removed tests that are not indented to pass for now

 ✘  ~/projects/ngrx-todolist   master ●  rspec
RubyDep: WARNING: Your Ruby is outdated/buggy.
RubyDep: WARNING: Your Ruby is: 2.3.0 (buggy). Recommendation: upgrade to 2.3.1.
RubyDep: WARNING: (To disable warnings, see:http://github.com/e2/ruby_dep/wiki/Disabling-warnings )
#<NoMethodError: undefined method `build_scope' for #<User:0x00000007d7df78>>                                          |  ETA: 00:00:09

  1) Projects:  GET #index returns curent users projects
     Failure/Error: expect(response).to have_http_status(:ok)
       expected the response to have status code :ok (200) but it was :internal_server_error (500)
     # ./spec/api/projects_spec.rb:21:in `block (3 levels) in <top (required)>'

 24/24 |==================================================== 100 =====================================================>| Time: 00:00:01

Finished in 1.62 seconds (files took 3.06 seconds to load)
24 examples, 1 failure

Failed examples:

rspec ./spec/api/projects_spec.rb:18 # Projects:  GET #index returns curent users projects
srghma commented 7 years ago

So, the problem is @resource is overwritten by devise_token_auth here

I have made pull request. . What do you think?

srghma commented 7 years ago

Cant find where I have done error, @richmolj can you help me, its weird because on end of assign all is right, code

require 'jsonapi_compliable/adapters/active_record'

class ApplicationResource < JsonapiCompliable::Resource
  use_adapter JsonapiCompliable::Adapters::ActiveRecord

  # I dont want to install kaminary, so just render all
  paginate do |scope, _current_page, _per_page|
    scope
  end

  def self.my_has_many(childen_type, sideload: true)
    child_type   = childen_type.to_s.singularize.to_sym
    my_type      = config[:type].to_s.singularize.to_sym

    child_class                  = child_type.to_s.camelize.constantize
    child_resource_class         = "#{child_class}Resource".constantize
    foreign_key_pointed_on_me    = "#{my_type}_id".to_sym

    debug = {
      child_type: child_type,
      my_type: my_type,
      child_class: child_class,
      child_resource_class: child_resource_class,
      foreign_key_pointed_on_me: foreign_key_pointed_on_me
    }

    pp "------", debug

    has_many childen_type,
             foreign_key: foreign_key_pointed_on_me,
             scope: -> { child_class.all },
             resource: child_resource_class

    return unless sideload

    allow_sideload childen_type, resource: child_resource_class do
      scope do |we|
        child_class.where(foreign_key_pointed_on_me => we.map(&:id))
      end

      assign do |we, children|
        we.each do |me|
          my_children = children.select { |c| c.send(foreign_key_pointed_on_me) == me.id }
          me.send("#{childen_type}=", my_children)
        end
      end
    end
  end
end
 $ clear; rspec spec/api/projects_spec.rb:23
Run options: include {:locations=>{"./spec/api/projects_spec.rb"=>[23]}}
"------"                                                                                                               |  ETA: ??:??:??
{:child_type=>:attachment,
 :my_type=>:comment,
 :child_class=>
  Attachment(id: integer, file: string, comment_id: integer, created_at: datetime, updated_at: datetime),
 :child_resource_class=>AttachmentResource,
 :foreign_key_pointed_on_me=>:comment_id}
"------"
{:child_type=>:comment,
 :my_type=>:task,
 :child_class=>
  Comment(id: integer, text: text, task_id: integer, created_at: datetime, updated_at: datetime),
 :child_resource_class=>CommentResource,
 :foreign_key_pointed_on_me=>:task_id}
"------"
{:child_type=>:task,
 :my_type=>:project,
 :child_class=>
  Task(id: integer, done: boolean, name: string, deadline: datetime, position: integer, project_id: integer, created_at: datetime, updated_at: datetime),
 :child_resource_class=>TaskResource,
 :foreign_key_pointed_on_me=>:project_id}
"pp json ="
{"data"=>
  [{"id"=>"1",
    "type"=>"projects",
    "attributes"=>{"name"=>"Porro nostrum ut delectus impedit deserunt qui."}},
   {"id"=>"2",
    "type"=>"projects",
    "attributes"=>{"name"=>"Tempore accusamus atque qui sint ut occaecati."}}],
 "meta"=>{}}

  1) Projects:  GET #index returns curent users projects
     Failure/Error: expect(json_included_types).to match_array %w[tasks comments attachments]

       expected collection contained:  ["attachments", "comments", "tasks"]
       actual collection contained:    []
       the missing elements were:      ["attachments", "comments", "tasks"]
     # ./spec/api/projects_spec.rb:24:in `block (3 levels) in <top (required)>'

 1/1 |===================================================== 100 ======================================================>| Time: 00:00:00

Finished in 0.61888 seconds (files took 3.38 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./spec/api/projects_spec.rb:18 # Projects:  GET #index returns curent users projects
richmolj commented 7 years ago

Based on the JSON response, you haven't added the relationships to your SerializableProject, is that the case?

Separately, what are you trying to do with this code customization - just debug or something else? I don't think you should have to get this low-level if you are using AR.

richmolj commented 7 years ago

Feel free to ask questions like this in Slack as well: https://jsonapi-suite.slack.com/

srghma commented 7 years ago

Lol, I dont get decumentation, now I see, big thanks :sleepy:

srghma commented 7 years ago

For slack one needs invitation

richmolj commented 7 years ago

Just let me know your email address :) Send to richmolj@gmail.com if you don't want on GH.

srghma commented 7 years ago

I think its better to stay in github - others will be able to see solutions )