Rails query in controller with multiple conditions - ruby-on-rails-3

I have the following relationships set up in my models for Festivals, Categories, Submissions and Curators (users).
Festival has many categories. Each category has one Festival.
Each category has one or more curators (a user) and curators could have more than one category.
Submissions have one category and one festival (through it's category).
"current_user" is the user that is logged in
"current_festival" is the one festival that is currently taking new submissions
When a curator (a user) is logged in and they look at the index of submissions. They should only see submissions for which they are curator (through category). I'm stumped on how to generate the proper list of submissions. Here is what is in the controller now:
def index
#submissions = current_festival.submissions.all
end
This would return all the submissions for the current festival, not just from the categories that the current_user is the curator. What I want is something like this, but I don't know the proper syntax:
def index
#categories = current_user.categories.where(festival_id: current_festival.id)
#submissions = current_festival.submissions.where( category_id: "one of the #categories" )
end
Any ideas what the proper syntax would be?

This will give you all the submission that belongs to category which are created by current_user
def index
category_ids = current_user.categories.where(festival_id: current_festival.id).collect(&:id)
#submissions = current_festival.submissions.where(category_id: category_ids)
end

Related

Get relation of a collection in rails

So simple but can't find how to do it in rails. I have a specific active record collection of users. Something like users = User.where(blabla). Given this collection is there a simple way to get all posts that those users have? Similar to User.posts, only for all users in that collection.
Post belongs_to User, User has_many posts.
Thanks!
Assuming that your Post model has a user_id with an association called "user", you can do something like this:
Post.where(user_id: User.where(blablah))
or
Post.joins(:user).where(users: {<user conditions>})
You'll need to be able to use the Hash form for the user conditions to use the second option. For example:
Post.joins(:user).where(users: {role: 'member'})
If your users query is more complex, you can create a scope for it:
class User < ApplicationRecord
scope :special, -> { where(< user conditions go here>) }
end
And then merge it with the Post query:
Post.joins(:user).merge(User.special)

Get Users with an attribute for each Group?

My models: User, Group, and Membership. Users can have many groups through memberships, and vice-versa. I want to create a tool for website admins that produces a large table with the following specification:
Every row represents a user,
Every column represents a group,
In each cell of the table there is a boolean indicating whether the user belongs to the group.
What would be the best way to do this? Is it possible to write a single SQL query that achieves it (i.e. User.find_by_sql)? If not, how else?
p.s. I actually need a bit more than this (I need two columns per group, the first one indicating membership, and the second one counting how many meetings the user has attended in that group, but this involves the Meeting model, so I'll leave that for later.
Assuming that you're asking about the backend methodology not the data visualization aspect most of what JuanM. said is correct. One thing I would recommend is avoid writing his 'get_groups' method and just set up a 'has many through' relationship between users in groups. To do so put
class User < ActiveRecord::Base
has_many :memberships
has_many :groups, through: :memberships
end
In your Users model and vice versa in your Groups model (assuming memberships 'belongs_to' both). Then you'll have a '.groups' method on any User instance and a '.users' method on any Group instance
This would be my approach:
Write a function that returns if the user belongs to a group passed by parameter. Get all the groups from a user. In your user.rb model you can add this method get_groups to retrieve all groups from the user and then a method is_in(group). See code below:
class User < ActiveRecord::Base
#validations, some other stuff
has_many :memberships
#this method stores all the group-ids of the user in an array
def get_groups
myGroups = []
memberships.each do |membership|
membership.groups.each do |group|
myGroups << group.id
end
end
return myGroups
end
#this method receive a Group object and return true if the user belongs to that group
def is_in(group)
groups = get_groups
return groups.include?(group.id)
end
Then in your view or controller you can work as follow:
#the columns of the table
groups = Group.all
#iterating all users
User.all.each do |user|
#each user has to see if it belongs to each group in the groups table
groups.each do |group|
#the boolean value you display in a cell
value = user.is_in(group)
end
end

Only show submissions for the current festival

I have models in my application for Festivals and Submissions. Each submission belongs to a single festival. And I have a helper to determine what is the "current_festival" based on dates for each festival.
module ApplicationHelper
def current_festival
#current_festival ||= Festival.current.first
end
end
.current is a scope in the festival model:
scope :current, where("published = true and closing_date >= ?", Time.now.to_date).order('closing_date asc').limit(1)
What I'd like is to restrict the submissions shown in the index view to ones that belong to the current festival only. How would you do that in the controller? Or would it be best to somehow do that in the model, perhaps through a scope?
I suppose you have a relation defined like this:
class Festival
has_many :submissions
end
Then you can do in any place:
Festival.current.submissions

Eager Loading - Only load Specific Records

Quick question about eager loading. I have the following code:
#user =
User.includes(:restaurants).find_by_unique_identifier(params[:unique_identifier])
However, I only want to load restaurants associated with a given user only if the restaurants have a list_id of X (which is one of the columns of the restaurants table).
How would I go about this?
I tried the following, but it still loaded all the restaurant records associated with the user.
#user = User.includes(:restaurants).where(:restaurants => {:list_id => params[:list_id]}).find_by_unique_identifier(params[:unique_identifier])
Assuming you have all the associations requirements setup, then you can use joins:
#user = User.all(:conditions =>["restaurants.list_id = ?", params[:list_id] ], :joins => [:restaurants])
UPDATE:
My code fetches a list of users. However, You can use your filtering methods to narrow down the list or get the individual records.

Rails 3: validate that a record belongs to user

I have a HABTM relationship between Products and Categories. Those Categories belongs to a user.
At my product form, I only show checkboxes for the current user. But i want to validate this on model too, so users can't fake POST variables and assign it to invalid categories.
How can i do such validation?
Example: given a category_id 5, i have to check if this category belongs to current_user.id ( provided by devise ).
Thanks.
You can add attr_accessor: creator_id to your Post model. (creator_id is not in database )
And send current_user.id from form to Post's creator_id.
Then use model callbacks. For example after_validation:
after_validation do
if User.find(creator_id).categories.pluck(:id).include?(category_id)
true
else
errors.add :category, "is invalid for user"
end
end