In my controller I have an instant variable with a where method, its part of a filter in the Search Controller.
#items = #items.where([ 'borrowable = ?', true]) if params[:top_filter] == 'borrow'
The borrowable = ?, true bit is completely wrong. What I want is to filter the #items that are borrowable by using a method in the Item's model called borrowable?.
How do I do this?
The method in the Item model is below.
def borrowable?(current_user, user, item, controller)
false
if user.invited?(current_user, user)
item.pieces.each do |piece|
if piece.available?(current_user, piece)
true
end
end
if controller == "pages"
true
end
end
end
If it's relying on model level code, then you won't be able to put it in a where clause. The where clause is trying to grab a list of items, but on each item you want to call a method, but you don't have the method until your grab the items. You could potentially use a stored procedure on the DB, but just in Rails code you could do this:
#items = #items.keep_if { |item| item.borrowable? } if params[:top_filter] == 'borrow'
You can't! ActiveRecord makes queries on the database, then builds object with the returned data. So until the data is returned, no ruby object exists, and you can't use their method.
If you are able to represent the same information using a "calculation" (in the SQL sense) then you can use it by
#items.where("some sql condition/calculation")...
Related
i think i used the right terminology for what i need, i currently have a database call in my home_controller that is returning a call to my database with all the entries in that table specified, Freelancer.
There is an attribute on these records that has either a true or false value, which is "featured".
I need a way to call a sort method, or some other way, on that object with the true being first and then the false being afterwards, i tried using this code
def index
#freelancers = Freelancer.all
p 'below im outputting featured freelancer i hope'
#freelancers.sort_by { |row| [row.featured ? 0 : 1, row.id]}
p #freelancers
end
But unfortunately this did not work, can anyone advise me on a way to get this to work? Id rather have the sorted object returned as is, rather then assigning it to a new one. Just for future features of adding pagy and a filter by cost.
Use order method
def index
#freelancers = Freelancer.order(featured: :desc)
end
The model User has first, last and login as attributes. It also has a method called name that joins first and last.
What I want is to iterate through the Users records and create an array of hashes with the attributes I want. Like so:
results = []
User.all.map do |user|
record = {}
record["login"] = user.login
record["name"] = user.name
results << record
end
Is there a cleaner way in Ruby to do this?
Trying to map over User.all is going to cause performance issues (later, if not now). To avoid instantiating all User objects, you can use pluck to get the data directly out of the DB and then map it.
results = User.all.pluck(:login, :first, :last).map do |login, first, last|
{ 'login' => login, 'name' => first << last }
end
Instantiating all the users is going to be problematic. Even the as_json relation method is going to do that. It may even be a problem using this method, depending on how many users there are.
Also, this assumes that User#name really just does first + last. If it's different, you can change the logic in the block.
You can use ActiveRecord::QueryMethods#select and ActiveRecord::Relation#as_json:
User.select(:login, '(first || last) as name').as_json(except: :id)
I would write:
results = User.all.map { |u| { login: u.login, name: u.name } }
The poorly named and poorly documented method ActiveRecord::Result#to_hash does what you want, I think.
User.select(:login, :name).to_hash
Poorly named because it does in fact return an array of Hash, which seems pretty poor form for a method named to_hash.
I have a relation in my rails database and I get one instance of my relation. I then need to determine how much of that instance is filled in. I do this by counting the nils in the relation but I don't know how to do this through code. I know about the .each loop but that makes me state the fields and i need something more like an array. This is what i have so far
#survey_data = Surveyprofile.find_by(:user_id => #user.user_id)
#counter = 0
#index = 0
#survey_data.each do |d|
//i need something like
if d[index].nil? == false
#counter = #counter +1
end
#index++
end
does anyone know how to express this??
(this is all done in the controller by the way)
I haven't tested this approach, but it should work.
survey_profile.rb:
class SurveyProfile < ActiveRecord::Base
def self.number_of_empty_answers(user_id)
user_survey = SurveyProfile.find_by_user_id(user_id)
count = 0
user_survey.attributes.each do |attr_name, attr_value|
count += 1 if attr_value.nil?
end
return count
end
survey_profiles_controller.rb:
SurveyProfile.number_of_empty_answers(#user.id)
The class method number_of_empty_answers counts the answers the user has not filled. Then you call that method from your controller.
Note that it doesn't have to be a class method. It can also be an instance method. You can find the instance first in the controller and then call the method on it.
Since you're iterating through the attributes hash, you can get more fancy and build an array of field names that have not been empty. But if you just want the count, the above should work.
I have a table in Rails and I would like to find all records of a table where a certain function returns true.
What is the best way to do this? I could of course iterate over all the records in the table and use conditional statements to test whether the function, given the individual record, returns true and add it to a list.
Is there any easier way of doing this something along the lines of Model.find(:all, :conditions => {...}) maybe?
Thanks
Class MyModel < ActiveRecord
def self.targetted
find_each.select(&:predicate_method?)
end
def predicate_method?
#something that returns either true or false
end
end
this is a bit more Rails idiomatic :
find_each will fetch your record by batches of 1000. it is better than all for your memory
&:predicate_method : transforming a symbol into a Proc (with the # operator) will actually make your code call the method on each of the passed objects
def record_that_returns_true_for_xfunction
Model.all.select {|record| xfunction(record.some_column) == true}
end
This is seems like what you are looking for. This method will return an array of all the records where xfunction(record.some_column) == true.
In my rails3.1 application, I'm trying to apply the following logic in one of my order model.
def digital?
line_items.map { |line_item| return false unless line_item.variant_id = '102586070' }
end
I've created a separate variant called prepaid_voucher which has id = 102586070. Despite this, the result is false...
Order has many line_items
LineItem belongs to order and variant
Variant has many line_items
Is this the best way to perform such a task and how can I fix?
First of all I think you want a double == here line_item.variant_id = '102586070', then I rather go for something like that (If I understand what you want)
def digital?
line_items.select{|line_item| line_item.variant_id == '102586070'}.any?
end
But it's hard to understand what you really want, what is the expected behavior if the id is not found?