Code Monkey home page Code Monkey logo

deep_pluck's Introduction

Hi there, I'm Rumble πŸ‘‹

Hi, I'm Rumble Huang, a full stack Ruby on Rails developer with back-end, front-end and server management skills. And also an indie game maker.

Skills and Tools

Khiav's github stats

deep_pluck's People

Contributors

berniechiu avatar jfarey avatar khiav223577 avatar klausbadelt avatar moon-moon-husky avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

deep_pluck's Issues

does'nt load translations

I have a class with translations
Questionnaire.deep_pluck(:title) returns

ActiveRecord::StatementInvalid (PG::UndefinedColumn: ERROR: column "title" does not exist)
title is translated field using globalise gem

Issue with STI and polymorphism

There seems to be an issue with selecting the appropriate type for use in a query when STI is involved.

class Parent
  ...
end
class Child
  has_one :information
end
class Information
 belongs_to :informationable, polymorphic: true
end

Attempting to use deep_pluck while create a query like the following:

> Child.deep_pluck(deep_information: [:id, :name])
...
SELECT informations.id, informations.name FROM "informations" WHERE ("informations"."informationable_type" = 'Child')

Comparatively, rails uses the parent of the STI for this query:

> Child.all.first.information 
...
SELECT informations.* FROM "informations" WHERE ("informations"."informationable_type" = 'Parent') AND ("informations"."informationable_id" = ...)

It seems like maybe this line needs to be addressed, but I'm not sure: https://github.com/khiav223577/deep_pluck/blob/master/lib/deep_pluck/model.rb#L120

Cannot deep_pluck HABTM association with different name not working when doing inverse lookup.

It appears when deep pluck attempts to figure out the association in reverse, it doesn't observer the correct association name. It seems to be using the class name rather than the association name (training_programs rather than borrower_training_programs).

begin
  require 'bundler/inline'
rescue LoadError => e
  warn 'Bundler version 1.10 or later is required. Please update your Bundler'
  raise e
end

gemfile(true) do
  source 'https://rubygems.org'
  gem 'deep_pluck', '~> 1.1.6'
  gem 'sqlite3'
end

require 'active_record'
require 'minitest/autorun'
require 'logger'

ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
ActiveRecord::Base.logger = Logger.new(STDOUT)

ActiveRecord::Schema.define do
  create_table 'training_programs', force: :cascade do |t|
    t.string :name
  end

  create_table 'training_providers', force: :cascade do |t|
    t.string :name
  end

  create_table 'training_programs_training_providers', id: false, force: :cascade do |t|
    t.bigint 'training_provider_id', null: false
    t.bigint 'training_program_id', null: false
  end
end

class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true
end

class TrainingProgram < ApplicationRecord
  has_and_belongs_to_many :training_provider,
    inverse_of: :borrower_training_programs,
    join_table: 'training_programs_training_providers'
end

class TrainingProvider < ApplicationRecord
  has_and_belongs_to_many :borrower_training_programs,
    class_name: 'TrainingProgram',
    inverse_of: :training_provider,
    join_table: 'training_programs_training_providers'
end

class BugTest < Minitest::Test
  def setup
    TrainingProgram.create!(
      name: 'tp', training_provider: [TrainingProvider.create!(name: 'as')]
    )
  end

  def teardown
    TrainingProvider.destroy_all
    TrainingProgram.destroy_all
  end

  def test_data
    assert_equal TrainingProgram.first.training_provider.first.name, 'as'
    assert_equal TrainingProvider.first.borrower_training_programs.first.name, 'tp'
  end

  def test_deep_pluck
    assert_equal TrainingProgram.deep_pluck(:name, training_provider: :name), [
      'name' => 'tp',
      training_provider: [
        'name' => 'as'
      ]
    ]
  end
end

HABTM STI parent and child referencing the same table

Possibly related to #46

deep_pluck uses the incorrect table name (uses the join table) for its query.

SQLite3::SQLException: no such column: training_programs_training_providers.training_program_id

begin
  require 'bundler/inline'
rescue LoadError => e
  warn 'Bundler version 1.10 or later is required. Please update your Bundler'
  raise e
end

gemfile(true) do
  source 'https://rubygems.org'
  gem 'deep_pluck', '~> 1.1.6'
  gem 'sqlite3'
end

require 'active_record'
require 'minitest/autorun'
require 'logger'

ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
ActiveRecord::Base.logger = Logger.new(STDOUT)

ActiveRecord::Schema.define do
  create_table 'training_programs', force: :cascade do |t|
    t.string :name
    t.integer :training_provider_id
  end

  create_table 'training_providers', force: :cascade do |t|
    t.string :name
    t.string :type
  end

  create_table 'training_programs_training_providers', id: false, force: :cascade do |t|
    t.bigint 'training_provider_id', null: false
    t.bigint 'training_program_id', null: false
  end
end

class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true
end

class TrainingProgram < ApplicationRecord
  belongs_to :training_provider
  has_and_belongs_to_many :borrower_apprenticeship_sponsors,
    class_name: 'ApprenticeshipSponsor',
    foreign_key: :training_program_id,
    association_foreign_key: :training_provider_id,
    inverse_of: :borrowed_training_programs,
    join_table: 'training_programs_training_providers'
end

class TrainingProvider < ApplicationRecord
  has_many :training_programs
end

class ApprenticeshipSponsor < TrainingProvider
  has_and_belongs_to_many :borrowed_training_programs,
    class_name: 'TrainingProgram',
    foreign_key: :training_provider_id,
    association_foreign_key: :training_program_id,
    inverse_of: :borrower_apprenticeship_sponsors,
    join_table: 'training_programs_training_providers'
end

