Comments (6)
From the docs https://api.rubyonrails.org/classes/ActiveRecord/Querying.html#method-i-find_by_sql
Executes a custom SQL query against your database and returns all the results. The results will be returned as an array, with the requested columns encapsulated as attributes of the model you call this method from.
select *
selects all the columns from the joined tables and makes them accessible via accessors on the User
. Its unfortunate that you have redefined that accessor method. So, either do a select with alias select *, foo as bar
or remove (or rename) that method from User
.
from rails.
Can you provide a reproduction test script using https://github.com/rails/rails/blob/main/guides/bug_report_templates/active_record.rb template?
from rails.
@fatkodima I ran the bug template. but I can’t reproduce the error.
# Running:
D, [2024-05-02T16:12:54.318104 #48134] DEBUG -- : User Load (0.3ms) SELECT*FROM users LEFT JOIN user_balances ON user_balances.user_id=users.id
.
Finished in 0.001494s, 669.3442 runs/s, 669.3442 assertions/s.
1 runs, 1 assertions, 0 failures, 0 errors, 0 skips
As you can see, It ran only one sql. => which is correct.
Then how come in my case, it ran all other sql queries.
User Load (4.2ms) SELECT*FROM users LEFT JOIN user_balances ON user_balances.user_id=users.id;
Client Load (0.7ms) SELECT `clients`.* FROM `clients` WHERE `clients`.`user_id` = 11 ORDER BY `clients`.`id` DESC LIMIT 1
Company Load (0.3ms) SELECT `companies`.* FROM `companies` WHERE `companies`.`user_id` = 11 LIMIT 1
UserBalance Load (0.2ms) SELECT `user_balances`.* FROM `user_balances` WHERE `user_balances`.`user_id` = 11 AND `user_balances`.`currency` = 'EUR' ORDER BY `user_balances`.`id` DESC LIMIT 1
Client Load (0.5ms) SELECT `clients`.* FROM `clients` WHERE `clients`.`user_id` = 1 ORDER BY `clients`.`id` DESC LIMIT 1
Client Load (0.4ms) SELECT `clients`.* FROM `clients` WHERE `clients`.`user_id` = 1 AND (currency = 'EUR') ORDER BY `clients`.`id` DESC LIMIT 1
ContactDetails Load (0.3ms) SELECT `contact_details`.* FROM `contact_details` WHERE `contact_details`.`user_id` = 1 AND `contact_details`.`contact_details_type` = 'personal' LIMIT 1
UserBalance Load (0.4ms) SELECT `user_balances`.* FROM `user_balances` WHERE `user_balances`.`user_id` = 1 AND `user_balances`.`currency` = 'EUR' ORDER BY `user_balances`.`id` DESC LIMIT 1
from rails.
I am confident that the problem is in the app itself, not in the rails. Try to ask on stackoverflow for the help.
So closing for now. If you will be able to provide a reproducible test script, we will reopen.
from rails.
@fatkodima Yes, you were right. But I would like to make some comment on here. So that next person can find the issue easily.
When you run,
User.find_by_sql("SELECT*FROM users LEFT JOIN user_balances ON user_balances.user_id=users.id;”)
find_by_sql with "JOIN" query, It will look up every column of the table in database. In my case, it's user
table and user_balances
table.
The Trick thing is, when you have method in your ActiveRecord class that has same name with db column.
My user_balances
table has something called "mambu_id" column.
and my User ActiveRecord Class has method name same as "mambu_id"
class User < ActiveRecord::Base
...
def mambu_id
# some logic here to call, another sql, and other methods..
end
...
end
I wanted call something like this.
User.find_by_sql("
SELECT
*
FROM
users
LEFT JOIN user_balances ON user_balances.user_id = users.id
WHERE
users.user_type = 'Lender' AND users.deleted_at IS NULL AND((user_balances.balance > 0)
OR
users.id IN(
SELECT DISTINCT savings.user_id FROM savings
LEFT JOIN investments ON investments.saving_id = savings.id
WHERE investments.status = 'completed' OR savings.status = 5)
)
ORDER BY
users.id;
")
But I can not. Because it will trigger the method on ActiveRecord class that has same name with db column of JOIN result.
Why should rails behave this way? when running 'find_by_sql' , is it better to just use column value ignoring method in the class? Obviously, User want to use RAW sql query. as name is "find_by_sql"
What do you think? @fatkodima
from rails.
Ok. thanks for the reply.
by the way. I was trying to write test case for you. I was not able to. Is there anything skip in MiniTest Framework?
# frozen_string_literal: true
require "bundler/inline"
gemfile(true) do
source "https://rubygems.org"
gem "rails"
# If you want to test against edge Rails replace the previous line with this:
# gem "rails", github: "rails/rails", branch: "main"
gem "sqlite3", "~> 1.4"
end
require "active_record"
require "minitest/autorun"
require "logger"
# This connection will do for database-independent bug reports.
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
ActiveRecord::Base.logger = Logger.new(STDOUT)
ActiveRecord::Schema[7.0].define(version: 2024_03_22_154820) do
create_table "users", id: :integer, charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "first_name"
t.string "last_name"
t.datetime "birthday", precision: nil
t.string "reset_password_token"
t.datetime "reset_password_sent_at", precision: nil
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at", precision: nil
t.datetime "last_sign_in_at", precision: nil
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at", precision: nil, null: false
t.datetime "updated_at", precision: nil, null: false
t.string "avatar"
t.string "confirmation_token"
t.boolean "is_confirmed", default: false
t.string "invite_loan"
t.integer "title", default: 0
t.string "confirmation_email"
t.string "user_type", null: false
t.string "user_subtype"
t.datetime "remember_created_at", precision: nil
t.string "business_name"
t.string "middle_name", limit: 300
t.string "currency", limit: 5
t.boolean "identity_checked"
t.boolean "from_invitation", default: false
t.integer "invited_by"
t.boolean "director", default: false
t.boolean "preferred", default: false
t.string "referral_id", limit: 32
t.datetime "confirmed_at", precision: nil
t.datetime "confirmation_sent_at", precision: nil
t.string "unconfirmed_email"
t.datetime "password_updated_at", precision: nil
t.datetime "deleted_at", precision: nil
t.datetime "balance_activated_at", precision: nil
t.datetime "personal_details_completed_at", precision: nil
t.integer "pension_trustee_id"
t.integer "company_role_id"
t.boolean "is_spv", default: false
t.string "heared_from", default: "other"
t.boolean "withdraw_once_per_month", default: true
t.integer "broker_id"
t.datetime "removal_requested_at", precision: nil
t.datetime "referral_activated_at", precision: nil
t.string "originator_id", default: "direct"
t.boolean "can_topup", default: true
t.boolean "mca_approved", default: false
t.boolean "secondary_market_approve", default: false
t.integer "failed_attempts", default: 0
t.string "unlock_token"
t.datetime "locked_at", precision: nil
t.boolean "deactivated", default: false
t.boolean "block_withdrawal", default: false
t.string "device_id"
t.string "registration_source"
t.string "status"
t.string "totp_secret_key"
t.text "device_token"
t.string "operating_system"
t.integer "otp_count"
t.datetime "otp_disabled_time", precision: nil
t.datetime "last_otp_validated_at", precision: nil
t.boolean "block_autoflend", default: false
end
create_table "user_balances", id: :integer, charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t|
t.string "currency"
t.string "mambu_id"
t.string "encoded_key"
t.integer "user_id"
t.datetime "created_at", precision: nil, null: false
t.datetime "updated_at", precision: nil, null: false
t.decimal "balance", precision: 15, scale: 4
end
end
## Active Model
class User < ActiveRecord::Base
def encoded_key
raise "error"
end
def mambu_id
raise "error"
end
def balance
raise "error"
end
end
class UserBalance < ActiveRecord::Base
end
## Test
class BugTest < Minitest::Test
def test_it
user1 = User.create!({
"email"=>"[email protected]",
"encrypted_password"=>"$2a$11$1jXOe2G2Z6vD5Xx3MQ9u2uTnaTzYGIM7T66uVmJf774BBftqwFWBO",
"first_name"=>"MCA-Investor",
"last_name"=>"Last",
"birthday"=>nil,
"reset_password_token"=>nil,
"reset_password_sent_at"=>nil,
"sign_in_count"=>2,
"current_sign_in_ip"=>"127.0.0.1",
"last_sign_in_ip"=>"127.0.0.1",
"avatar"=>nil,
"confirmation_token"=>nil,
"is_confirmed"=>false,
"invite_loan"=>nil,
"title"=>"mr",
"confirmation_email"=>nil,
"user_type"=>"Lender",
"user_subtype"=>"individual_lender",
"remember_created_at"=>nil,
"business_name"=>nil,
"middle_name"=>nil,
"currency"=>nil,
"identity_checked"=>true,
"from_invitation"=>false,
"invited_by"=>nil,
"director"=>false,
"preferred"=>false,
"referral_id"=>"FLEN11380L554",
"confirmed_at"=>nil,
"confirmation_sent_at"=>nil,
"unconfirmed_email"=>nil,
"deleted_at"=>nil,
"personal_details_completed_at"=>nil,
"pension_trustee_id"=>nil,
"company_role_id"=>nil,
"is_spv"=>false,
"heared_from"=>"other",
"withdraw_once_per_month"=>true,
"broker_id"=>nil,
"removal_requested_at"=>nil,
"originator_id"=>"admin_panel",
"can_topup"=>true,
"mca_approved"=>true,
"secondary_market_approve"=>false,
"failed_attempts"=>0,
"unlock_token"=>nil,
"locked_at"=>nil,
"deactivated"=>false,
"block_withdrawal"=>false,
"device_id"=>nil,
"registration_source"=>nil,
"status"=>nil,
"totp_secret_key"=>nil,
"device_token"=>nil,
"operating_system"=>nil,
"otp_count"=>nil,
"otp_disabled_time"=>nil,
"last_otp_validated_at"=>nil,
"block_autoflend"=>false
})
user_balance1 = UserBalance.create!({
"currency"=>"EUR",
"mambu_id"=>"BAL_JJNA253",
"encoded_key"=>"8a8587588b213a0f018b23cf5c330ab4",
"user_id"=>1,
"balance"=>0.8605e6
})
assert_raises(StandardError) do
# This should raise "error". but did not.
User.find_by_sql("SELECT*FROM users LEFT JOIN user_balances ON user_balances.user_id=users.id")
end
end
end
from rails.
Related Issues (20)
- Inconsistent documentation between ActiveRecord::RecordNotSaved and ActiveRecord::Persistence::ClassMethods#save!
- Prevent fork bombs in ActiveSupport::ForkTracker HOT 1
- Avoid Seed Data Execution in CI by Replacing `db:setup` with `db:test:prepare` HOT 3
- ActiveRecord time field issue with timezone HOT 4
- `test_render_mutate_string_literal` shows `inline template:1: warning: literal string will be frozen in the future` HOT 2
- ActionMailer deliver_later doesn't work in development (delivery_method = :file) HOT 2
- Form tokens are ignored when `csrf_meta_tags` is present HOT 5
- undefined method `accessor' for #<ActiveModel::Type::Value:0x0000563c30ebdd50> HOT 6
- Support built-in compressor for `ActiveSupport::Cache` HOT 2
- Scaffolding with namespace generates broken partial view links with tailwind HOT 2
- `ActiveSupport::LogSubscriber` example and code reloads HOT 10
- Attribute aliases don't resolve dynamically like normal attribute methods HOT 1
- Association with the same name as the demodularized model name is incorrectly inferred
- New `permanent_connection_checkout` does not seem to work as expected. HOT 4
- [Edge Guides]: Text in some code snippets not readable (low contrast) HOT 1
- Unexpected behavior when calling `Model.find_by_id` with `true` or `false` HOT 5
- Migration Guide needs to cover out-of-order migrations HOT 1
- Range of dates with infinite end are stored incorrectly in Postgres database HOT 4
- `config.assets.debug` has misleading documentation HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from rails.