each_with_index not working for an array rails [closed] - ruby-on-rails

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
When each_with_index is used along with an array of active records returned from a query and when i call the attributes of the model. it says undefined method, for the attribute
Controller
#user_contact_query=Usercontact.select("*")
#available_contacts_array=Array.new
#user_contact_query.each do |variable|
#user_query=User.find( :all,:conditions => ["id = ?",variable.relator_id])
#available_contacts_array.push(#user_query)
end
View
<% #available_contacts_array.each_with_index do |variable, index| %>
<%= variable.email %>
<% end %>

Well, step by step, since this is rather bad code:
#user_contact_query = Usercontact.select("*")
the select part here is a bit strange, I would have used .all. Otherwise no problem here.
#available_contacts_array = Array.new
since in the next line you assign an array anyway there is no need to 'initialize' this variable here, you could just omit that line. (Most Ruby programmers would use [] to initialize an empty array in most cases)
#available_contacts_array = #user_contact_query.to_a
Assuming that we get some records back from the query we now should have an array with user contact objects. Again a simple .all would have had a similar effect as far as I understand what's going on. But assuming that Usercontact has email this is fine and what you expect it to be.
#user_contact_query.each do |variable|
#user_query = User.find(:all, :conditions => ["id = ?", variable.relator_id])
#available_contacts_array.push(#user_query)
end
Now if I get this right what you do is you go through all Usercontacts you found, find every User related to it (possibly more than one) and then attach the result at the end of the array of Usercontacts. As a result you have a mix of Users and Usercontacts in that array. (Which still would work in your view if both have email, since thanks to duck typing Ruby would not care. But most likely one of both is missing email). Also if more than one User is found then an array of users is pushed. And an array for sure has no email.
Ok, with your edit it becomes simple. When you use :all with find then what you get is not a record but an array of records (even if there us only one.). You can just do:
User.find(variable.relator_id)
which will then find a single record and push that in the array. Which I guess is what you expect it to do.
There would be better ways in Rails to do this but this would require the models to be defined properly what your use of relator_id makes look unlikely.

First off please post your full error message. Although Without seeing the error I can tell with certainty that the issue is caused by you calling a method on a nil object i.e you think a value exists where it actually does not.
Besides that you really really should take more care of your code. The code you have right now is just plain horrible. This is an equivalent of your code:
#available = []
UserContact.find_each do |contact|
#available << User.find(contact.relator_id)
end
An alternative is to use #inject
#available = UserContact.all.inject([]) do |list, contact|
list << User.find(contact.relator_id)
list
end
And the best solution would be to actually use ActiveRecord assocations here.
P.S your code does not make much sense anyhow. Why would you put users contacts and users both into that list?

Why don't you do just?
controller's helper:
#array = Usercontact.select( "*" ).map do| variable |
User.find( :all,:conditions => [ "id = ?",variable.relator_id ])
end
view's helper:
#array.each.with_index do| variable, index |
# ...
end
General note: you'be used in the #available_contacts_array variable mixed types, probably this lead to the error, please don't do in such matter.

Related

Rails join query

I am pretty new in rails and honestly, I am struggling with queries even after multiple researchs.
Here is my simple schema:
So basically, a question has many options, an option belongs to a question and has many answer, and an answer belongs to an option and has many users.
I don't think it s necessary to post the models code since it is just like i mentioned above.
What i would like to do is given a question option, see if a particular user already checked it (so look in the answer table if there is a row matching a given id_option, user_id and user_type). So in my haml loop, when displaying the different question option, i'm calling a method of my question_option model just like this :
- question.question_option.all.each do |option|
#{option.title}
.check
- if option.selected_by(current_actor)
= check_box_tag(option.id, "checked",true, class: 'styled-checkbox')
- else
= check_box_tag(option.id, "checked",false, class: 'styled-checkbox')
and the method called :
def selected_by(answerer)
answer_match =
::Vacancies::QuestionOption
.joins(:answers)
.where(answerer_id: answerer.id, answerer_type:answerer.type )
response = answer_match.find(self.id)
return response
end
This method is located in my QuestionOption model and leads to no errors but it s not working ever.
Can you help me transform this query to make it work with ActiveRecord ? Thanks
Try the below code. It checks if there are any answers by the user passed in the params on the question. I think this is what you intended to do as well-
def selected_by(answerer)
answers =
Answer.where(answerer_id: answerer.id, answerer_type:answerer.type, id_option: self.id)
answers.exists?
end

Display all versions of individual records in Papertrail

I'm building a league system and currently it stores and updates the players 'elo score' depending on the result. Now, I'm trying to add in 'HighCharts' to display the players elo score over the season in a sweet looking line chart. Someone suggested I use Papertrail to store the updates and I have got that all installed.
Now here comes my problem, I can't seem to figure out how to spit out the users elo_score versions in an array easy for 'HighCharts' to use. I can get the last updates to elo_score:
Last updated score = <%= #player.versions.last.reify.elo_score %>
But I can't seem to find the syntax to spit out all the 'versions' for 'elo_score'. Something like "1000, 1020, 1043, 1020".
I've also tried:
<%= #player.versions.map { |version| version.reify.elo_score} %>
But this gives me "undefined method `elo_score' for nil:NilClass". While just <%= #player.versions.map { |version| version.reify %> spits out all information in the record and obviously not just the elo_score.
Can anyone help? Sorry if I've not made this clear, I'm absolute brand new to rails, and this is just a fun project in my spare time but I'm having a blast!
Thanks alot!
What you did here:
#player.versions.map { |version| version.reify.elo_score }
Is perfectly fine to take all those scores and put them in an array. The problem that you're getting (the nil:NilClass stuff) is coming because at least one reify is nil. That is, that some version doesn't have a reify.
If each version is supposed to have a reify, be sure to add that as a model validation, and find in your code where the reify is being set and see why it's nil.
If it's okay for a version to have a nil reify, you could accomplish it a number of ways, but the straightforward and explicit way would look like this:
elo_scores = []
#player.versions.each do |version|
unless version.reify.nil?
elo_scores << version.reify.elo_score
end
end
I would suggest putting this in to a method, like get_elo_scores, and then you could more easily call it like:
#player.get_elo_scores
EDIT For clarification from the comments:
Your User model (or Player model, whatever you named it) should have a method that looks like this:
def get_elo_scores
elo_scores = []
self.versions.each do |version|
unless version.reify.nil?
elo_scores << version.reify.elo_score
end
end
return elo_scores
end
I apologize for not making this clearer, but you won't have access to #player within this method because that only exists in the context of your controller and view. The above is now a proper instance method: it will call .versions upon itself, and the rest is fine. I also added an explicit return call at the end.
Now you will be able to call #player.get_elo_scores on any User (or Player) object.
Hope that helps!
Here's a one-liner version of #MrDanA's answer :
elo_scores = self.versions.map{|version| version.reify.elo_scores}
note that you can't check if version.reify.nil? though

How do I add an `.order` invocation to a ActiveRecord collection that I retrieved?

I am new in this world of Rails. And I cannot get my head around this problem. How to get #microposts ordered by the date the micropost was created.
This is the line
#microposts = current_user.followeds.map(&:microposts).flatten
I only managed to order by date the 'followeds', but that is not what I am looking for. All the attempts I have made gave me errors, so I guess I am not aware of some syntax.
Any help is welcome!
Normally, you would add an order clause, as in:
Micropost.where(:written_by => current_user.followeds).order(:created_at)
The way you currently have this line structured doesn't permit that, however, since order is only available on ActiveRecord::Relations, and once you do map you no longer have a Relation available to chain on.
If that's the case, you'll want something like:
current_user.followeds.map(&:microposts).flatten.sort_by { |m| m.created_at }
I think you should try to approach this from another angle.
How about something like this:
#microposts = Micropost.where(author_id: current_user.followed_ids).order(:created_at).all
You might of course have to exchange author_id for whatever foreign key you have to identify what user a Micropost was written by.
If you want to reverse the posts (newest first), you just write order("created_at desc") instead.

Rails Active Record find all including duplicates

How can I get duplicate posts in my view?
I want to be able to do something like this:
#post = post.find(1,2,1)
to return post 1 , post 2 and then post 1 (again).
realize this is a dumb question but I can't find any documentation.
Although I'm not sure about the use case you can do something like:
#posts = Post.find(1,2) << Post.find(1)
of you can define this in your Post model:
def find_with_array(*args)
posts = []
for arg in args
posts << Post.find(arg)
end
posts
end
Obviously the above is inefficient as you are making many SQL calls. If you want it efficient then you can write a code that makes one sql call (but will not return duplicates) and then iterate through the array and rearrange (with copying for duplicates) such as (not fully tested):
def find_with_array(*args)
posts_with_no_duplicates = Post.find(args)
posts_with_duplicates = []
for arg in args
for post in posts_with_no_duplicates
if arg == post.id
posts_with_duplicates << post
end
end
end
end
This one should be better as you are only making one call to DB (normally slowest part) however it's O(N^2) There might be a way to make it O(N) if need be. However It's great improvement from the previous option
Without knowing more detail, here's what I would advise. Take a look at this post regarding checkbox arrays: http://www.skuunk.com/2008/05/checkbox-arrays-in-rails.html
Each checkbox drops a value into a particular params key. This will solve the problem of getting an array with a list of values. Let me know in the comments if this doesn't resolve your particular issue.

Rails: Flatten array in parameter

I'm trying to flatten an array for my form.
def update
#tour = Tour.find(params[:id])
params[:tour][:hotel_ids][0] = params[:tour][:hotel_ids][0].split(',')
...
This results in:
"hotel_ids"=>[["1","2"]]
Naturally I want it to be
"hotel_ids"=>["1","2"]
My Form:
<%= text_field_tag 'tour[hotel_ids][]', nil %>
Hope anyone can help with this.
EDIT
I've gotten it to work, somehow. This might be a bad way to do it though:
I changed the text_field that get's the array from jquery to:
<%= text_field_tag 'tour[h_ids][]', nil %>
then in my controller I did:
params[:tour][:hotel_ids] = params[:tour][:h_ids][0].split(',')
And this works, I had to add h_ids to attr_accessor though. And it will probably be a big WTF for anyone reading the coder later... but is this acceptable?
This is ruby!
params[:tour][:hotel_ids][0].flatten!
should do the trick!
ps: the '!' is important here, as it causes the 'flatten' to be saved to the calling object.
pps: for those ruby-related questions I strongly suggest experimenting with the irb or script/console. You can take your object and ask for
object.inspect
object.methods
object.class
This is really useful when debugging and discovering what ruby can do for you.
Simply use <%= text_field_tag 'tour[hotel_ids]', nil %> here, and then split like you do in example.
What really happens in your example is that Rails get param(-s) tour[hotel_ids][] in request and it thinks: "ok, so params[:tour][:hotel_ids] is an array, so I'll just push every value with this name as next values to this array", and you get exactly this behavior, you have one element in params[:tour][:hotel_ids] array, which is your value ("1,2"). If you don't need (or don't want) to assign multiple values to same param then don't create array (don't add [] at the end of the name)
Edit:
You can also go easy way (if you only want answer to posted question, not solution to problem why you have now what you expect) and just change your line in controller to:
params[:tour][:hotel_ids] = params[:tour][:hotel_ids][0].split(',')
#split returns array and in your example you assigned this new array to first position of another array. That's why you had array-in-array.

Resources