class BugTest < Minitest::Test
  def setup
    TrainingProgram.create!(
      name: 'tp', borrower_apprenticeship_sponsors: [ApprenticeshipSponsor.create!(name: 'as')]
    )
  end

  def teardown
    ApprenticeshipSponsor.destroy_all
    TrainingProgram.destroy_all
  end

  def test_data
    assert_equal TrainingProgram.first.borrower_apprenticeship_sponsors.first.name, 'as'
  end

  def test_deep_pluck
    begin
      assert_equal TrainingProgram.deep_pluck(:name, borrower_apprenticeship_sponsors: :name), [
        'name' => 'tp',
        borrower_apprenticeship_sponsors: [
          'name' => 'as'
        ]
      ]
    rescue => e
      puts '-----'
      puts e
      puts '-----'
    end
  end
end

Support for Mongoid

Happy to see if we can support Mongoid in the future. Actually I can do it if I have some suggestions for the head start.

Support for rails 7.0.8

I upgraded rails version 7.0.4 to 7.0.8
When I try to use any model with deep_pluck, I get the following:

.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/activerecord-7.0.8/lib/active_record/result.rb:138:in column_type': wrong number of arguments (given 2, expected 3) (ArgumentError)`

Strange results when a model joins multiple tables

This might be a pluck_all issue ...

User.includes(:articles, :friends).deep_pluck(:name, { articles: :title, friends: :name })

This query shows some strange results.
Although I found that it happened when I updated the pluck_all version above 2.0.3 ( this patch might have some problems. ), I have no idea to fix this issue.
If you have some idea to fix it, please tell me.

has_and_belongs_to_many issue

I'm not sure if it's possible to do so, but I'm having an issue using deep_pluck with a has_and_belongs_to_many association.

Example data structure:

class County < ApplicationRecord
  has_and_belongs_to_many :zip_codes
end
class Zipcode < ApplicationRecord
  has_and_belongs_to_many :counties
end

When I try to use deep_pluck on this association I get the following:

[2] pry(main)> County.limit(2).deep_pluck(zipcodes: :city)
   (1.2ms)  SELECT counties.id FROM "counties" LIMIT 2
   (4.3ms)  SELECT counties_zipcodes.county_id, "zipcodes"."city" FROM "zipcodes" WHERE "counties_zipcodes"."county_id" IN (178, 179)
ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR:  missing FROM-clause entry for table "counties_zipcodes"
LINE 1: SELECT counties_zipcodes.county_id, "zipcodes"."city" FROM "...

So it appears to be using the correct joins table for the SELECT and WHERE, but not the FROM.

Rails 6.1 `map!` deprecation warning

DEPRECATION WARNING: map! is deprecated and will be removed from Rails 6.2 (use map instead) under Rails 6.1 when using #deep_pluck. The issue is fixed in this PR for pluck_all - can you merge there? Happy to provide a PR here once a new version of pluck_all is published.

Eager load support

Can there be a patch to support eager loading via .includes and .references so that N+1 conditions don't occur as long as the data was eager loaded?

Could this be used with GraphQL?

GraphQL generally works in a way that you can query exactly the fields (columns) that you want from the database like this:

{
  users {
    name
    posts {
      title
    }
  }
}

There's a very popular GraphQL gem for ruby: https://github.com/rmosolgo/graphql-ruby

Currently, the best solution that I've sees is using batch querying. It would looks something like this in reality:

users = User.all
posts = Post.find(user_id: users.map(&:id))

Perhaps this could be optimized using deep_pluck?
It would already be a huge improvement if it could pluck only requested fields:

users = User.pluck(:id, :name)
posts = Post.where(user_id: users.map(&:id)).pluck(:title)

Note that we also need to fetch user.id even though that's not in the query.

Any ideas how this could be achieved?
Could this be something that could be done on the graphql-ruby gem perhaps?

Does not handle polymorphic associations correctly

Great gem, thank you for sharing! Very convenient when you need to build classes composed of data from a whole bunch of tables, and using models is too slow.

It does not handle polymorphic associations correctly; the '*_type' column is ignored, so you may get the wrong data in situations where two different parent models share the same id.

For example:

class Child < ApplicationRecord
  belongs_to :parent, polymorphic: true
end

class One < ApplicationRecord
  has_one :child, as: :parent
end

class Two < ApplicationRecord
  has_one :child, as: :parent
end

One.create(id: 1, child: Child.new)
Two.create(id: 1, child: Child.new)

Two.all.deep_pluck(child: [:id]) == One.all.deep_pluck(child: [:id]) # Should not be true!

I will try and figure out a PR.

Don't add association name as key to returned json

Is there a way to flatten the response of deep_pluck to not add the name of an association as key?
(Please see current and wanted outcome examples below)

I have something like 'flat_deep_pluck' in my mind but what I basically want to achieve:

Associations

# Vehicle.rb
has_many :logbooks
has_many :sessions, through: :logbooks

# Session.rb
belongs_to :logbook
has_one :vehicle, through: :logbook

# Logbook.rb
belongs_to :vehicle
has_many :sessions

Query

Session.deep_pluck(:name, 'vehicles' => :manufacturer)

Current outcome

{
  "name": "Session_01",
  "logbook": {
    "vehicle": {
      "manufacturer": "BMW"
    }
  }
}

What I would like to get as outcome

{
  "name": "Session_01",
  "vehicle": {
    "manufacturer": "BMW"
  }
}

need serializer support

可否支援 deep_pluck ε‡Ί model θ£‘ι’εΊεˆ—εŒ–ηš„ζ¬„δ½οΌŸ

e.g
class User < ActiveRecord::Base
  serialize :preferences, Hash
end

# in controller

User.where(id: 1).deep_pluck(preferences: [:food, :car])

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.