How to have condition in ActiveRecord update - ruby-on-rails

I am trying to update a record. Am using the following code.
Proddiscount.update({:prodid => params[:id]}, {:discount=>params[:discount]})
Query Im trying to have is:
update proddiscount set discount = '' where prodid = ''

If prodif is not a primary key, use update_all (read more here)
Proddiscount.update_all("discount = #{params[:discount]}", ["prodid = ?", params[:prodid])
But it won't trigger validations.

How about doing this:
#prod = Proddiscount.find(:first, :conditions => {prodid => params[:id]})
#prod.update_attributes({:discount=>params[:discount]})

Related

how append an object to association relation in rails?

In a rails 4.1 application I need to add an object to an "AssociationRelation"
def index
employee = Employee.where(id_person: params[:id_person]).take
receipts_t = employee.receipts.where(:consent => true) #gives 3 results
receipts_n = employee.receipts.where(:consent => nil).limit(1) #gives 1 result
#I would need to add the null consent query result to the true consent results
#something similar to this and the result is still an association relation
#receipts = receipts_t + receipts_n
end
Is there a simple way to do this?
A way of solving this:
def index
employee_receipts = Employee.find_by(id_person: params[:id_person]).receipts
receipts_t = employee_receipts.where(consent: true)
receipts_n = employee_receipts.where(consent: nil).limit(1)
#receipts = Receipt.where(id: receipts_t.ids + receipts_n.ids)
end
Unfortunately .or() can't be used here because it's only available from Rails v5.0.0.1
you could do this way
receipts_t_ids = employee.receipts.where(:consent => true).pluck(:id)
receipts_n_ids = employee.receipts.where(:consent => nil).limit(1).pluck(:id)
#receipts = Receipt.where(id: receipts_t_ids + receipts_n_ids)
To avoid extra queries and keeping arrays in memory, you can use or
Like this:
def index
employee_receipts = Employee.find_by(id_person: params[:id_person]).receipts
#receipts =
employee_receipts.where(consent: true).or(
employee_receipts.where(consent: nil).limit(1)
)
end

Combine two ActiveRecord results and sort by a shared joined table attribute

I have a Convo table and a GroupMeeting table that both are associated with a Msg table.
I want to find all the instances where the current_user has convos or group_meetings with msgs, combine the two, and then show both together to the user in order of the last msg.created_at
Here I have defined both:
#convos = Convo.includes(:msgs).where("sender_id = ? OR recipient_id = ?", current_user, current_user).where.not(:msgs => { :id => nil }).merge(Msg.order(created_at: :desc))
#group_meetings = current_user.group_meetings.includes(:msgs).where.not(:msgs => { :id => nil }).merge(Msg.order(created_at: :desc))
And then combined them together:
#convos = #convos + #group_meetings
What I can't figure out is how to now sort them by msg.created_at
I have tried the following:
#convos = (#convos + #group_meetings).sort_by(&:"#{msg.created_at}")
#convos.order('msg.created_at DESC')
These all seem to be server-side sorting though. How can I sort these based off the join table, after the array has been created?
Please let me know if I need to supply any other details. Thank you!!
You can try the following:
(#convos + #group_meetings).sort_by { |item| item.msgs.minimum(:created_at) }

Rails update attribute table col1 with col2

I want to (mass)update a model. Each line of should be updated by replacing the val of attb 1 with the val of attr2
users = User.find_all_by_project_id(params[:project_id])
users.each do |d|
User.update_attribute attribute1 with attribute2
end
How is the best way?
Thanks for your input.
This is how you should do it so everything happens on the sql side.
User.update_all("attribute1 = attribute2", { project_id: params[:project_id] })
That should be done this way:
User.where(:project_id => params[:project_id]).update_all('col1 = col2')
or
User.update_all('col1 = col2', {:project_id => params['project_id'] })

In ActiveRecord, how to check if an object property is nil?

Suppose I need to check if a certain property is not set.
I imagine something like this but It doesn't work.
#users = User.find_all_by_role(["role = ?",nil])
I tried some other variants with no luck.
I guess this should be pretty straightforward.
Thank you!
Using ActiveRecord's pre-3.0 syntax:
#users = User.find(:all, :conditions => { :role => nil })
After 3.0 you can write:
#users = User.where(:role => nil)
Try: #users = User.find(:all, :conditions=>'role is null')
#users = User.where(:roles => nil).all
There's no need to break into SQL for this.

Adding a LIKE criteria to a Rails Conditions block

Consider the following code which is to be thrown at an AR find:
conditions = []
conditions[:age] = params[:age] if params[:age].present?
conditions[:gender] = params[:gender] if params[:gender].present?
I need to add another condition which is a LIKE criteria on a 'profile' attribute. How can I do this, as obviously a LIKE is usually done via an array, not a hash key.
You can scope your model with hash conditions, and then perform find on scope with array conditions:
YourModel.scoped(:conditions => conditions).all(:conditions => ["profile like ?", profile])
Follwing is ugly but it works
conditions = {} #This should be Hash
conditions[:age] = params[:age] if params[:age].present?
conditions[:gender] = params[:gender] if params[:gender].present?
conditions[:profile] = '%params[:profile]%' if params[:profile].present?
col_str ="" #this is our column names string for conditions array
col_str = "age=:age" if params[:age].present?
col_str+= (col_str.blank?)? "gender=:gender" :" AND gender=:gender" if params[:gender].present?
col_str += (col_str.blank?) 'profile like :profile' : ' AND profile like :profile' if params[:profile].present?
:conditions=>[col_str , conditions]
When you call your active record find, you send your conditions string first, then the hash with the values like :
:conditions => [ "age = :age AND gender = :gender AND profile LIKE :profile", conditions ]
that way you can keep doing what you are doing :)

Resources