Ruby on Rails: getting associated values to display - ruby-on-rails

I'm trying to create some kind of activity feed, and I'm having trouble getting the values I need to.
I have a controller with this action
def show
#user = User.find(params[:id])
#ideas = Idea.find(#user)
#lists = List.find(#user)
#li_array = (#lists + #ideas).sort{|a,b| -(a.created_at <=> b.created_at)}
end
I'm new to rails, and I'm trying to put together an array of values from the users of both ideas and lists. But I figured out that I can't do what I'm doing now because it will only pass the current user's id to match an id for Idea/List, but what I need to do is find the user's id column and search through based on #user.
I need to get all values from the users, what is the best method?
models
user.rb
has_many :lists
has_many :ideas, :through => :lists
list.rb
has_many :ideas
belongs_to :user
idea.rb
belongs_to :list
belongs_to :user
Thanks

You can simply do:
#user = User.find(params[:id])
#ideas = #user.ideas
#lists = #user.lists

Related

How to access certain database tables in Rails controller?

I am using Rails as a JSON API. My database has the following structure: the City model has_many Users, which in turn has_many Businesses.
When I send a GET request to businesses#index, I want Rails to return all the businesses in a given city, not just for a given user. What's the best way to do this?
I've already tried the given code below as a first pass, which is returning an internal server error (500).
def index
#city = City.find(params[:city_id])
#users = #city.users
#businesses = #users.businesses
render json: #businesses
end
Can you try this?
Because of the #user is an array. so the error will occuring.
# city.rb
class City < ApplicationRecord
has_many :users
end
#user.rb
class User < ApplicationRecord
belongs_to :invoice
has_many :businesses
end
#business.rb
class Business < ApplicationRecord
belongs_to :user
end
# your controller
def get_business
#city = City.find(params[:id])
#business = #city.users.includes(:business)
render json: #business
end
Add a new relationship to your City model:
has_many businesses, through: users
Then when you have a specific city you can get all businesses:
#city.businesses
You might also want to try starting with the Business model to make the query.
Business.joins(user: :city).where(cities: { id: params[:city_id] })
joins uses the association names
where uses the table names

Ruby on Rails where statement using user attribute

So basically I want something like this:
#network = Network.where(:id => current_user.network_ids).first
#posts = Post.where(:user.network.first => #network).order("created_at DESC")
But it basically doesn't recognize the column :user in the second line as the real column is user_id. I even tried:
#posts = Post.where('User.find(user_id).network.first =?',network )
with no luck
any ideas on how I could approach this.
model:
class User
has_and_belongs_to_many :network
has_many :posts
end
class Network
has_and_belongs_to_many :user
end
class Post
belongs_to :user
end
I basically want to filter the posts according to the network of the current user
So I simply solved the problem by using:
#posts = Post.where('user_id = ?', #network.user_ids)
As i can see, you have posts which belongs to a user and then user has many networks therefore your query should be
#posts = Post.where(:user.networks.first => #network).order("created_at DESC")
what your are calling is
:user.network.first
which states user has has_one relationship with network

Adding Posts To A Collection with Join Models

