Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NoMethodError in after callback inside Grape::Middleware::Formatter #2139

Open
Bilal-Abbas-Gigalabs opened this issue Dec 14, 2020 · 14 comments
Labels

Comments

@Bilal-Abbas-Gigalabs
Copy link

Bilal-Abbas-Gigalabs commented Dec 14, 2020

I am getting Grape::Middleware::Formatter : undefined method `collect' for #<Stream:0x00007f685ce13270>
My code works fine, I have tested each line by my hand but if I run the whole API this error appears.
My code is as follow

        @stream = Stream.new(stream_params)
        @stream.location_id = get_location
        @stream.user_id = @streamer.id
        @stream.university = @university
        @stream.category = @category
        @stream.save!
        status(200){
          'message': 'successfully created the stream request'
        }
@dnesteryuk
Copy link
Member

@Bilal-Abbas-Gigalabs which version of Grape and Rack do you use?

@Bilal-Abbas-Gigalabs
Copy link
Author

Bilal-Abbas-Gigalabs commented Dec 15, 2020

rack (~> 2.0, >= 2.0.8)
grape (1.5.1)
      activesupport
      builder
      dry-types (>= 1.1)
      mustermann-grape (~> 1.0.0)
      rack (>= 1.3.0)
      rack-accept
    grape-active_model_serializers (1.5.2)
      active_model_serializers (>= 0.10.0)
      grape (>= 0.8.0)
    grape_devise_token_auth (0.1.4)
      devise (>= 3.3)
      devise_token_auth (>= 0.1.32)
      grape (> 0.9.0)
    grape_on_rails_routes (0.3.2)
      rails (>= 3.1.1)
    groupdate (5.2.1)
      activesupport (>= 5)
    i18n (1.8.5)
      concurrent-ruby (~> 1.0)

@dblock
Copy link
Member

dblock commented Dec 15, 2020

I think this is because your method returns the stream somehow.

Noticing that status does not take a block. Try this:

... # your code that does something to Stream
status 200
{ 'message': 'successfully created the stream request' }

@dblock dblock added the bug? label Dec 15, 2020
@Bilal-Abbas-Gigalabs
Copy link
Author

Still getting the same error on above update !!!

@dblock
Copy link
Member

dblock commented Dec 15, 2020

Post the full stack please?

@Bilal-Abbas-Gigalabs
Copy link
Author

caught error of type NoMethodError in after callback inside Grape::Middleware::Formatter : undefined method `collect' for #<Stream:0x00007fdc60daa630>
  
