Question

I'm trying a couple things to find conversations where not all messages have been deleted and now the kaminari page method is not working. Could it be that conversations is a hash and the delete_if method changes the hash in an unexpected way? The page method works when used directly with @mailbox.conversations.page(params[:page_1]).per(9) so it must be the delete_if block that is making it not work.

Here's my action:

def index  
    @conversations = @mailbox.conversations.delete_if do |c|
        receipts = c.receipts_for @master
        (receipts.where(deleted: true).count == receipts.count)  
    end
    @conversations = @conversations.page(params[:page_1]).per(9)
end

I've also used .find_each instead of delete_if.

Here's the error I'm getting on my view

NoMethodError (undefined method `page' for #):
Was it helpful?

Solution

Params

Firstly, are you sure you're meaning to be using params[:page_1] - if you're sending ?page=x, it will just be params[:page]


Method

Secondly, your undefined method error is because you're not calling a valid ActiveRecord object:

def index  
    @conversations = @mailbox.conversations.delete_if do |c|
        receipts = c.receipts_for @master
        (receipts.where(deleted: true).count == receipts.count)  
    end
    @conversations = @conversations.page(params[:page_1]).per(9)
end

What's @conversations?

Kaminari & Will_Paginate both override the SQL query you'll make from your Controller / Model. This means you have to call their page & per methods on ActiveRecord calls:

As per the documentation:

Everything is method chainable with less “Hasheritis”. You know, that's the Rails 3 way. No special collection class or anything for the paginated values, instead using a general AR::Relation instance. So, of course you can chain any other conditions before or after the paginator scope

I believe you'd be better doing something like this:

def index  
    @mailbox.conversations.each do |c|
        receipts = c.receipts_for @master
        c.destroy if (receipts.where(deleted: true).count == receipts.count)  
    end
    @conversations = @mailbox.conversations.page(params[:page]).per(9)
end

Update

If you don't want to destroy your items, you could use an ActiveRecord association extension like this:

#app/controllers/your_controller.rb
def index  
    @conversations = @mailbox.conversations.receipts.page(params[:page]).per(9)
end

#app/models/model.rb
Class Model < ActiveRecord::Base
    has_many :conversations do

        def receipts
            receipts = joins(:receipts_for).select("COUNT(*)")
            proxy_association.target.delete_if do
                receipts.where(deleted: true) == receipts
            end
        end

    end
end

This will need tweaking, but hopefully will give you some ideas as to what you can do

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top