Returning a hash instead of array with ActiveRecord::Base.connection - ruby-on-rails

I have to use a query like this :
query = Enc.joins(:rec).group("enc.bottle").
select("enc.bottle as mode, count(rec.id) as numrec, sum(enc.value) as sumvalue")
That I use with :
#enc = ActiveRecord::Base.connection.select_all(query)
To get the data, I've to do #enc.rows.first[0] (it works)
But #enc.rows.first["mode"] doesn't work ! Because each row of #enc.rows contains array.. not a map with the name of each field.
Maybe select_all is a wrong method.
Does it exist another method to get the data with the name of field ?
Thank you
EDIT

If you can associate a model with the query, then there's no need for the generic select_all method. You can use find_by_sql like this:
Enc.find_by_sql(query).first.mode
# => testing
Note that you will no be able to see the aliases when inspecting the results, but they are there. Also, the convention is to use plural names for the tables. You might find it easier to just sticks with the defaults.

Related

Rails 4 update_all and set value from another field

I need to do some bulk updates in some models and set value of a field as value of another field.
Right now I can do that with raw sql like this:
ActiveRecord::Base.connection.execute("UPDATE `deleted_contents` SET `deleted_contents`.`original_id` = `deleted_contents`.`id` WHERE `deleted_contents`.`original_id` is NULL")
This is working fine, however I need to do this using ActiveRecord query interface due to many reasons.
I tried:
DeletedContent.where(original_id: nil).update_all(original_id: value_of_id_column)
For value_of_id_column I tried :id, self.id, id, etc, nothing works. What should I set for value_of_id_column to get the original query generated by rails? Is this possible, or using the raw sql is the only solution?
Also I do not want to iterate over each record and update. This is not a valid solution for me:
DeletedContent.where(original_id: nil).each do |deleted_content|
update_each_record
end
I'm pretty sure you cannot obtain that query by passing a hash to update_all.
The closest to what you want to obtain would be:
DeletedContent.where(original_id: nil).update_all("original_id = id")

How can you test if a certain value is in an instance variable in Ruby on Rails?

I need to test if an instance variable in my controller contains a specific value. I think .include? would be the way to do it but that doesn't seem to work.
My code looks something like this:
#names=Model.find_by_sql("select name from ...")
if #names.include?(params[:name])
...
end
The if statement somehow allways evaluates to true.
Thanks
Firstly, find_by_sql is not a good way to do. find_by_sql will return you an object of class Model. Whereas params[:name] is most likely a string. The following should work:
Model.find(:all, :conditions => 'specify conditions here').map(&:name).include?(params[:name])
The results of find_by_sql will be (from the docs):
an array with columns requested encapsulated as attributes of the model you call this method from.
You need to search within the results.

Rails: Getting column value from query

Seems like it should be able to look at a simple tutorial or find an aswer with a quick google, but I can't...
codes = PartnerCode.find_by_sql "SELECT * from partner_codes where product = 'SPANMEX' and isused = 'false' limit 1"
I want the column named code, I want just the value. Tried everything what that seems logical. Driving me nuts because everything I find shows an example without referencing the actual values returned
So what is the object returned? Array, hash, ActiveRecord? Thanks in advance.
For Rails 4+ (and a bit earlier I think), use pluck:
Partner.where(conditions).pluck :code
> ["code1", "code2", "code3"]
map is inefficient as it will select all columns first and also won't be able to optimise the query.
You need this one
Partner.where( conditions ).map(&:code)
is shorthand for
Partner.where( conditions ).map{|p| p.code}
PS
if you are often run into such case you will like this gem valium by ernie
it gives you pretty way to get values without instantiating activerecord object like
Partner.where( conditions ).value_of :code
UPDATED:
if you need access some attribute and after that update record
save instance first in some variable:
instance=Partner.where( conditions ).first
then you may access attributes like instance.code and update some attribute
instance.update_attribute || instance.update_attributes
check documentation at api.rubyonrails.org for details

How to get table column value?

I write follow code to get one record from the table webeehs:
webeehs_result = Webeeh.find(:all, :conditions=>["webeeh_project_id=#{project_id}"])
Then I want to get one column value from this record, how could I do?
For example, the column name is webeeh_date.
first of all, never EVER write code like that. Building your own conditions as pure strings can leave you vulnerable to SQL injection exploits. If you must do conditions, then do it like this:
:conditions => ["webeeh_project_id = ?", project_id]
if you have a Project model, you should rename the webeeh_project_id column from your Webeeh model into project_id and have an association in your Project model like has_many :webeehs
Then, you won't need to call that find anymore, just do a p = Project.find(id) and then p.webeehs will return the webeehs you need.
the result will be an array which you can iterate through. And to get your webeeh.webeeh_date member, just call it like this:
result.each do |webeeh|
date = webeeh.webeeh_date
end
webeehs_result = Webeeh.findwebeeh_dates
is enough to get all columnn values.
For a different method and performance issues check the following: http://www.stopdropandrew.com/2010/01/28/finding-ids-fast-with-active-record.html
webeeh_result will usually be an array of results for the database.
You can iterate throughit using
webeehs_result.each do |webeeh|
# use "webeeh.webeeh_date" to access the column_name or do whatever you want with it.
end

Unable to read values from object returned from ActiveRecord.find

I make the following call to the DB.
#patientRegistration = PatientRegistration.find(:all,
:conditions=>["name = '#{patientName}'"])
This searches for a patient registration based on a given name. I get a valid #patientRegistration object. When I invoke #patientRegistration.inspect it prints correctly all the values for the object in the DB.
But when I try to read a particular attribute (say id or name) by doing the following: #patientRegistration.id or #patientRegistration.name, I get invalid values. Either its blank or some junk values. I don't understand how inspect is able to retrieve all the values correctly but reading individual attributes gives invalid values.
Thanks
find(:all) returns an array of all the records that match the conditions (inspect probably shows you the result in square brackets). #patientRegistration.first.name will return you the name of the first record in the array. However, if you are only interested in the first or only record that matches the conditions, then you can use find(:first) instead:
#patientRegistration = PatientRegistration.find(:first,
:conditions => ["name = ?", patientName])
Note that I've also changed your condition to use a parameter so that it is no longer at risk from SQL injection attacks.
You can also re-write this code using an attribute-based finder:
#patientRegistration = PatientRegistration.find_by_name(patientName)
This will do a find(:first). For the equivalent of find(:all), use find_all_by instead of find_by.

Resources