Repeating code, bad practice - ruby-on-rails

I have this piece of code
#liked_tweet = LikedTweet.new
#liked_tweet = #liked_tweet.existing_like( params[:tweet_id], current_user.id )
Is there any better way how to write this? I have a feeling that this is just bad practise. Or is it perfectly ok?
thank you very much for your time

#liked_tweet = LikedTweet.where(tweet_id: params[:tweet_id], user_id: current_user.id).first_or_create

#liked_tweet = #liked_tweet.existing_like( params[:tweet_id], current_user.id ) || LikedTweet.new

Related

A better way to do conditional ActiveRecord statements?

I'm trying to figure out a better way to have one query here. I want to be able to send something to last where statement a wildcard so I can select all vendors. Right now if i don't include that line it doesn't filter by vendor so I essentially get all the purchase requests.
Any thoughts of a cleaner way to do these sorts of queries?
if #vendor == "0" #checks for vendor
#purchase_requests = PurchaseRequest.includes(:purchase_order)
.where(:created_at => #date_start..#date_end)
.where(:total_cost => #cost_beginning..#cost_end)
else
#purchase_requests = PurchaseRequest.includes(:purchase_order)
.where(:created_at => #date_start..#date_end)
.where(:total_cost => #cost_beginning..#cost_end)
.where("purchaseorder.VendorRef_ListID = ?", #vendor)
end
there must be some better solution, but try this
#purchase_requests = PurchaseRequest.includes(:purchase_order).where(created_at: #date_start..#date_end, total_cost: #cost_beginning..#cost_end)
#purchase_requests = #purchase_requests.where("purchaseorder.VendorRef_ListID = ?", #vendor) unless #vendor == "0"
Here is a simplified version:
#purchase_requests = PurchaseRequest
.includes(:purchase_order)
.where(created_at: #date_start..#date_end)
.where(total_cost: #cost_beginning..#cost_end)
#purchase_requests = #purchase_requests.where('purchase_orders.VendorRef_ListID = ?', #vendor) unless #vendor == '0'

Easier way to write If hash includes then - Ruby

I have the following in an initialize method on my model:
#home_phone = contact_hash.fetch('HomePhone')
However, sometimes I need this instead:
#home_phone = contact_hash.fetch('number')
Also, sometimes neither of those will be true and I will need the home_phone attribute to be empty.
How can I write this out without creating a big loop like so:
if contact_hash.has_key?('HomePhone')
#home_phone = contact_hash.fetch('HomePhone')
elsif contact_hash.has_key?('number')
#home_phone = contact_hash.fetch('number')
else
#home_phone = ""
end
You could try
#home_phone = contact_hash.fetch('HomePhone', contact_hash.fetch('number', ""))
or better
#home_phone = contact_hash['HomePhone'] || contact_hash['number'] || ""
contact_hash.values_at('HomePhone','number','home_phone').compact.first
Edit:
My first solution did not really give the answer asked for. Here is a modified version, although I think in the case of only 3 options the solution given by #knut is better.
contact_hash.values_at('HomePhone','number').push('').compact.first
def doit(h, *args)
args.each {|a| return h[a] if h[a]}
""
end
contact_hash = {'Almost HomePhone'=>1, 'number'=>7}
doit(contact_hash, 'HomePhone', 'number') # => 7
You could use values_at I suppose:
#home_phone = contact_hash.values_at('HomePhone', 'number').find(&:present?).to_s
That isn't exactly shorter but it wouldn't be convenient if you had the keys in an array:
try_these = %w[HomePhone number]
#home_phone = contact_hash.values_at(*try_these).find(&:present?).to_s
You could also wrap that up in a utility method somewhere or patch it into Hash.

Ruby csv import get code smaller but equal

I'm new to rails and ruby...
How can i refactor such code, which import's from csv file data?
Now i have such code
if row[qnt].to_s != ""
eqnt = /(\d+)/.match(row[qnt])[0].to_s
else
eqnt = 0
end
I try something like
if row[qnt].present?
eqnt = /(\d+)/.match(row[qnt])[0].to_s
else
eqnt = 0
end
But is it equal, and also what else could i do to get code smaller?
How about this?
row[qnt].present? ? eqnt = /(\d+)/.match(row[qnt])[0].to_s : eqnt = 0
I'm not convinced the code gains readability by trying to compress it much further.
eqnt = row[qnt].present? ? /(\d+)/.match(row[qnt])[0].to_s : 0
Or
eqnt = 0
eqnt = /(\d+)/.match(row[qnt])[0].to_s if row[qnt].present?
Or
theRow = row[qnt]
eqnt = theRow.present? ? /(\d+)/.match(theRow).first.to_s : 0
Or better yet, extract this into a method, keep the mainline code clean, and isolate the logic.
I'm not psyched about eqnt ending up with different types, though, unless that's by design.
eqnt = (/(\d+)/.match(row[qnt]) || [0])[0]

Better Rails code for update or create clause?

The code smells and i'm sure i'm missing a helper to do a simple
update or create query like the below snippet :
#user_answer = current_user.user_answers.find_by_question_id(params[:a_question])
if #user_answer.nil?
#user_answer = current_user.user_answers.build({ :answer_id => params[:an_answer] , :question_id => params[:a_question] })
#user_answer.save
else
#user_answer.update_attributes(:answer_id => params[:an_answer])
#user_answer.save
end
You might be looking for the find_or_initialize_by method. For example:
#user_answer = current_user.user_answers.find_or_initialize_by_question_id(params[:a_question])
#user_answer.answer_id = params[:an_answer]
#user_answer.save
How about,
#user_answer = current_user.user_answers.find_or_create_by_question_id(params[:a_question])
This will avoid the explicit save

getting a column by "name" in an activerecord

I have a select statement that returns a field in a table.
records = Product.select("DISTINCT #{iFieldName}").where("id in (0, #{iInClaws})" )
I want to convert the data in the database to an array to be used later.. say as another inClaws.
records.each{|record| fieldArray << record.?????}
I have two questions.
Is there a better way to do this?
If there's not, then how do I get the data out of the field.
Thanks to all..
After everyone came to help my final method looked like this.
def self.getFieldArray(iFieldName, iIDsInClaws, iIdFieldName = 'id')
records = self.select("DISTINCT #{iFieldName}").where("#{iIdFieldName} in (#{iIDsInClaws})" )
return records.map{|record| record.send(iFieldName)};
end
fieldArray = records.map(&:iFieldName)
Or
res = records.map{|r| r.send(iFieldName)}
records.each{|record| fieldArray << record.send(iFieldName)}

Resources