I'm trying to add a 'Collections' model to group Posts so that any user can add any Post they like to any Collection they've created. The Posts will have already been created by a different user. We are just letting other users group these posts in their own Collections. Basically like bookmarking.
What is the cleanest, and most Rails-ey-way of doing this?
I've created the model and run through the migration and what not. Also I've already created proper views for Collection.
rails g model Collection title:string user_id:integer
collections_controller.rb
class CollectionsController < ApplicationController
def index
#collections = current_user.collections.all
end
def show
#collection = Collection.all
end
def new
#collection = Collection.new
end
def create
#collection = current_user.collections.build(collection_params)
if #collection.save
redirect_to #collection, notice: 'saved'
else
render action: 'new'
end
end
def update
end
private
def collection_params
params.require(:collection).permit(:title)
end
end
collection.rb
class Collection < ActiveRecord::Base
belongs_to :user
has_many :posts
validates :title, presence: true
end
post.rb
has_many :collections
It seems like has_many or has_and_belongs_to_many associations are not correct? Should I be creating another model to act as an intermediary to then use
has_many :collections :through :collectionList?
If my association is wrong, can you explain what I need to change to make this work?
Also the next part in this is since this is not being created when the Post or Collection is created, I'm not sure the best way to handle this in the view. What is the best way to handle this, keeping my view/controller as clean as possible? I just want to be able to have a button on the Post#Show page that when clicked, allows users to add that post to a Collection of their own.
In such case you should use or has_and_belongs_to_many or has_many :through association. The second one is recommended, because it allows more flexibility. So now you should:
Create new model PostsCollections
rails g model PostsCollections post_id:integer collection_id:integer
and migrate it
Set correct model associations:
Something like:
class Post < ActiveRecord::Base
has_many :posts_collections
has_many :categories, through: :posts_collections
end
class Collection < ActiveRecord::Base
has_many :posts_collections
has_many :posts, through: :posts_collections
end
class PostsCollections < ActiveRecord::Base
belongs_to :post
belongs_to :collection
end
Then you'll be able to use
#collection.first.posts << #post
And it will add #post to #collection's posts
To add a post to a collection from view
Add a new route to your routes.rb, something like:
resources :collections do # you should have this part already
post :add_post, on: :member
end
In your Collections controller add:
def add_post
#post = Post.find(params[:post_id])
#collection = Collection.find(params[:id])
#collection.posts << #post
respond_to do |format|
format.js
end
end
As for views, you'll have to create a form to show a collection select and button to add it. That form should make POST method request to add_post_collection_path(#collection) with :post_id parameter.
You can read more explanations of how rails associations work in Michael Hartl's tutorial, because that subject is very wide, and can't be explained with short answer.

rails adding tags to controller

I am implementing a basic tagging feature to my app. New to rails.
I have a listings model and I am working in the listings_controller # index. When the user goes to the listing page and sets the :tag param I want #users only to hold the users which match the tag.
So if they goto www.example.com/listings?tag=foo only pages which have been tagged with foo are loaded. This is what I have come up with so far but there is several problems with it.
def index
if params[:tag]
#id = Tag.where(:name => params[:tag]).first.id
#listingid = Tagging.where(:tag_id => #id)
#listingid.each do |l|
#users = User.find(l.listing_id)
end
else
#users = User.all
end
end
I am not sure how to loop and add each found user to #users. I think I may be going about this whole thing the wrong way.. My tag/tagging models look as follows:
tag.rb
class Tag < ActiveRecord::Base
has_many :taggings
has_many :listings, through: :taggings
end
tagging.rb
class Tagging < ActiveRecord::Base
belongs_to :tag
belongs_to :listing
end
Taggings has the following colums:
id, tag_id, listing_id
Tags has the following columns:
id, name
Any guidance would be appreciated, been trying to fix this for a while with no luck.
Trying with
def index
#tag = Tag.where(:name => params[:tag]).first
if #tag
#listings = #tag.listings.includes(:user)
#users = #listings.map{|l| l.user}
else
#users = User.all
end
end

Nested Resource - Controller to filter by current_user also

Thanks to some help in another question, I now have a nested resource setup, and it is nearly working the way I need it to. This is a follow-up question about the controller.
Expenses have both a user, and a project that they belong to.
I would like to visit /projects/5/expenses, and see a list of all the expenses for that project, (which IS working), but also have it sensitive to the user that is currently signed in, so they only see their own expenses.
first the models:
class Expense < ActiveRecord::Base
attr_accessible :amount, :project_id, :user_id
belongs_to :project
belongs_to :user
end
each of the other models has "has_many :expenses", to complete the relationship.
so my route looks like:
resources :projects do
resources :expenses
end
And
class ExpensesController < ApplicationController
def index
#user = current_user
#project = Project.find(params[:project_id])
#expense_list = #project.expenses.all
end
How can I filter my #expense_list further by only showing the current_user's expenses?
You need a an additional condition to query the expenses based on the user that they belong to.
I would suggest that you create a scope in your Expense model
scope :for_user, lambda{ |user|
where( :user_id => user.id )
}
And you can do this in the controller:
#expense_list = #project.expenses.for_user(current_user).all

Resources