diff --git a/lib/rasti/db/relations/many_to_many.rb b/lib/rasti/db/relations/many_to_many.rb index 0f806d5..8c011ed 100644 --- a/lib/rasti/db/relations/many_to_many.rb +++ b/lib/rasti/db/relations/many_to_many.rb @@ -29,12 +29,15 @@ def fetch_graph(environment, rows, selected_attributes=nil, excluded_attributes= if target_collection_class.data_source_name == relation_data_source_name target_data_source = environment.data_source_of target_collection_class - join_rows = target_data_source.db.from(qualified_target_collection_name(environment)) - .join(qualified_relation_collection_name(environment), target_foreign_key => target_collection_class.primary_key) - .where(Sequel[relation_collection_name][source_foreign_key] => pks) - .select_all(target_collection_class.collection_name) - .select_append(Sequel[relation_collection_name][source_foreign_key].as(:source_foreign_key)) - .all + dataset = target_data_source.db.from(qualified_target_collection_name(environment)) + .join(qualified_relation_collection_name(environment), target_foreign_key => target_collection_class.primary_key) + .where(Sequel[relation_collection_name][source_foreign_key] => pks) + .select_all(target_collection_class.collection_name) + + selected_attributes ||= target_collection_class.collection_attributes - excluded_attributes if excluded_attributes + dataset = dataset.select(*selected_attributes.map { |a| Sequel[target_collection_class.collection_name][a] }) if selected_attributes + + join_rows = dataset.select_append(Sequel[relation_collection_name][source_foreign_key].as(:source_foreign_key)).all else relation_data_source = environment.data_source relation_data_source_name @@ -42,9 +45,11 @@ def fetch_graph(environment, rows, selected_attributes=nil, excluded_attributes= .where(source_foreign_key => pks) .select_hash_groups(target_foreign_key, source_foreign_key) - target_collection = target_collection_class.new environment + query = target_collection_class.new environment + query = query.exclude_attributes(*excluded_attributes) if excluded_attributes + query = query.select_attributes(*selected_attributes) if selected_attributes - join_rows = target_collection.where(target_collection_class.primary_key => relation_index.keys).raw.flat_map do |row| + join_rows = query.where(target_collection_class.primary_key => relation_index.keys).raw.flat_map do |row| relation_index[row[target_collection_class.primary_key]].map do |source_primary_key| row.merge(source_foreign_key: source_primary_key) end diff --git a/spec/query_spec.rb b/spec/query_spec.rb index 534d492..995ae23 100644 --- a/spec/query_spec.rb +++ b/spec/query_spec.rb @@ -76,29 +76,51 @@ end it 'Select graph attributes' do - person = Person.new db[:people].where(document_number: 'document_2').select(:first_name, :last_name, :user_id).first + language = Language.new custom_db[:languages].where(id: 1).select(:id).first + + person = Person.new db[:people].where(document_number: 'document_2').select(:document_number, :user_id).first.merge(languages: [language]) user = User.new db[:users].where(id: 2).select(:id).first.merge(person: person) - post = Post.new db[:posts].where(id: 1).first.merge(user: user) + categories = db[:categories].where(id: [1,2]).select(:id).map { |c| Category.new c } + + post = Post.new db[:posts].where(id: 1).first.merge(user: user, categories: categories) + + selected_attributes = { + user: [:id], + 'user.person' => [:document_number, :user_id], + 'user.person.languages' => [:id], + categories: [:id] + } posts_query.where(id: 1) - .graph('user.person') - .select_graph_attributes(user: [:id], 'user.person' => [:first_name, :last_name, :user_id]) + .graph(*selected_attributes.keys) + .select_graph_attributes(selected_attributes) .all .must_equal [post] end it 'Exclude graph attributes' do - person = Person.new db[:people].where(document_number: 'document_2').select(:document_number, :last_name, :user_id).first + language = Language.new custom_db[:languages].where(id: 1).select(:id).first + + person = Person.new db[:people].where(document_number: 'document_2').select(:document_number, :user_id).first.merge(languages: [language]) user = User.new db[:users].where(id: 2).select(:id).first.merge(person: person) - post = Post.new db[:posts].where(id: 1).first.merge(user: user) + categories = db[:categories].where(id: [1,2]).select(:id).map { |c| Category.new c } + + post = Post.new db[:posts].where(id: 1).first.merge(user: user, categories: categories) + + excluded_attributes = { + user: [:name], + 'user.person' => [:first_name, :last_name, :birth_date], + 'user.person.languages' => [:name], + categories: [:name] + } posts_query.where(id: 1) - .graph('user.person') - .exclude_graph_attributes(user: [:name], 'user.person' => [:first_name, :birth_date]) + .graph(*excluded_attributes.keys) + .exclude_graph_attributes(excluded_attributes) .all .must_equal [post] end