Return false statement - ruby-on-rails

I'm new to RoR; I want create the following statement. I've an array; I want that controller return false if all array elements are not equal to a variable value.This is the code
def check_warehouse(asset,serial)
wh = Warehouse.where(["(asset = ? and serial = ?) OR (asset = ?) OR (serial= ?)",asset,serial,asset,serial])
return false if wh.count > 1
return false if
wh.each do |wh|
wh.position_id != session[:position_id]
end
end
but it doesn't works!why?
Moreover, can you suggest me a plugin or gem running on Rails 3.1 for generate pdf from RoR datas?
Thank you all

You have this code:
return false if wh.each do |wh|
wh.position_id != session[:position_id]
end
This will not execute the way you want. In ruby, .each will execute the "block" (code between do/end) and return to you the original array.
So if wh is an array, empty or not, and you say:
return false if []
ruby will not return false. instead, you'd likely rather:
return false if wh.any? {|wh| wh.position_id != session[:position_id] }
You probably would want it to return true if the position is the session position, so you can switch to:
return wh.any?{|wh| wh.position_id == session[:position_id] }

Try smth like this:
def check_warehouse(asset,serial)
wh = Warehouse.where(["(asset = ?) OR (serial= ?)",asset,serial]) # first condition was just extra
return false if wh.detect {|wh| wh.position_id != session[:position_id] }
end
I removed return false if wh.count > 1 because there's no sense to check the array if you return if it has more than 1 element. Please tell me if I misunderstood you
UPD
Actually you can do that in the db:
def check_warehouse(asset,serial)
Warehouse.where(
["(asset = ? OR serial= ?) AND NOT position_id = ?", asset, serial, session[:position_id]]
).count.zero?
end

Related

How to sort a hash by a function depending on values from the hash

I want to sort a hash by the following conditions:
An object that has hash[:sold] as false comes before an object that has hash[:sold] as true.
If both objects have hash[:sold] as false enter code here, then compute two variables distance_a, distance_b for the two hashes. I want object a to come before object b if distance_a < distance_b.
Code:
curr_hash.sort do |a,b|
status_a = a[1][:sold]
status_b = b[1][:sold]
if status_a == false && status_b == false
a_first_loc = [a[1][:loc_id], current_loc_id].min
a_second_loc = [a[1][:loc_id], current_loc_id].max
b_first_loc = [b[1][:loc_id], current_loc_id].min
b_second_loc = [b[1][:loc_id], current_loc_id].max
distance_a = LocationDistance.find_by(city_id: current_city.id, loc_a: a_first_loc, loc_b: a_second_loc).distance
distance_b = LocationDistance.find_by(city_id: current_city.id, loc_a: b_first_loc, loc_b: b_second_loc).distance
distance_a <=> distance_b
else return status_a == false ? 1 : 0
end
end
Borrowing #Maxim's distance function and using sort_by means the distance is only calculated once for each item.
Extracting distance as a function also has the advantage that it can be tested independently
def distance(hash)
LocationDistance.find_by(loc_a: hash[1][:loc_id], current_loc_id].min,
loc_b: [hash[1][:loc_id], current_loc_id].max,
city_id: current_city.id).distance
end
a.sort_by(|x| [true ? 1 : 0, distance(x)])
This has to do the job nicely for you:
def distance(hash)
LocationDistance.find_by(loc_a: hash[1][:loc_id], current_loc_id].min,
loc_b: [hash[1][:loc_id], current_loc_id].max,
city_id: current_city.id).distance
end
a.sort{|a,b| a[:sold] == b[:sold] ? ((distance(a) < distance(b)) ? -1 : 1) : (a[:sold] ? 1 : -1)}

Update a record in a table in rails

I have a table A(:name, :flag) and want to update the flag column of a record in the table if a certain condition evaluates to true.
if A.find(300).flag == false
//Will this work -> A.find(300).flag = true
What should I write in that line?
if A.find(300).flag == false
//Will this work -> A.find(300).flag = true
change to
A.find(300).update(flag: true) if A.find(300).flag == false
You can add method to a.rb
def self.update_if_false id
find(id).update(flasg: true) if A.find(id).flag == false
end
Then you can use it as A.update_if_false(300)
This will decrease database call if flag is true:
Rails 4:
obj = A.find(300)
obj.update(flag: true) unless obj.flag
Rails 3.2:
obj = A.find(300)
obj.update_attributes(flag: true) unless obj.flag
Note: update method made public and aliased with update_attributes in active record 4.
yes..it will work...i tried in ruby2.0 console..Assuming you have all the attributes present....
2.0.0-p481 :026 > Image.find(30).title = true
Image Load (7.8ms) SELECT "images".* FROM "images" WHERE "images"."id" = $1 LIMIT 1 [["id", 30]]
=> true
you can go ahead and add your update statement ..if true else false.
if A.find(300).flag == false
##do something
else
##do other thing
end

Can't use where on a column with nil value

I have an Article model
Article.last.publish
=> nil
Article.last.publish != true
=> true
Article.where("publish != ?", true)
=> []
Why am I getting an empty array there?
There are only 2 falsy values in ruby : false and nil
So, if you check the value of !nil then the output will be true
So with your first statement
Article.last.publish # its output is nil
Then your second statement
Article.last.publish != true # this is correct , since !nil = true
But the last one
Article.where("publish != ?", true)
gets converted into a query as
SELECT `articles`.* FROM `articles` WHERE (publish != 1)
which means all articles whose publish value is not true, which means false
and false is not equal to nil.
nil and false are two different falsy values.
Try Article.where(publish: false)

One-line assignment: If (condition) variable = value1 else value2

How do I do something like this?
if params[:property] == nil
#item.property = true
else
#item.property = false
Always forget the proper syntax to write it in one line.
In PHP it would be like this:
#item.property=(params[:property]==nil)true:false
Is it the same in rails?
use the ternary operator:
#item.property = params[:property] ? true : false
or force a boolean conversion ("not not" operation) :
#item.property = !!params[:property]
note : in ruby, it is a common idiom not to use true booleans, as any object other than false or nil evaluates to true.
m_x answer is perfect but you may be interested to know other ways to do it, which may look better in other circumstances:
if params[:property] == nil then #item.property = true else #item.property = false end
or
#item.property = if params[:property] == nil then true else false end

Rails - Triggering Flash Warning with method returning true

I'm trying to trigger a warning when a price is entered too low. But for some reason, it always returns true and I see the warning regardless. I'm sure there something wrong in the way I'm doing this as I'm really new to RoR.
In model:
def self.too_low(value)
res = Class.find_by_sql("SELECT price ……. WHERE value = '#{value}'")
res.each do |v|
if #{value} < v.price.round(2)
return true
else
return false
end
end
end
In controller:
#too_low = Class.too_low(params[:amount])
if #too_low == true
flash[:warning] = 'Price is too low.'
end
I would write it somewhat different. You iterate over all items, but you are only interested in the first element. You return from inside the iteration block, but for each element the block will be executed. In ruby 1.9.2 this gives an error.
Also i would propose using a different class-name (Class is used to define a class)
So my suggestion:
Class YourGoodClassName
def self.too_low(amount)
res = YourGoodClassName.find_by_sql(...)
if res.size > 0
res[0].price.round(2) < 1.00
else
true
end
end
end
You can see i test if any result is found, and if it is i just return the value of the test (which is true or false); and return true if no price was found.
In the controller you write something like
flash[:warning] = 'Price is too low' if YourGoodClassName.too_low(params[:amount])

Resources