Jak mogę przekonwertować ten kod na raw sql i używać go w szynach? Ponieważ kiedy wdrażam ten kod w heroku, pojawia się błąd przekroczenia limitu czasu żądania. Myślę, że będzie to szybsze, jeśli użyję raw sql.
@payments = PaymentDetail.joins(:project).order('payment_details.created_at desc')
@payment_errors = PaymentError.joins(:project).order('payment_errors.created_at desc')
@all_payments = (@payments + @payment_errors)
sql
ruby-on-rails
Johnny Cash
źródło
źródło
Odpowiedzi:
Możesz to zrobić:
records_array
byłby wówczas wynikiem zapytania SQL w tablicy, którą można iterować.źródło
records_array
będą różnych typów dla różnych adapterów bazy danych. Jeśli używasz PG, będzie to instancjaPG::Result
, a nieArray
.values
tenPG::Result
obiekt, aby uzyskać tablicę wynikówActiveRecord::Base.connection.exec_query
bardziej, ponieważ zwracaActiveRecords::Result
obiekt, który ma przydatne metody, takie jak.columns
i.rows
dostęp do nagłówków i wartości. Szereg skrótów z.execute
może być kłopotliwy i dać mi zbędne wyniki, gdy uruchomiłem klauzulę SUM GROUP BY.Wiem, że to stare ... Ale miałem dzisiaj ten sam problem i znalazłem rozwiązanie:
Jeśli chcesz utworzyć instancję wyników:
Jeśli chcesz tylko skrótu wartości:
Obiekt wynikowy:
select_all
zwracaresult
obiekt. Możesz z tym robić magiczne rzeczy.Źródła:
źródło
#find_by_sql
jest dokładnie tym, czego chciałem, dziękuję bardzo.Możesz wykonać surowe zapytanie używając
ActiveRecord
. I zasugeruję, aby przejść do bloku SQLźródło
SELECT * FROM users WHERE users.id = #{ user.id }
Możesz wykonać bezpośredni SQL, aby mieć jedno zapytanie dla obu tabel. Podam przykład zdezynfekowanego zapytania, aby, mam nadzieję, powstrzymać ludzi przed wprowadzaniem zmiennych bezpośrednio do samego łańcucha (niebezpieczeństwo wstrzyknięcia SQL), nawet jeśli ten przykład nie określa potrzeby:
Edycja : jak powiedział Huy, prosty sposób jest
ActiveRecord::Base.connection.execute("...")
. Innym sposobem jestActiveRecord::Base.connection.exec_query('...').rows
. I możesz używać natywnych przygotowanych instrukcji, np. Jeśli używasz postgres, przygotowaną instrukcję można wykonać za pomocą raw_connection, przygotuj i exec_prepared zgodnie z opisem w https://stackoverflow.com/a/13806512/178651Możesz również umieszczać surowe fragmenty SQL w zapytaniach relacyjnych ActiveRecord: http://guides.rubyonrails.org/active_record_querying.html oraz w powiązaniach, zakresach itp. Prawdopodobnie możesz zbudować ten sam SQL za pomocą zapytań relacyjnych ActiveRecord i możesz robić fajne rzeczy z ARel, jak wspomina Ernie w http://erniemiller.org/2010/03/28/advanced-activerecord-3-queries-with-arel/ . I oczywiście są inne ORM, klejnoty itp.
Jeśli będzie to często używane, a dodanie indeksów nie spowoduje innych problemów z wydajnością / zasobami, rozważ dodanie indeksu w DB dla payment_details.created_at i for payment_errors.created_at.
Jeśli wiele rekordów, a nie wszystkie, muszą pojawić się na raz, rozważ użycie podziału na strony:
Jeśli chcesz dokonać paginacji, rozważ utworzenie w DB najpierw widoku o nazwie payment_records, który łączy tabele payment_details i payment_errors, a następnie przygotuj model widoku (który będzie tylko do odczytu). Niektóre bazy danych obsługują zmaterializowane widoki, co może być dobrym pomysłem na wydajność.
Weź również pod uwagę specyfikację sprzętu lub maszyny wirtualnej na serwerze Rails i serwerze DB, konfiguracji, przestrzeni dyskowej, szybkości / opóźnieniu sieci / itp., Bliskości itp. I rozważ umieszczenie DB na innym serwerze / maszynie wirtualnej niż aplikacja Rails, jeśli nie masz, itp. .
źródło
Chcę pracować z
exec_query
zActiveRecord
klasy, ponieważ zwraca mapowanie zapytania przekształcania obiektu, więc robi się bardzo praktyczne i wydajne iteracyjne z obiektami, gdy obiekt jest Raw SQL.Przykład:
i zwróć to pełne zapytanie:
Aby uzyskać tylko listę wartości
Aby uzyskać tylko kolumny pól
źródło
Możesz także mieszać surowy SQL z warunkami ActiveRecord, na przykład jeśli chcesz wywołać funkcję w stanie:
źródło