Array in Ruby on rails, undefined method `minimum' - ruby-on-rails

#click = Missing.select{|d| d.click < 10000}
find = #click.minimum(:id)
#data = Missing.where(id: find)
dataSize = #data.size
#renderData = #data[dataSize - 1]
render :json => #renderData
Errors:
undefined method `minimum' for #<Array:0x00000004acd678>
Error code : find = #click.minimum(:id)
I have no idea why it is wrong.
render :json = #click is working.
find = Missing.minimum(:id) is working.

#click = Missing.select{|d| d.click < 10000} is returning an array of active record instances. This is why minimum can not be called against an array.
If you want the first record in the #click set then use #click.first.id. If you want the smallest (min) id then use #click.map(&:id).min. Looking at your code i'm not sure what you are trying to achieve?
On a side note, i'd avoid calling Missing.select{|d| d.click < 10000} because that is doing a full table scan on your Missing model's table. As Ruby Racer says, better to query with active record.

#click is an array, not an association.
Why don't you use activerecord query to get your find?
find = Missing.where('click < 10000').minimum(:id)

Related

Rails - PG::DatatypeMismatch: ERROR

So it's a very beginner question, I am getting the following error. I know that I need to convert it over to string type. I have tried many kinds of conversion method, but yet to work. Hard coding this field as something like '2018-01-01' works. The param content that I am getting back is correct. It is the type that is creating this error. I even try to convert it over to a date type and tested the type and returned true, but still fail to succeed. Let me know if this makes sense.
PG::DatatypeMismatch: ERROR: column "order_date" is of type date but expression is of type integer
My expresson
created_at = (params[:created_at])
Have tried
created_at = (params[:created_at]).to_date
created_at = (params[:created_at]).to_s
I am trying to get the params[:created_at] from the payload and use the following code to insert into psql. So I think I should go with the create action. Please let me know what I am doing wrong.
def create
created_at = (params[:created_at])
puts created_at
sql = "insert into api.salesorder(site, order_date,sale_type,sales_rep,terms,customer_number) values('WHS',#{created_at},'CUST','HOUSE','PRE','123456')"
results = ActiveRecord::Base.connection.execute(sql)
end
If you still want to use direct SQL (which I advise against in Rails, since Rails does the SQL for you), you need to change it to wrap your date in single quotes.
sql = "insert into api.salesorder(site, order_date, sale_type,sales_rep, terms, customer_number) values('WHS','#{created_at}','CUST','HOUSE','PRE','123456')"
A better solution would be to leverage Rails to do the SQL work for you. Something like this:
# in app/models/salesorder.rb
class Salesorder < ActiveRecord::Base
end
# in app/controller/salesorder_controller.rb
class SalesorderController < ApplicationController
def create
#salesorder = Salesorder.new
#salesorder.order_date = params[:created_at]
#salesorder.site = 'WHS'
#salesorder.sale_type = 'CUST'
#salesorder.sales_rep = 'HOUSE'
#salesorder.terms = 'PRE'
#salesorder.customer_number = '123456'
if #salesorder.save
redirect_to #salesorder, notice: 'Salesorder was successfully created.'
else
render :new
end
end
end
You could do something like created_at = Date.parse(params[:created_at]), but i don't think it's nescessary. Some more information might be helpful. Is your params an integer type?

Why does `where` give an "undefined method" error in Rails?

I'm trying to get all the feedbacks with a specific attribute. I am using this code:
def index
feedbacks = Feedback.all
if params[:tag]
#average_customer_rating = feedbacks.where('buyer_feedback_date is not null').rated(Feedback::FROM_BUYERS).average(:buyer_rating) || 0
#products = Product.includes(:images).tagged_with(params[:tag]).order('DESC').limit(22)
else
#products = Product.includes(:images).all
#average_customer_rating = feedbacks.where('buyer_feedback_date is not null').rated(Feedback::FROM_BUYERS).average(:buyer_rating) || 0
end
end
and Rails shows this error:
undefined method `where' for []:Array
Why can't I use where here and how do I fix it?
In Rails 3.x, all returns an array:
feedbacks = Feedback.all # <- an array
feedbacks.where(...) # <- fails
To get an ActiveRecord::Relation, you have to use scoped:
feedbacks = Feedback.scoped # <- an ActiveRecord::Relation
feedbacks.where(...) # <- works
See Working with scopes for more examples.
Note that this distinction is not needed in Rails 4 anymore – scoped was deprecated in favor of all which now returns an ActiveRecord::Relation.
Why can't I use where on an array?
Because Array class does not have instance method called where.
Since feedbacks.class is Array, you get an error.
You have two options:
Define feedbacks as instance of ActiveRecord::Relation and use where
Not using where but appropriate methods from Array class.
If Feedback is your ActiveRecord model, you could probably use Feedback.where('buyer_feedback_date is not null').
feedbacks = Feedback.all
Why would you query every entry in this table to get
feedbacks.where('buyer_feedback_date is not null').rated(Feedback::FROM_BUYERS).average(:buyer_rating) || 0
Try this =>
#average_customer_rating =Feedback.where('buyer_feedback_date is not null').rated(Feedback::FROM_BUYERS).average(:buyer_rating) || 0
else
#average_customer_rating = Feedback.where('buyer_feedback_date is not null').rated(Feedback::FROM_BUYERS).average(:buyer_rating) || 0
Should scope it to cust_feedback

Using a Variable Name as Attribute in Rails

I want to DRY up my Rails code by making a common method that will be reused. In order to do so, I have to make some field/attributes and the class name that is used in the code variables, so it can work for the three models (and their fields) with the same code. I tried to learn from this question and this one, but I haven't been able to get it to work.
In my model, I have this:
def self.update_percentages
update_percentages_2(User, "rank", "top_percent")
end
def self.update_percentages_2(klass, rank_field, percent_field)
rank_class = (klass.name).constantize
total_ranks = rank_class.maximum(rank_field)
top_5 = (total_ranks * 0.05).ceil
rank_class.find_each do |f|
if f.send("#{rank_field}") <= top_5
f.send("#{percent_field}", 5)
f.save
end
end
end
With this code, I get ArgumentError: wrong number of arguments (1 for 0). When I start commenting lines out to narrow down the problem, it seems that the f.send("#{percent_field}", 5) causes the error.
And if I add:
percent_field = (percent_field).constantize
I get: Name Error: wrong constant name top_percent.
Can someone please help me determine what I'm doing wrong?
If you want to assign to an attribute, you need the method name with the equal sign:
f.send("#{percent_field}=", 5)
Also, this:
rank_class = (klass.name).constantize
is equivalent to this:
rank_class = klass
I would rewrite your method to update all qualifying records in on transaction.
def self.update_percentages_2(klass, rank_field, percent_field)
top_5 = ( klass.maximum(rank_field) * 0.05).ceil
klass.where("#{rank_field} <= ?", top_5).update_all(percent_field => 5)
end
BTW
Here is an answer to your original question.

NoMethodError When Using Database Column Aliases in Rails

Undefined method errors when I try to use a column alias for an aggregate (PostgreSQL)
Inside my model:
class B2bLoginAttempt < ActiveRecord::Base
set_table_name "b2b_logins"
end
Inside my controller:
#client_ip = request.env['REMOTE_ADDR']
#sql = "select count(id) as failed_logins FROM b2b_logins WHERE ip_address = '"+#client_ip+"'"
f = B2bLoginAttempt.find_by_sql(#sql)
failed_attempts = f.failed_logins.to_s
f.destroy
Then I see: undefined method `failed_logins' for #<Array:0x104d08478>
The error occurs because find_by_sql returns an array, so you need to write f.first.failed_logins.to_s instead of f.failed_logins.to_s.
Check find_by_sql doc here.
Not sure I am completely following your logic correctly, but it seems like you may be better off with this:
f = B2bLoginAttempt.where("ip_address = ?", #client_ip)
f.map(&:destroy)
You can get the actual count with f.count
Did I miss something?

how to write a ActiveRecord query in the controller using a db column

I am doing the following:
#group_coach = GroupCoach.find("groups_count < '9'" )
I have a groups_count column in my db that is being updated by a counter_cache => true method in the Group model.
I know this isn't right. Because the error it spits out: Couldn't find GroupCoach with ID=groups_count < '9'
I have reviewed the Rails Guides:
client = Client.find(10)
Client.where("orders_count = '2'")
The second option does run in the localhost but isn't actually returning a GroupCoach... It just returns groupcoach...
What is the proper syntax for this?
Have you tried:
#group_coach = GroupCoach.where("groups_count < 9")
To clarify: #group_coach will be a collection of records. So you can't call #group_coach.name because all that will do is give you "GroupCoach" (the name of the class). Instead, you would need to iterate over the items:
#group_coach.each do |group_coach|
puts group_coach.name
end

Resources