okuramasafumi / alba

Alba is a JSON serializer for Ruby, JRuby and TruffleRuby.
https://okuramasafumi.github.io/alba/
MIT License
934 stars 43 forks source link

Conditional Associations in Alba Trigger SQL Queries Even When Conditions are False #377

Closed bbasanta238 closed 2 months ago

bbasanta238 commented 3 months ago

Describe the bug

When serializing a user object with conditional associations using Alba, SQL queries are executed for associations even when the condition for including those associations is set to false.

To Reproduce

Steps to reproduce the behavior:

  1. Define a User model with associations like Post.
  2. Define serializers for User, and Post.
  3. Fetch a user object with params to exclude association.
class User < ApplicationRecord
  has_many :posts
end

class UserResource
  include Alba::Resource

  attributes :uid, :email

  many :posts, resource: PostResource, if: proc { |_user, _params| params[:include_posts] }
end

class PostResource
  include Alba::Resource

  attributes :uid, :detail
end

UserResource.new(user, params: {  include_posts: false }).to_json

Expected behavior

SQL queries for associations should not be executed when the condition for including those associations is set to false.

Actual behavior

SQL queries for associations are executed regardless of the conditional inclusion settings.

Environment

okuramasafumi commented 3 months ago

Thank you for reporting! This seems a bug, I'll investigate it.

okuramasafumi commented 3 months ago

@bbasanta238 OK, so the quick fix is to remove the second parameter of the block. As described in https://github.com/okuramasafumi/alba/blob/main/README.md#conditional-attributes, the second parameter is for the attribute, in this case, posts. After removing it, Alba understands the attribute is not necessary.

You can access params in the block without parameters.

okuramasafumi commented 3 months ago

I added more detailed explanation to README: https://github.com/okuramasafumi/alba?tab=readme-ov-file#caution-for-the-second-parameter-in-if-proc

bbasanta238 commented 3 months ago

@okuramasafumi Thank you. Removing the second parameter works as expected. But suppose i need only uid and email attribute but it is executing query to select all data.

SELECT `users`.* FROM `users` ORDER BY `users`.`id` ASC LIMIT 1

Is it supposed to be like that or it can be optimized? And what about eager loading?

okuramasafumi commented 3 months ago

@bbasanta238 First of all, ActiveRecord queries all columns by default. Also, Alba is not designed specifically for Rails/ActiveRecord, and it's not planned to add such optimizations to Alba. You can do it by yourself outside of Alba, for example:

users = User.select(:uid, :email)
UserSerializer.new(users).serialize
okuramasafumi commented 2 months ago

I'm closing it now since I believe it's resolved.