Skip to content

Kaminari pagination is not supported by Tapioca #1859

Open
@lavoiesl

Description

Trying to update tapioca from 0.12.0 to 0.13.1 results in this error:

path/to/file.rb:32: Method page does not exist on Model::PrivateAssociationRelation https://srb.help/7003
    32 |    @records = Model.all.page(params[:page]).per(25)

Investigation

The page method is defined on the class by kaminari:
https://github.com/kaminari/kaminari/blob/9182d065c144afa45c6b7cf444f810bea1fd7201/kaminari-activerecord/lib/kaminari/activerecord/active_record_model_extension.rb#L14-L23

But attempting to introspect it at runtime yields nothing:

pry(main)> Model.all.method(:page)
=> #<Method: Model::ActiveRecord_Relation#page(*)>
pry(main)> Model.all.method(:page).source_location
=> nil
pry(main)> Model.all.method(:page).owner
=> Model::ActiveRecord_Relation
pry(main)> Model.all.method(:page).owner.instance_method(:page)
NameError: undefined method `page' for class `ActiveRecord::Relation'
from (pry):1:in `instance_method'from (pry):35:in `method'
pry(main)> Model.all.methods.include?(:page)
=> false

This is because it is delegated by https://github.com/rails/rails/blob/d37c533139f70efdcd95f8dadd48c10eba429f94/activerecord/lib/active_record/relation/delegation.rb#L71-L88

Which is generated on demand when the method is missing:
https://github.com/rails/rails/blob/d37c533139f70efdcd95f8dadd48c10eba429f94/activerecord/lib/active_record/relation/delegation.rb#L115-L124

Attempting the same as above after calling the method once does yield something a bit more interesting:

pry(main)> Model.all.method(:page)
=> #<Method: Model::ActiveRecord_Relation(Model::GeneratedRelationMethods)#page(...) /Users/seb/.gem/ruby/3.2.2/gems/activerecord-7.1.3.2/lib/active_record/relation/delegation.rb:78>
pry(main)> Model.all.method(:page).source_location
=> ["/Users/seb/.gem/ruby/3.2.2/gems/activerecord-7.1.3.2/lib/active_record/relation/delegation.rb", 78]
pry(main)> Model.all.method(:page).owner
=> Model::GeneratedRelationMethods
pry(main)> Model.all.method(:page).owner.instance_method(:page)
=> #<UnboundMethod: Model::GeneratedRelationMethods#page(...) /Users/seb/.gem/ruby/3.2.2/gems/activerecord-7.1.3.2/lib/active_record/relation/delegation.rb:78>
pry(main)> Model.all.methods.include?(:page)
=> true

The same can be achieved by calling Model.generate_relation_method(:page)

Workaround

Adding this in config/initializers/kaminari.rb makes tapioca generate the methods:

if defined?(Tapioca)
  Rails.application.config.after_initialize do
    Rails.application.eager_load!

    ActiveRecord::Base.descendants.each do |model|
      model.generate_relation_method(:page)
      model.generate_relation_method(:per)
    end
  end
end

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions