Where method if condition is false - ruby-on-rails

Does it return empty array or nil if condition is false?
For example:
#result=Result.where(:test_id=>test_id, :user_id => current_user.id).first
if there is no result with such test_id and user_id.
I just don't get, I thought first option, but this returns nil.

Your variable is constructed in two parts, the first part returns an ActiveRecord::Relation (which is essentially an array):
#result_array = Result.where(:test_id=>test_id, :user_id => current_user.id)
> #result_array.class
=> ActiveRecord::Relation
which is empty (shows as []) if there are no results.
The second returns the first item, or (if it's the empty array) nil:
> (1..10).first
=> 1
> [].first
=> nil
#first_or_nil = #result = #result_array.first
I recommend typing these type of commands in the rails console to see what the results.

For your problem you may use like this code.
#result=Result.where(:test_id=>test_id).(:user_id => current_user.id).first

Thy to use #bang with method .first!
For example:
#result=Result.where(:test_id=>test_id, :user_id => current_user.id).first!
It should return the first element whit ruby will meet in table "results".
It should help.

You can also use this simple query...
#result=current_user.results.find_by_test_id(:test_id)

Related

Retrieve a value from a hash in a hash in an array in a hash

I am trying to get the value of zap in a hash that looks like:
hash = {
:foo => 1,
:bar => [{
:baz => 2,
:zot => {
:zap => 3
}
}]
}
hash.dig breaks as soon as it gets to the array.
If it's important, this is a step in an if/elsif/else statement checking for different error messages. (i.e. elsif zap == 3)
I would do something like this:
hash[:bar].first.dig(:zot, :zap)
I believe you are incorrect, and dig in fact works on any object with a dig method. Dig is defined both for arrays and hashes. Also, if I define a dig method on a custom object:
o = Object.new
def o.dig(*args)
puts args.inspect
return :result
end
then when called like so:
{custom_object: o}.dig(:custom_object,1,2,3)
#-> output: [1,2,3]
#=> :result
you can see that dig gets called on o with the remaining arguments ([1,2,3]) and returns whatever the custom dig method returns.
What you may have missed is that for arrays, you need to use a numeric index, or dig raises a type error when it gets called on the array. So hash.dig(:bar, 0, :zot, :zap) is what you probably want. (credit to Alex for beating me to the punch).

Checking for nil result set before viewing

I've been reading Checking for nil in view in Ruby on Rails but I'm struggling to implement the marked solution.
I want to only load a graph in my View if a result set is not nil.
Controller:
#statistics = # ...my ActiveRecord query...
Helper:
def show_stats(statistics)
if statistics.pluck(:count)
image_tag(Gchart.line :size => '640x260',
:stacked => false,
:title => '',
:data => [statistics.pluck(:count)],
:legend => ['Stats'],
:bar_colors => ['3300CC', '3399FF'],
:axis_with_labels => ['y'])
end
end
View (HAML):
= show_stats(#statistics)
Currently when there are no statistics, I get an error. I want the View to not render the graph if there are no statistics. What am I doing wrong in the helper?
Error:
undefined method `-' for nil:NilClass
on the line where I call the helper.
if i understand correctly statistics.pluck(:count) will always return an array consisting of values of count attribute for each record found.
in ruby empty array evaluates to true, you might try to rewrite that if line like this:
if statistics.pluck(:count).any?
in fact it's good idea to cache that value and not fetch it from db again few lines below:
if (counts = statistics.pluck(:count)).any?
...
:data => [counts]
...
end
also i assume :data option wants array of values and not array of array of values so the final version would be:
if (counts = statistics.pluck(:count)).any?
...
:data => counts
...
end
P.S. if you still have an error - please share a full backtrace with us, knowing only "undefined method" doesn't tell much
Why not check for #statistics in your view like follows:
= show_stats(#statistics) if #statistics
Did you try this?
= show_stats(#statistics) unless #statistics.nil?

How get value from database ?

How get items from table ? I want get value from question column, using condition.
#result = Customers.where(:name => session[:username], :email => session[:useremail])
Now, I can get value from any column ? like this: #result.column_from_customers_table , right ?
This is a common mistake for beginners. The code you have returns an ActiveRecord::Relation object and doesn't actually connect to your db yet. In order to get a record you have to loop through each one of the results or call .first on it in order to get the first matching result
# returns an ActiveRecord::Relation object
#results = Customers.where(:name => session[:username], :email => session[:useremail])
# returns the first matching record
#object = #results.first
# then you can call the column names on #object
#object.name
#object.email
# looping through the results
#results.each do |object|
puts object.name
puts object.email
end

How can I select the minimummonths value?

In SQL I would do this:
SELECT minimummonths WHERE name = "gold"
I want to do the same in Ruby on Rails and have the following in the new section of my orders controller:
#plan = params[:plan]
#Payplanrow = Payplan.where(:name => #plan).minimummonths
I then try to display #payplanrow in my page using <%=#Payplanrow %> but it doesnt work. I get the error:
undefined method `minimummonths' for #<ActiveRecord::Relation:0x007fe30f870ec0>
I want to print the minimummonths value for the plan selected. There will only ever be one row of data corresponding to the #plan value.
I'm pretty new to Ruby on Rails so I'm just trying to get a pointer in the right direction. I looked everywhere but there doesn't seem to be an example of this.
The problem is Payplan.where(:name => #plan) is returning an array of Payplan objects. Assuming you are using Rails 3, you can read more about it in "Active Record Query Interface".
But, if you are certain that your query is returning only one record you could do:
#Payplanrow = Payplan.where(:name => #plan).first.try(:minimummonths)
The Rails way is to have a scope in your model:
class Payplan < ActiveRecord::Base
scope :by_name, lambda {|name|
{:conditions => {:name => name}}
}
end
#controller
#Payplanrow = Payplan.by_name(#plan).first.try(:minimummonths)
Although it's not really optimal, you can do:
#Payplanrow = Payplan.where(:name => #plan).first.minimummonths
You can use pluck to get only the minimummonths value :
minimummonths = Payplan.where(:name => #plan).pluck(:minimummonths).first
Instead of using where then first, it's better to use find when you are expecting a single record.
#Payplanrow = Payplan.find_by_name(#plan).try(:minimummonths)
That should be:
Payplan.where(:name => #plan).first.minimummonths

Using best_in_place gem how do I specify a nil value for a select tag?

The answer on this question has provided me with a nice roadmap for how to generate select tags with data from a collection on an association.
This works nicely and everything is going great.
The issue I have now is, how do I handle an empty collection?
With the regular :type => :input, I can just specify :nil => "Some nil message here".
But that doesn't seem to work for the collection, and to make matters worse, when there is nothing in the collection it seems to be displaying some integers (i.e. 1 and 2). I am assuming those are the IDs from the previously displayed objects in the collection, but for obvious reasons that doesn't make much sense.
Any ideas on how I can handle an empty collection with this gem?
Thanks.
Edit 1:
One alternative is to just put my original best_in_place helper tag inside an if statement for when a collection is not nil. But then how does the user edit it when it is blank? Perhaps there may be no way to handle this, because it would involve creating a new record in the collection.
I use a "workaround" for the empty options in a select tag, it could help you:
:type => :select, :collection => #my_colletion || [[I18n.t('common.none'), -1]]
When #my_colletion is nil, it shows a choice named 'None' with id = -1 (wich is not that bad to handle in the backend).
This part of code assumes the #my_collection is an array of arrays like [ [key, value], [key, value], ... ] OR nil.
Although, if you want your MyModel.all collection to fit the conditions for best_in_place, you can use the following:
#my_collection = MyModel.all.map{ |object| [object.name, object.value] }
# => this returns an array like [ [key, value], [key, value], ... ]
# => returns an empty array (NOT nil) if there is no entry in the DB
About the -1 id:
Using the -1 id as 'none' is easy because you don't need to explicitly handle the value nil (tests, etc). With the -1 id, you can use the following:
MyModel.where(id: params[:id]).first # => Returns the first object that has the params[:id]
# if params[:id] is -1, it will return nil and not raise an error.
I hope it helped :)

Resources