leikind / wice_grid

A Rails grid plugin to create grids with sorting, pagination, and (automatically generated) filters
MIT License
537 stars 213 forks source link

Cannot include a Model from another database in the same server ( Ver.3.4.9) #172

Open fibers opened 10 years ago

fibers commented 10 years ago

Example. Using self.establish_connection to specify the belonging database. Model 'User' from database A, Model 'UserReport' from database B

if we initialize the grid like this :

@user_reports_grid = initialize_grid(
        UserReport,
        include: [:user]
)

When in version 3.4.4 , this would create the following sql plans.

 SELECT COUNT(*) FROM `user_reports` 
  UserReport Load (0.3ms)  SELECT  `user_reports`.* FROM `user_reports` LIMIT 100 OFFSET 0
  AuthUser Load (0.4ms)  SELECT `auth_user`.* FROM `auth_user`  WHERE `auth_user`.`id` IN (3, 25)

It won't cause any problems cause it query the database by a sequence sqls step by step. Each sql will use rails native method, so the application know which database the sql should be sent to.

But when in version 3.4.9, the wice_grid will generate the sql with 'JOIN' clause.

SELECT COUNT(DISTINCT `user_reports`.`id`) 
FROM `user_reports` LEFT OUTER JOIN `auth_user` ON `auth_user`.`id` = `user_reports`.`user_id` 
LEFT OUTER JOIN `auth_user` `reporters_user_reports` ON `reporters_user_reports`.`id` = `user_reports`.`reporter_id` 

In this case , the application will be confused.

leikind commented 10 years ago

Very interesting.

Before Rails 4 and ActiveRelation's references method the logic of includes was as follows:

You used the first case to run the query for two different databases, which is kind of amazing :) I don't think that AR authors could ever imagine such usage :)

In Rails 4 this automagical recognition of whether there are conditions for that table or not has been dropped in favor of references, which is an explicit way of saying "I want this association to be joined in one SQL query and there will be conditions on that table".

The effectively broke WiceGrid in Rails 4 in those cases when there are filters for the columns from that associated table. Apparently this is not your case because you only used includes to preinitialize all associated ActoveRecord, and not for filters.

I needed to start using references, and because the whole point of WiceGrid is to run one big query, I retained the Rails 3 behavior of includes by running references inside of the plugin for every association in includes. In my mind this was a bugfix, hence a minor version was incremented, but it broke your usage of includes.

This all leads me to believe that I should follow the semantics of ActiveRelation and introduce references explicitly in the API. Then the plugin will work again for your two databases.