undefined method `order' for []:Array - sql

I have the following code where I load the activities for the user based on whether or not they are an admin. Users can only see their own activity feed, whereas admins can see the entire stream. This is a precursor to sharing activity feeds with friends, etc.
def index
if current_user?
#incidents = Incident.find_all_by_user_id(current_user.id).order("created_at desc")
else
#incidents = Incident.all.order("created_at desc")
end
end
I am getting the above referenced error(undefined method "order" for []:Array). It seems to be the .order reference, but I have checked the rails Guides and it seems to be correct syntax.
Any ideas?

Try changing the find_by... to where, so:
def index
if current_user?
#incidents = Incident.where(user_id: current_user.id).order("created_at desc")
else
#incidents = Incident.all.order("created_at desc")
end
end
should work :-)

The #index action method can be simplified and optimized (by replacement find_all_by with where) to:
def index
clause = current_user? && Incident.where(user_id: current_user.id) || Incident
#incidents = clause.order("created_at desc")
end

Related

how can I hide resources?

I want to create a page where it shows the resource created by other users but hide the resources created by current_user. is there a method or certain way in which I can do so?
class ExamplesController < ApplicationController
def index
#examples = Example.all.order("created_at DESC")
#creator_examples = Example.where(creator: current_user).order("created_at DESC") <---hide this!!!
end
You can simply manipulate your where clause into something like this:
def index
#examples = Example.all.order("created_at DESC")
#creator_examples = #examples.where.not(id: current_user.id)
end
This is for rails 4, if you're using rails 3
#creator_examples = Example.where("id != ?", current_user.id)
Note -> Example.all in rails 3 returns an array so you can't chain it with where

act_as_votable rails Counting votes on answers emited by specific user

I am close to new at Ruby on Rails (but love it) and I cannot managge to filter acuratelly.
Mi goal is to retrieve all the votes puted on answers created by one user. And I am using act_as_votable_gem
On answer.rb I have:
class Answer < ActiveRecord::Base
acts_as_votable
belongs_to :user
belongs_to :letter
...
end
At user.rb I have:
class User < ActiveRecord::Base
acts_as_voter
has_many :answers, dependent: :destroy
...
end
At users_controller.rb comes the trick because I have the letter form on the user show action:
def show
#user = User.find(params[:id])
#letter = Letter.new(params[:letter])
#letters = #user.letters.all
#answers = #user.answers
...
#emitedupvotes = #user.votes.up.count
#emiteddownvotes = #user.votes.down.count
#totalemitedvotes = #emitedupvotes + #emiteddownvotes
#receivedupvotes = ????????
#receiveddownvotes = ???????
...
end
I have tryed:
a) (the recomended one) #receivedupvotes = #answer.votes.up.count but this one needs #answer = Answer.find(params[:id]) and I am having => "ActiveRecord::RecordNotFound at /users/1 Couldn't find Answer with id=1"
Or, if I do: Answer.find(params[:answer_id]) => "Couldn't find Answer without an ID".
b) (the most logical) #receivedupvotes = #answers.votes.up.count => "undefined method `votes' for nil:NilClass"
c) (crazy one) #receivedupvotes = #answers.user.votes.up.count => "undefined method `user'"
d) #receivedupvotes = #answers.votes.up.where("voter = #user").count => "undefined method `votes' for nil:NilClass".
So, I tryed joins (never done before):
e) #receivedupvotes = #answers.joins(:votes).votes.up.count => "undefined method `votes' for..."
f) #receivedupvotes = #answers.joins(:votes).up.count => "undefined method `up' for..."
Any help? Thanks.
I don't know if you're still stuck on this, but if so..
What gets voted on? Seems like Answer gets voted on.
If User has_many :answers, then that means #user.answers will return you an array of Answer objects. However, judging by your point b) it looks like #answers is nil, so you'll have to dig into that to find out why.
So getting #user.answers to return an actual array of Answer and not nil is your first step.
Once you get that far, #answers.votes won't work because again, #answers is an array. Each Answer has votes, so you would call votes on an instance of Answer, not on the array.
Getting back to your main goal which is to tally up all the up and down votes a user received. Since User doesn't get voted on, but Answer does get voted on, you'll want to tally up all the votes for each of the user's answers.
Here's one way:
#receivedupvotes = 0
#receiveddownvotes = 0
#user.answers.each do |answer|
#receivedupvotes = #receivedupvotes + answer.votes.up
#receiveddownvotes = #receiveddownvotes + answer.votes.down
end
Also, you should really use underscores in your variable names, like #received_up_votes. It's the recommended way for Ruby and is more readable.
Jeff. Thank you very much. It is working now as it should.
This is the answer for others to read:
#user.answers is working as it should.
An this is the working implementation for counting votes on user answers with act_as_votable:
#user_answers_received_upvotes = 0
#user_answers_received_downvotes = 0
#user.answers.each do |answer|
#user_answers_received_upvotes = #user_answers_received_upvotes + answer.votes.up.size
#user_answers_received_downvotes = #user_answers_received_downvotes + answer.votes.down.size
end
#user_answers_total_received_votes = #user_answers_received_upvotes + #user_answers_received_downvotes
I will upvote your answer when I can.
Thanks again.

Where to set session default value?

guys!
Prior to asking i should mention, that i`m working without ActiveRecord or any self-hosted-database. So thats why i have to store some values in the session.
From the very begining i desided to set session value of the users city in the layout. - i supposed it would be loaded before anything else. So i`ve done something like this:
<% session[:city] ||= {:name => 'City-Name', :lat => '40', :lng => '40'}%>
But when i`m loading directly to inner page it occurs that session[:city is nil *(
How should i set the session properely, so that it wouldn`t be nil???
I had similar needs in one of the applications I worked on. It needed the users data to be loaded on sign-in and stored in the session. So, wrote a module called session_helpers.rb with the following:
module SessionHelpers
def get_value(key)
session[key.to_sym]
end
protected
def store_data(*objects)
objects.each do |object|
if object.is_a?(Hash)
object.each do |key, value|
session[key.to_sym] = value
end
end
end
end
def remove_data(*objects)
objects.each do |object|
if object.is_a?(String)
key = to_id(object)
else
key = to_id(object.class.name)
end
session[key] = nil
end
end
def update_data(key, value)
session[key.to_sym] = value
end
private
def to_id(name)
"#{name.parameterize('_').foreign_key}".to_sym
end
end
You can make any or all the methods available to views as well:
# application_controller.rb
helper_method :get_value
From the model I would retrieve a hash of the data that needs to be put up in the session about the user:
def common_data
#data = Hash.new
#data.merge!( { 'news' => self.news.count } )
...
#data
end
As I wanted to do this after sign-in I overrode the devise method to do this:
def after_sign_in_path_for(resource_or_scope)
store_data( '_count', current_user.common_data )
dashboard_path
end
This way I was able to load important data about the user on sign-in and store it in the session and retrieve whenever I wanted. Hope this helps.

Rails 3: Sortable Columns

I'm following Railscasts #228 in Rails 3.0.5 and ruby 1.9.2p180.
I have copied code near verbatim from the verbatim with the exception of changing the class name from Product to Player. I'm also skipping the last portion where Ryan adds arrows to denote the sort direction. I'm able to load the correct index page and see all of the desired URL's with the desired parameters (direction and sort), but nothing is actually happening on click. The URL is changing, but the page is not reloading.
Here is my code:
ApplicationHelper
def sortable(column, title = nil)
title ||= column.titleize
direction = (column == params[:sort] && params[:direction] == "asc") ? "desc" : "asc"
link_to title, :sort => column, :direction => direction
end
PlayersController
def index
#players = Player.order(sort_column + ' ' + sort_direction)
end
private
def find_team
session[:team] ||= Team.new
end
def sort_column
Player.column_names.include?(params[:sort]) ? params[:sort] : "name_e"
end
def sort_direction
%w[asc desc].include?(params[:direction]) ? params[:direction] : "asc"
end
Thanks for your help!
Edit: As requested, HTML code. You can see that the link for Position is currently desc, as I am at: http://localhost:3000/players?direction=asc&sort=abb_pos. However, no actual sorting has occurred for this column, or any other column.
<th>Name</th>
<th>Team</th>
<th>Position</th>
<th>Height</th>
<th>Weight</th>
Nathan
I'd suggest doing this first thing:
def index
order = sort_column + ' ' + sort_direction
puts "-- order:'#{order}'"
...
end
Click the links and then look in server's console for that "--" output. Most probably there's a logical flaw somewhere that makes the actual compiled ORDER clause always be the same. Links themselves look perfectly okay. Unless there's a # character in the links somewhere, all clicks should work (i.e. the browser should reload the content).
As for the problem in general, there's a gem called handles_sortable_columns, which gets you sortable columns for no effort at all.
Alex
Found the issue. I had the following code in my player model:
Player.rb
default_scope :order => 'name_e'
As a result, the SQL search generated looked like this:
SELECT `players`.* FROM `players` ORDER BY name_e, avg_points desc

Rails: join with multiple conditions

I have a simple model like
class Interest < ActiveRecord::Base
has_and_belongs_to_many :user_profiles
end
class UserProfile < ActiveRecord::Base
has_and_belongs_to_many :interests
end
When I want to query all the users with a specific interests, that's fairly simple doing
UserProfile.joins(:interests).where('interests.id = ?', an_interest)
But how can I look for users who have multiple interests? Of course if I do
UserProfile.joins(:interests).where('interests.id = ?', an_interest).where('interests.id = ?', another_interest)
I get always an empty result, since after the join, no row can have simultaneously interest.id = an_interest and interest.id = another_interest.
Is there a way in ActiveRecord to express "I want the list of users who have 2 (specified) interests associated?
update (solution) that's the first working version I came up, kudos to Omar Qureshi
specified_interests.each_with_index do |i, idx|
main_join_clause = "interests_#{idx}.user_profile_id = user_profiles.id"
join_clause = sanitize_sql_array ["inner join interests_user_profiles interests_#{idx} on
(#{main_join_clause} and interests_#{idx}.interest_id = ?)", i]
relation = relation.joins(join_clause)
end
in (?) is no good - it's an OR like expression
what you will need to do is have multiple joins written out longhanded
profiles = UserProfile
interest_ids.each_with_index do |i, idx|
main_join_clause = "interests_#{idx}.user_profile_id = user_profiles.id"
join_clause = sanitize_sql_array ["inner join interests interests_#{idx} on
(#{main_join_clause} and interests_#{idx}.id = ?)", i]
profiles = profiles.join(join_clause)
end
profiles
You may need to change the main_join_clause to suit your needs.
This will get users that have at least one of the specified interests.
UserProfile.joins(:interests).where(:id => [an_interest_id, another_interest_id])
To get users that have both of the specified interests I'd probably do something like this:
def self.all_with_interests(interest_1, interest_2)
users_1 = UserProfile.where("interests.id = ?", interest_1.id)
users_2 = UserProfile.where("interests.id = ?", interest_2.id)
users_1 & users_2
end
Not amazingly efficient, but it should do what you need?
Try IN (?) and an array:
UserProfile.joins(:interests).where('interests.id IN (?)', [1,2,3,4,5])