In rails we have Model.find(id_number) request. What I want to ask is there any possibility to create straight request to DB, for example: SELECT * FROM users WHERE id = 1 and replace rails basic Model.where(id: 1)?
EDIT
In my model.rb I have:
scope :search_import, -> {includes(:translations)}
default_scope -> {self.search_import}
And request (in rails console) looks like:
User Load (0.5ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
User::Translation Load (0.6ms) SELECT `users_translations`.* FROM `users_translations` WHERE `users_translations`.`category_id` IN (1)
But I don't want to User::Translation was executed (with unscoped I have the same result)
Sure, something like
ActiveRecord::Base.connection.execute("SELECT * FROM users WHERE id = 1")
I have a rails-api application in which users can follow other users.
To check if an user already follows another user, I need to include a query in the attributes and because of that, I have always a N+1 query problem.
Here is my code:
Index action in user controller:
def index
#users = ::User.all.paginate(page: params[:page])
end
The followers will always be included by a default_scope in the User model.
index.json.jbuilder:
json.partial! 'attributes', collection: #users, as: :user
_attributes.json.jbuilder:
json.extract! user, :id, :firstname, :lastname, :username, :follower_count
is_follower = user.follower.find_by(id: current_user.id).present? if current_user
json.following is_follower
And as a result:
User Load (0.1ms) SELECT "users".* FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."follower_id" WHERE "relationships"."followed_id" = $1 [["followed_id", 14]]
Rendered v1/user/users/_attributes.json.jbuilder (1.3ms)
User Load (0.1ms) SELECT "users".* FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."follower_id" WHERE "relationships"."followed_id" = $1 [["followed_id", 9]]
Rendered v1/user/users/_attributes.json.jbuilder (1.4ms)
User Load (0.1ms) SELECT "users".* FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."follower_id" WHERE "relationships"."followed_id" = $1 [["followed_id", 13]]
Is there some workaround or is it somehow possible to generate a dynamic attribute in the SQL query which includes the boolean value if the user follows the other user?
Thank you very much in advance.
My first thought would be to eager load the followers using the .includes method when you get the list of users like this #users = ::User.all.includes(:followers).paginate(page: params[:page]). But perhaps, I'm not understanding your question correctly? Let me know if that works or if I should focus my answer on a different subject. Thanks!
EDIT: Correct answer from the comments below:
Perhaps you can try user.followers.include?(current_user) to make use of the pre-loaded followers association.
I have set up a Rails REST Service and I am having a problem showing a single record. Here is the URL that I am trying to hit:
http://website:3000/users/2/timesheets/21
Controller code:
def show
puts "SHOW"
puts params.inspect
#timesheets = User.find(params[:user_id]).timesheets(params[:id])
respond_to do |format|
format.json { render json: #timesheets }
end
end
I know the params are getting to the controller, but it is not using the :timesheet_id. Here is the console output to show what I mean:
Started GET "/users/2/timesheets/21" for **.**.***.** at 2013-03-19 06:12:11 -0400
Processing by TimesheetsController#show as */*
Parameters: {"user_id"=>"2", "id"=>"21"}
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", "2"]]
Timesheet Load (0.5ms) SELECT "timesheets".* FROM "timesheets" WHERE "timesheets"."user_id" = 2
Completed 200 OK in 120ms (Views: 36.5ms | ActiveRecord: 2.9ms)
I see the timesheet id of 21 in the parameters hash. A query is then made to get the user, but then all of the timesheets for that user are grabbed. Any help would be appreciated. Thanks.
What Prakash suggests works, but executes two queries: one to get the user and one the get the timesheet. There does not seem to be any reason to do User.find(...) first. Might as well query the timesheets table only, which will only execute one query and is thus faster:
#timesheet = Timesheet.where('user_id = ? and id = ?', params[:user_id], params[:id]).first
Try this:
#user = User.find(params[:user_id])
#timesheet = #user.timesheets.find(params[:id])
This should run a query as follows:
SELECT "timesheets".* FROM "timesheets" WHERE "timesheets"."id" = 21 AND ("timesheets"."user_id" = 2) LIMIT 1
The corresponding view should be referring to #timesheet variable and not #timesheets.
I'm using rails_admin to email all users when a button is clicked. The action is called twice instead of once.
lib/rails_admin_email_everyone.rb:
require 'rails_admin/config/actions'
require 'rails_admin/config/actions/base'
module RailsAdmin
module Config
module Actions
class EmailEveryone < RailsAdmin::Config::Actions::Base
register_instance_option :visible? do
authorized?
end
register_instance_option :link_icon do
'icon-envelope'
end
register_instance_option :collection? do
true
end
register_instance_option :member? do
false
end
register_instance_option :controller do
Proc.new do
#topics_with_owners = Topic.where('user_id IS NOT NULL')
#topics_with_owners.each do |topic|
#reminder = Reminder.new(:topic_id=> topic.id,
:to_user_id => student.id, :from_user_id => current_user.id)
if #reminder.save
TopicMailer.reminder(#reminder.topic).deliver
#reminder.update_attribute(:sent, true)
else
logger.error "Error sending email reminder: "
+ #reminder.errors.full_messages.map {|msg| msg}.join(',')
end
end
flash[:success] = "Reminders successfully sent."
redirect_to back_or_index
end
end
end
end
end
end
config/initializers/rails_admin.rb:
require Rails.root.join('lib', 'rails_admin_email_everyone.rb')
RailsAdmin.config do |config|
config.authenticate_with do
redirect_to(main_app.root_path, flash:
{warning: "You must be signed-in as an administrator to access that page"})
unless signed_in? && current_user.admin?
end
module RailsAdmin
module Config
module Actions
class EmailEveryone < RailsAdmin::Config::Actions::Base
RailsAdmin::Config::Actions.register(self)
end
end
end
end
config.actions do
# root actions
dashboard # mandator y
# collection actions
index # mandatory
new
export
history_index
bulk_delete
# member actions
show
edit
delete
history_show
show_in_app
email_everyone do
visible do
bindings[:abstract_model].model.to_s == "Reminder"
end
end
end
end
When I examine my log I see it executes twice, but with slightly different parameters. One including pjax. I found this stackoverflow question relating a similar issue to the pjax timeout:
Started GET "/admin/reminder/email_everyone?_pjax=%5Bdata-pjax-container%5D" for 127.0.0.1 at 2012-12-01 20:28:12 -0900
Processing by RailsAdmin::MainController#email_everyone as HTML
Parameters: {"_pjax"=>"[data-pjax-container]", "model_name"=>"reminder"}
User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
Topic Load (1.3ms) SELECT "topics".* FROM "topics" WHERE (user_id IS NOT NULL)
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
(0.2ms) BEGIN
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
Topic Load (0.5ms) SELECT "topics".* FROM "topics" WHERE "topics"."id" = 4398 LIMIT 1
SQL (6.5ms) INSERT INTO "reminders" ("created_at", "from_user_id", "sent", "topic_id", "to_user_id", "updated_at") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id" [["created_at", Sun, 02 Dec 2012 05:28:12 UTC +00:00], ["from_user_id", 1], ["sent", false], ["topic_id", 4398], ["to_user_id", 1], ["updated_at", Sun, 02 Dec 2012 05:28:12 UTC +00:00]]
(1.1ms) COMMIT
User Load (0.6ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
Rendered topic_mailer/reminder.text.erb (375.8ms)
Started GET "/admin/reminder/email_everyone" for 127.0.0.1 at 2012-12-01 20:28:14 -0900
Processing by RailsAdmin::MainController#email_everyone as HTML
Parameters: {"model_name"=>"reminder"}
User Load (0.8ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
Topic Load (1.1ms) SELECT "topics".* FROM "topics" WHERE (user_id IS NOT NULL)
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
(0.2ms) BEGIN
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
Topic Load (0.5ms) SELECT "topics".* FROM "topics" WHERE "topics"."id" = 4398 LIMIT 1
SQL (7.1ms) INSERT INTO "reminders" ("created_at", "from_user_id", "sent", "topic_id", "to_user_id", "updated_at") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id" [["created_at", Sun, 02 Dec 2012 05:28:14 UTC +00:00], ["from_user_id", 1], ["sent", false], ["topic_id", 4398], ["to_user_id", 1], ["updated_at", Sun, 02 Dec 2012 05:28:14 UTC +00:00]]
(1.0ms) COMMIT
User Load (0.7ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
Rendered topic_mailer/reminder.text.erb (368.9ms)
I found the same issue,
I just added following code into lib/rails_admin_custom_action.rb
i.e Added pjax? option to false
module RailsAdmin
module Config
module Actions
class EmailEveryone < RailsAdmin::Config::Actions::Base
register_instance_option :pjax? do
false
end
end
end
end
end
may this will help you..
There's a pull request marked as good to merge that creates a pjax option for rails_admin. Unfortunately, it requires tests and there hasn't been any action for 3 months:
https://github.com/sferik/rails_admin/pull/1295
I have two models
class User
has_one :entry
end
class Entry
belongs_to: user
end
in my controller I use find_each to iterate over entries to email each of the users.
Entry.find_each(:include => :user, :conditions => {:approved => true}) do |entry|
UserMailer.send_competition_open_email(entry, entry.user)
end
entry.user is always nil. ":include => :user" never finds the user.
yet i can see in my SQL logs it tries to get it. But fails. Any ideas?
Entry Load (0.6ms) SELECT `entries`.* FROM `entries` WHERE `entries`.`approved` = 1 AND (`entries`.`id` >= 0) ORDER BY `entries`.`id` ASC LIMIT 1000
User Load (1.4ms) SELECT `users`.* FROM `users` WHERE (`users`.`id` IN (1,2,3))
User Load (0.4ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
class Entry
belongs_to: user
end
Just a quick check that you noticed the colon is butting "belongs_to" and not "user"?