NoMethodError (undefined method `collect' for #<Stream:0x00007fdc60daa630>):
  
activemodel (6.0.3.4) lib/active_model/attribute_methods.rb:432:in `method_missing'
grape (1.5.1) lib/grape/middleware/formatter.rb:47:in `block in build_formatted_response'
activesupport (6.0.3.4) lib/active_support/notifications.rb:182:in `instrument'
grape (1.5.1) lib/grape/middleware/formatter.rb:46:in `build_formatted_response'
grape (1.5.1) lib/grape/middleware/formatter.rb:30:in `after'
grape (1.5.1) lib/grape/middleware/base.rb:39:in `call!'
grape (1.5.1) lib/grape/middleware/base.rb:29:in `call'
grape (1.5.1) lib/grape/middleware/base.rb:36:in `call!'
grape (1.5.1) lib/grape/middleware/base.rb:29:in `call'
grape_devise_token_auth (0.1.4) lib/grape_devise_token_auth/middleware.rb:14:in `call'
grape (1.5.1) lib/grape/middleware/auth/base.rb:37:in `_call'
grape (1.5.1) lib/grape/middleware/auth/base.rb:19:in `call'
grape (1.5.1) lib/grape/middleware/error.rb:39:in `block in call!'
grape (1.5.1) lib/grape/middleware/error.rb:38:in `catch'
grape (1.5.1) lib/grape/middleware/error.rb:38:in `call!'
grape (1.5.1) lib/grape/middleware/base.rb:29:in `call'
rack (2.0.9) lib/rack/head.rb:12:in `call'
grape (1.5.1) lib/grape/endpoint.rb:231:in `call!'
grape (1.5.1) lib/grape/endpoint.rb:225:in `call'
grape (1.5.1) lib/grape/router/route.rb:58:in `exec'
grape (1.5.1) lib/grape/router.rb:116:in `process_route'
grape (1.5.1) lib/grape/router.rb:72:in `block in identity'
grape (1.5.1) lib/grape/router.rb:91:in `transaction'
grape (1.5.1) lib/grape/router.rb:70:in `identity'
grape (1.5.1) lib/grape/router.rb:55:in `block in call'
grape (1.5.1) lib/grape/router.rb:132:in `with_optimization'
grape (1.5.1) lib/grape/router.rb:54:in `call'
grape (1.5.1) lib/grape/api/instance.rb:167:in `call'
grape (1.5.1) lib/grape/api/instance.rb:71:in `call!'
grape (1.5.1) lib/grape/api/instance.rb:66:in `call'
grape (1.5.1) lib/grape/api.rb:68:in `call'
actionpack (6.0.3.4) lib/action_dispatch/routing/mapper.rb:19:in `block in <class:Constraints>'
actionpack (6.0.3.4) lib/action_dispatch/routing/mapper.rb:48:in `serve'
actionpack (6.0.3.4) lib/action_dispatch/journey/router.rb:49:in `block in serve'
actionpack (6.0.3.4) lib/action_dispatch/journey/router.rb:32:in `each'
actionpack (6.0.3.4) lib/action_dispatch/journey/router.rb:32:in `serve'
actionpack (6.0.3.4) lib/action_dispatch/routing/route_set.rb:834:in `call'
warden (1.2.9) lib/warden/manager.rb:36:in `block in call'
warden (1.2.9) lib/warden/manager.rb:34:in `catch'
warden (1.2.9) lib/warden/manager.rb:34:in `call'
rack (2.0.9) lib/rack/etag.rb:25:in `call'
rack (2.0.9) lib/rack/conditional_get.rb:38:in `call'
rack (2.0.9) lib/rack/head.rb:12:in `call'
activerecord (6.0.3.4) lib/active_record/migration.rb:567:in `call'
actionpack (6.0.3.4) lib/action_dispatch/middleware/callbacks.rb:27:in `block in call'
activesupport (6.0.3.4) lib/active_support/callbacks.rb:101:in `run_callbacks'
actionpack (6.0.3.4) lib/action_dispatch/middleware/callbacks.rb:26:in `call'
actionpack (6.0.3.4) lib/action_dispatch/middleware/executor.rb:14:in `call'
actionpack (6.0.3.4) lib/action_dispatch/middleware/actionable_exceptions.rb:18:in `call'
actionpack (6.0.3.4) lib/action_dispatch/middleware/debug_exceptions.rb:32:in `call'
actionpack (6.0.3.4) lib/action_dispatch/middleware/show_exceptions.rb:33:in `call'
railties (6.0.3.4) lib/rails/rack/logger.rb:37:in `call_app'
railties (6.0.3.4) lib/rails/rack/logger.rb:26:in `block in call'
activesupport (6.0.3.4) lib/active_support/tagged_logging.rb:80:in `block in tagged'
activesupport (6.0.3.4) lib/active_support/tagged_logging.rb:28:in `tagged'
activesupport (6.0.3.4) lib/active_support/tagged_logging.rb:80:in `tagged'
railties (6.0.3.4) lib/rails/rack/logger.rb:26:in `call'
actionpack (6.0.3.4) lib/action_dispatch/middleware/remote_ip.rb:81:in `call'
request_store (1.5.0) lib/request_store/middleware.rb:19:in `call'
actionpack (6.0.3.4) lib/action_dispatch/middleware/request_id.rb:27:in `call'
rack (2.0.9) lib/rack/runtime.rb:22:in `call'
activesupport (6.0.3.4) lib/active_support/cache/strategy/local_cache_middleware.rb:29:in `call'
actionpack (6.0.3.4) lib/action_dispatch/middleware/executor.rb:14:in `call'
actionpack (6.0.3.4) lib/action_dispatch/middleware/static.rb:126:in `call'
rack (2.0.9) lib/rack/sendfile.rb:111:in `call'
actionpack (6.0.3.4) lib/action_dispatch/middleware/host_authorization.rb:82:in `call'
rack-cors (1.1.1) lib/rack/cors.rb:100:in `call'
railties (6.0.3.4) lib/rails/engine.rb:527:in `call'
puma (4.3.7) lib/puma/configuration.rb:228:in `call'
puma (4.3.7) lib/puma/server.rb:713:in `handle_request'
puma (4.3.7) lib/puma/server.rb:472:in `process_client'
puma (4.3.7) lib/puma/server.rb:328:in `block in run'
puma (4.3.7) lib/puma/thread_pool.rb:134:in `block in spawn_thread'

@dblock
Copy link
Member

dblock commented Dec 15, 2020

I don't know how your Stream object is making this to the formatter part. Your code above creates it, assigns it to some @stream and then is done with it? Or are you returning it elsewhere? Post the complete API class?

Does the API return a result successfully without any of the stream = ... code?

I think you'll have to put up something that reproduces the problem from here for us to help.

@Bilal-Abbas-Gigalabs
Copy link
Author

That is my end point

    # ----------------------------------------------------
    # POST /
    # ----------------------------------------------------
    #
    desc 'Create stream request'
    post '/' do
      authenticate_api_admin_user!
        init_create
        @stream = Stream.new(stream_params)
        @stream.location_id = get_location
        @stream.user_id = @streamer.id
        @stream.university = @university
        @stream.category = @category

        unless params[:user][:streamImage].nil?
          s3 = Aws::S3::Resource.new(region:'eu-west-2')
          extension = params[:user][:streamImage][:filename].split('.').last
          filename = SecureRandom.uuid + "." + extension
          image = s3.bucket('communy-file-storage').object("stream_images/" + filename)
          image.upload_file(params[:user][:streamImage][:tempfile])
          @stream.stream_image = image.public_url.to_s
        end
        
        set_temp_date_to_stream

        survey = Survey.find(ActiveSupport::JSON.decode(params[:user][:survey])["id"]) if 
        ActiveSupport::JSON.decode(params[:user][:survey]).present?
        @stream.survey = survey if survey.present?

        @stream.save!

        @notification = Notification.new()
        @notification.title = "New Stream Request!"
        @notification.text = "Your university admin has invited you for a stream."
        @notification.type = Notification.types[:stream_request_from_university]
        @notification.user_id = @streamer.id

        @notification.save!

        assign_secondary_categories
        @stream_request = StreamRequest.new(stream_request_params)
        @stream_request.save!
        assign_time_ranges

        status 200
        {
          'message': 'successfully created the stream request'
        }
    end

Follwoing are my helpers

helpers do
    def stream_params
      @stream_params ||= {
        name: ActiveSupport::JSON.decode(params[:user][:title]),
        overview: ActiveSupport::JSON.decode(params[:user][:description]),
        publish_status: ActiveSupport::JSON.decode(params[:user][:isPublished]) ? 'broadcasted' : 'draft',
        streamer_status: 'waiting',
        agora_status: 'standby',
        stream_type: ActiveSupport::JSON.decode(params[:user][:streamType]) == 'Webinar' ? 1 : 0,
        repeat_stream: ActiveSupport::JSON.decode(params[:user][:repeatStream]).nil? ? 'None' : 
      ActiveSupport::JSON.decode(params[:user][:repeatStream])
      }
    end

    def update_stream_params
      @update_stream_params ||= {
        name: ActiveSupport::JSON.decode(params[:user][:title]),
        overview: ActiveSupport::JSON.decode(params[:user][:description]),
        repeat_stream: ActiveSupport::JSON.decode(params[:user][:repeatStream]).nil? ? 'None' : 
        ActiveSupport::JSON.decode(params[:user][:repeatStream]),
        category_id: ActiveSupport::JSON.decode(params[:user][:primaryCategory])
      }
    end

    def stream_request_params
      @stream_request_params ||= {
        requester: current_api_admin_user,
        requestee: @streamer,
        status: ActiveSupport::JSON.decode(params[:user][:isPublished]) ? 'pending' : 'draft',
        stream: @stream,
        from_university: true
      }
    end

    def location_params
      @location_params ||= {
        place: ActiveSupport::JSON.decode(params[:user][:location]),
        university_id: @university.id
      }
    end

    def init_create
      @university = current_api_admin_user.profession_university
      unless @university
        error!('This user is not assigned to any university', 404, nil)
      end

      @streamer = User.find(ActiveSupport::JSON.decode(params[:user][:streamer])["id"])
      unless @streamer
        error!('Streamer can not find', 404, nil)
      end

      @category = Category.find(ActiveSupport::JSON.decode(params[:user][:primaryCategory]))
      unless @category
        error!('Category can not find', 404, nil)
      end
    end

    def init_update
      @stream = Stream.find(ActiveSupport::JSON.decode(params[:user][:id]))
      unless @stream
        error!("There is no stream with this id #{ActiveSupport::JSON.decode(params[:user][:id])}", 404, nil)
      end

      @stream_request = StreamRequest.find_by_stream_id(@stream.id)
      unless @stream_request
        error!('There is no stream_request about this stream', 404, nil)
      end

      @university = current_api_admin_user.profession_university
      unless @university
        error!('This user is not assigned to any university', 404, nil)
      end
    end

    def get_location
      location = Location.where(place: ActiveSupport::JSON.decode(params[:user][:location]))
                         .where(university_id: @university.id)

      if location.empty?
        location = Location.new(location_params)
        location.save!
      else
        location = location.first
      end
      location.id
    end

    def set_temp_date_to_stream
      favorite_time_range_option = ActiveSupport::JSON.decode(params[:user][:availableTimes]).find { |t| t["isFavorite"] }

      unless favorite_time_range_option
        error!('There should be at least one favorite available time', 404, nil)
      end

      @stream.starts_at = Time.at(favorite_time_range_option["startTs"]).to_datetime
      @stream.ends_at = Time.at(favorite_time_range_option["endTs"]).to_datetime
    end

    def assign_time_ranges
      @stream_request.time_ranges.clear
      ActiveSupport::JSON.decode(params[:user][:availableTimes]).each do |time_range|
        start_ts = Time.at(time_range["startTs"]).to_datetime
        end_ts = Time.at(time_range["endTs"]).to_datetime

          @stream_request.create_time_ranges(start_ts, end_ts, time_range["isFavorite"])
      end
    end

    def assign_secondary_categories
      if ActiveSupport::JSON.decode(params[:user][:secondaryCategories]).present?
        secondary_categories = @stream.secondary_categories
        secondary_categories.destroy_all
        ActiveSupport::JSON.decode(params[:user][:secondaryCategories])&.each do |category|
          next unless Category.find(category["id"])

          SecondaryCategory.create(stream: @stream, category_id: category["id"])
        end
      end
    end
  end

and one model method

def create_time_ranges(start_hour, end_hour, is_favorite)
    time_range = TimeRange.new(start_hour: start_hour, end_hour: end_hour,
                               favorite: is_favorite, stream_request_id: id)
    time_range.save!
    time_ranges << time_range
  end

I ran each an every line of code in debugging and it did not gave me this error
This error occurs when the request got completed

@Bilal-Abbas-Gigalabs
Copy link
Author

I am just creating the stream along with a request whose code is listed and that is it.
Nothing else

@dblock
Copy link
Member

dblock commented Dec 15, 2020

I don't see anything wrong, but there's a lot going on. I would delete everything to start in the API body, make sure that works, then slowly re-add parts of the code to narrow it down.

@Bilal-Abbas-Gigalabs
Copy link
Author

Sure thank you
I will wait for that.

@dblock
Copy link
Member

dblock commented Dec 15, 2020

Sorry, I meant you should do that. I will wait to hear what you find.

@chrisedington
Copy link

chrisedington commented Jun 22, 2022

Weirdly enough, I have a model called Stream too and this is happening to me, sharing none of the above code. @Bilal-Abbas-Gigalabs did you manage to solve it? @dblock perhaps?

@n1sym
Copy link

n1sym commented Oct 17, 2022

Hi, I also encountered the same error.

In my case, it was because I had defined @stream in my code.

In such a situation,

I hope this helps. Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants