I need to get calculcated field from database. In pgsql i do it, this way:
SELECT extra_function(field_name) AS calculated_field_name FROM table;
This moment in ROR i have done it this way:
default_scope do
select <<-SQL.squish
table_name.*,
extra_function(field_name) AS calculated_field_name
SQL
end
Ho to do it better way?
Ruby 3
Rails 7
PgSQL 14
Related
I'm trying to understand how to use the select method in queries to return custom columns.
I'm running Rails 5.2, database is postgresql.
m = Message.all.select("messages.*, CASE WHEN id > 30 THEN TRUE ELSE FALSE END AS above_30")
returns only the messages table with all its columns. How do I get the above_30 column, preferable eager loaded?
The above_30 is there, but Rails will not define an access for it because there is no column by that name in your schema.
You can define one yourself, or use m[:above_30] to access the "raw" attributes of the object as returned from the query.
I just updated from Rails 4.0.2 to Rails 4.1.2 and realized ActiveRecord includes have become unusably slow. What used to take just a view milliseconds now take almost 5 minutes.
I join two tables Item and Keyword over a join table with has_and_belongs_to_many in the model. I have almost 3000 items, 3000 keywords and 8000 join table entries.
Getting all items and including all keywords used to be very fast but now takes forever:
Item.includes(:keywords)
I compared the SQL of both 4.0.2 and 4.1.2 and Rails seems to not use an inner join query in Rails 4.1.2 anymore. Database response time is very fast, so this is not the issue.
SQL for Rails 4.0.2
Item Load (5.8ms) SELECT items.* FROM items
SQL (4.6ms) SELECT keywords.*, t0.item_id AS
ar_association_key_name FROM keywords INNER JOIN items_keywords
t0 ON keywords.id = t0.keyword_id WHERE t0.item_id IN
(<id1>, ...)
SQL for Rails 4.1.2
Item Load (3.7ms) SELECT items.* FROM items
HABTM_Keywords Load (2.8ms) SELECT items_keywords.* FROM
items_keywords WHERE items_keywords.item_id IN (<id1>, ...)
Keyword Load (0.6ms) SELECT keywords.* FROM keywords WHERE
keywords.id IN (<id1>, ...)
Is this a known issue? I can not find anything on this so I thought it's probably best to ask the community first before reporting a bug report.
For now I changed my Rails version back to 4.0.2.
Thanks Björn
This has been a bug in 4.1.2 and is solved here:
https://github.com/rails/rails/pull/15675
You can avoid the performance regression here by explicitly referencing the association:
Item.includes(:keywords).references(:keywords)
But the problem is Rails-wide, and while there's a fix in, it's not in any release yet so I've put it in an initializer for now.
For me this is still quite slow, but only about half as slow as without the fix.
module ActiveRecord
# FIXME: this is a fix pulled from https://github.com/rails/rails/pull/15675
# for a serious performance issue, look to remove it on the next Rails upgrade
module Associations::Builder
class HasAndBelongsToMany
def hash
object_id.hash
end
def ==(other)
equal?(other)
end
alias :eql? :==
end
end
module AttributeMethods
module PrimaryKey
def id
return unless self.class.primary_key
sync_with_transaction_state
read_attribute(self.class.primary_key)
end
end
end
end
I have a rather complex sql statement that is created on the fly. But the same problem exists for a simple query, so I use this one as an example.
I have a Feature model. I can call Feature.count --> 4
But if I try to get all Feature ids using ActiveRecord::Base.connection.execute("SELECT ID from features") the result is a OCI8::Cursor object. I do not know how to get the data out of it.
If I try ActiveRecord::Base.connection.execute("SELECT ID from features").fetch I get [1]. With xyz.fetch_hash I get {"ID" => 1}.
I would like to have all IDs.
I just switched from PostgreSQL to Oracle.
Using PostgreSQL, I got all data using ActiveRecord::Base.connection.execute("SELECT ID from features").to_a, but to_a does not exist using the activerecord-oracle_enhanced-adapter gem (*** NoMethodError Exception: undefined method 'to_a' for #<OCI8::Cursor:0x00000007028aa8>).
I am using Ruby 2.0 and Rails 4. The connection to the Oracle database is working, except my manually created statement.
I found a solution.
Old: ActiveRecord::Base.connection.execute("SELECT ID from features")
New: ActiveRecord::Base.connection.exec_query("SELECT ID from features").to_a
Maybe someone have the same problem.
I was wondering if there was any way in rails to return a new_attribute in a select as statement in rails.
For simplified example Books.select("'tuds' as new_attribute").first where new_attribute isn't in the DB, just returns a bunch of empty active record objects.
Seems like this should work, but I'm not having any luck. Any thoughts!?
Thanks!
-Mario
`
UPDATE: I'm a goof. I wasn't actually looking at the actual object and was just looking at the log in my console.
Works for me using Rails 3.2:
irb(main):001:0: User.select('full_name as whatever').first.whatever
User Load (0.5ms) SELECT id, full_name as whatever FROM `users` LIMIT 1
=> "Zap Brannigan"
Is this what you want to achieve?
I'm using ruby 1.9.2 and rails 3 with a postgresql 8.4 database.
I have the following piece of rails code.
#playersonline = Member.find(:all, :conditions => ["loggedIn = ?", true] )
And I get the following error when the line is encountered:
PGError: ERROR: column "loggedin" does not exist
Looking at the query it generates it shows the following:
SELECT "members".* FROM "members" WHERE (loggedIn = 't')
The loggedIn column does exist in my table, and it has a boolean data type.
Another thing that is odd, when I try to query just the loggedIn column via a sql browser I get the same error? i.e. select loggedIn from members
Thanks
Postgres is case-sensitive by default so loggedIn isn't the same as loggedin. Although you can override it, Rails convention is that variable name-parts are separates by an underscore.
I wouldn't recommend re-inventing the wheel. Go in and change the columnn name (and any other columns that follow your notation) you might have to logged_in. This will prevent you from encountering any more strange errors.