Incorrect user posts being displayed. (Follower & Following) - ruby-on-rails

I am trying to display posts from users I am following. However, for some reason my stream index is displaying posts from users who are following me. How can I display posts from users I am following and not the other way around? Thank you in advance.
User Model
has_many :following, :through => :relationships, :source => :followed
has_many :subscribed, class_name: "Relationship", foreign_key: "follower_id"
Post Model
scope :subscribed, ->(following) { where user_id: following }
Relationships Model
class Relationship < ActiveRecord::Base
belongs_to :follower, class_name: "User"
belongs_to :followed, class_name: "User"
validates :follower_id, presence: true
validates :followed_id, presence: true
has_many :followed_users, through: :relationships, source: :followed
#fields id | user_id | follower_id | created_at | updated_at
belongs_to :user
end
Stream Controller
class StreamController < ApplicationController
def index
#posts = Post.subscribed current_user.following
end
end
Stream Index
<div class="page-header">
<center><strong><h1> Stream Page </h1></strong></center>
</div>
<div id="posts" class="transitions-enabled">
<% #posts.each do |post| %>
<div class="box panel panel-default">
<%= link_to image_tag(post.image.url(:medium)), post %>
<div class="panel-body">
<%= post.description %><br/>
<strong><%= post.user.name if post.user %></strong>
<% end %>
</div>
<% end %>
</div>
<% end %>
</div>

The problem will be with the association you're calling
--
Associations
You're using my code (which is great!!) - I think the problem will be how you're calling the relationship association data
You'll be able to do this:
#app/controllers/posts_controller.rb
Class PostsController < ApplicationController
#posts = Post.subscribed current_user.followed
end

Related

Self-Referential Relationship for Record will only Create Relationship with Itself

I am attempting to create a method by which a user may attach related records to an existing records similar to how a user may follow other users. However, when the method is called, a relationship can only be made between the record and itself. I have based my code on a follower/following model and I believe the issue is arising because the method is unable to differentiate between the current record and the record being selected to create a relationship with. Any ideas how this may be addressed? Relevant code is below...
Model
class Ingref < ApplicationRecord
has_many :active_relationships, class_name: "Ingrelationship",
foreign_key: "child_id",
dependent: :destroy
has_many :passive_relationships, class_name: "Ingrelationship",
foreign_key: "parent_id",
dependent: :destroy
has_many :children, through: :active_relationships, source: :parent
has_many :parents, through: :passive_relationships, source: :child
# Follows a user.
def follow(other_ingref)
children << other_ingref
end
# Unfollows a user.
def unfollow(other_ingref)
children.delete(other_ingref)
end
# Returns true if the current user is following the other user.
def following?(other_ingref)
children.include?(other_ingref)
end
end
Relationship Controller
class IngrelationshipsController < ApplicationController
before_action :set_search
def create
ingref = Ingref.find(params[:parent_id])
ingref.follow(ingref)
redirect_to ingref
end
def destroy
ingref = Ingrelationship.find(params[:id]).parent
#ingref.unfollow(ingref)
redirect_to ingref
end
end
Relationship Model
class Ingrelationship < ApplicationRecord
belongs_to :child, class_name: "Ingref"
belongs_to :parent, class_name: "Ingref"
end
Form
<% Ingref.find_each do |ingref| %>
<div class="col-md-2">
<div class="caption">
<h3 class="title" style="font-size: 14px;"> <%= ingref.name %> </h3>
<%= form_for(#ingref.active_relationships.build) do |f| %>
<div><%= hidden_field_tag :parent_id, ingref.id %></div>
<%= f.submit "Follow" %>
<% end %>
</div>
</div>
<% end %>
I found that the issue outlined above arose due to a child not being defined in the child-parent relationship between two records in the self referential relationship. by adding the following lines in the form and controller respectively I was able to define this variable and create the desired relationships.
Form
<%= hidden_field_tag :child_id, #ingref.id %>
Controller
current_ingref = Ingref.find(params[:child_id])

Using a Many-to-Many Relationship with the Public Activity gem in Rails

I have the scenario where an author has and belongs to many books, vice versa. Following the instructions for setting up associations in a one-to-many relationship works fine but when a many-to-many relationship introduced I get this error message whenever I try to create or update my book model.
undefined method `author' for #<Book:0x007fb91ae56a70>
As far as setting up how authors are chosen for a book I'm using the code provided by the token-input railscast here with a few alterations.
class Author < ActiveRecord::Base
has_many :authorships
has_many :books, through: :authorships
def self.tokens(query)
authors = where("name like ?", "%#{query}%")
if authors.empty?
[{id: "<<<#{query}>>>", name: "Add New Author: \"#{query}\""}]
else
authors
end
end
def self.ids_from_tokens(tokens)
tokens.gsub!(/<<<(.+?)>>>/) {create!(name: $1).id}
tokens.split(',')
end
end
class Book < ActiveRecord::Base
attr_reader :author_tokens
include PublicActivity::Model
tracked owner: :author
has_many :authorships
has_many :authors, through: :authorships
def author_tokens=(ids)
self.author_ids = Author.ids_from_tokens(ids)
end
end
Form View
<%= form_for(#book) do |f| %>
...
<div class="field">
<%= f.text_field :author_tokens, label: 'Author', input_html: {"data-pre" => #book.authors.to_json} %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
There is no author relationship in your Book model.
What
tracked owner: :author
does is basically calling method author on your Book instance. You should try :authors
But!
That won't solve your problem because owner can only be one. So you can do something like:
tracked owner: proc {|_, book| book.authors.first }
to set the owner to the first author the book has.
class Author < ActiveRecord::Base
has_many :author_books, inverse_of: :author, dependent: :destroy
accepts_nested_attributes_for :author_books
has_many :books, through: :author_books
end
class Book < ActiveRecord::Base
has_many :author_books, inverse_of: :book, dependent: :destroy
accepts_nested_attributes_for :author_books
has_many :authors, through: :author_books
end
class AuthorBook < ActiveRecord::Base
validates_presence_of :book, :author
end
============= view ==============
<%= form_for #book do |f| %>
<%= f.text_field :title %>
<%= f.fields_for :author_books do |f2| %>
<%# will look through all author_books in the form builder.. %>
<%= f2.fields_for :author do |f3| %>
<%= f3.text_field :name %>
<% end %>
<% end %>
<% end %>

Rails - Returning list of incorrect ids

I have an app including Dog, Events and Booking models. Each event has many bookings, each dog has many bookings but each booking belong to an event and has one dog.
On the view for Events it should list all bookings with that id and the details of the linked dog.
I was having a lot of trouble with "Rails Error: undefined method ` ' for nil:NilClass" but then realised the problem was that it is retrieving a list of dogs based on the booking id and not the dog_id field.
In the console I can see that this is the SQL query being generated and what I think is the source of the error but I can't figure out why:
SELECT "dogs".* FROM "dogs" INNER JOIN "bookings" ON "dogs"."id" = "bookings"."id" WHERE "bookings"."event_id" = ? [["event_id", 1]]
I've spent days combing Stack Overflow and Google to figure out where I've gone wrong but am a bit lost. Here are the models:
class Event < ActiveRecord::Base
has_many :bookings
has_many :dogs, :through => :bookings, :foreign_key => "dog_id"
end
class Dog < ActiveRecord::Base
validates :name, presence: true, length: { maximum: 255 }
validates :breed, presence: true, length: { maximum: 255 }
belongs_to :owner
validates :owner_id, presence: true
has_many :bookings
has_many :events, through: :bookings, :foreign_key => "event_id"
end
class Booking < ActiveRecord::Base
belongs_to :event
has_one :dog, :foreign_key => "id"
validates :event_id, presence: true
validates :dog_id, presence: true
end
The controllers
class EventsController < ApplicationController
before_action :logged_in_user
def index
#events = Event.paginate(page: params[:page])
end
def show
#event = Event.find(params[:id])
#bookings = #event.bookings.paginate(page: params[:page])
...
class DogsController < ApplicationController
def show
#dog = Dog.find(params[:id])
end
def new
#dog = Dog.new
end
...
class BookingsController < ApplicationController
end
And finally the show view for Events and the _booking partial it renders:
<% provide(:title, #event.name) %>
<div class="row">
<aside class="col-md-4">
<section class="event_info">
<h1><%= #event.name %></h1> - <%= #event.category %>
<span><b><%= #event.date %></b> <%= #event.start %> - <%= #event.finish %> </span>
<span><b>Location:</b> <%= #event.location %></span>
<%-# Calculated occupany figure goes in line below. -%>
<span><b>Capacity: </b>X / <%=#event.capacity %></span>
</section>
</aside>
<div class="col-md-8">
<section class="event_notes_header">
Description
</section>
<section class="event_notes_body">
<%= #event.description %>
</section>
<section class="event_notes_header">
Notes
</section>
<section class="event_notes_body">
Event notes will be displayed here...
</section>
</div>
<div class="col-md-8">
<% if #event.bookings.any? %>
<h3>Bookings (<%= #event.bookings.count %>)</h3>
<ol class="bookings">
<%= render #bookings %>
</ol>
<%= will_paginate #bookings %>
<% end %>
</div>
</div>
_booking.html.erb
<li id="booking<%= booking.id %>">
<span class="event"><%= link_to booking.event.name, booking.event %></span>
<span class="dog"><%= link_to booking.dog.name, booking.dog %></span>
</li>
Apologies if I've missed anything or if the code has gotten a little convoluted - this is where I am after several days of plugging stuff in and out to try and fix this error.
The first problem I see here is in your associations (and I believe it's the main reason this crap is happening). Your Booking model is a typical joining model for a has_many :through association. But the inner associations are not set properly. If you look at the association between Dog and Booking, you'll notice that there are two has_* paths and no belongs_to path (wich needs to be on the model, that has the dog_id in it, in this case the Booking model).
So your first step is to set the associations properly. You should change
has_one :dog, :foreign_key => "id"
to
belongs_to :dog
Second thing I recommend you do with those associations is getting rid of those foreign_key calls, that might just confuse you and are not needed as long as you're folowing conventions.

How to create a new nested resource?

A users can have many favorites top_songs,top_movies through songs and movies table.
A user registered user(current_user) want to post his favorites movies and songs.
Perhaps all Model association are right, i am stuck in controller and view (form).
When i submit from, i gets errors-
Can't mass-assign protected attributes: songs
How can i achieve this please?
all codes are below.
User Model
class User < ActiveRecord::Base
attr_accessible :id, :name_special_char, :screenname, :fullname, :username, :prefix, :firstname, :lastname,:middlename, :suffix, :age, :sex, :email,
:top_movies_attributes,:top_songs_attributes
has_many :top_movies
has_many :movies, through: :top_movies
has_many :top_songs
has_many :songs, through: :top_songs
accepts_nested_attributes_for :top_songs, :allow_destroy => true
accepts_nested_attributes_for :top_movies, :allow_destroy => true
end
Movie Model
class Movie < ActiveRecord::Base
attr_accessible :name
has_many :top_movies
has_many :users, through: :top_movies
end
TopMovie Model
class TopMovie < ActiveRecord::Base
belongs_to :user
belongs_to :movie
# attr_accessible :title, :body
end
Song Model
class Song < ActiveRecord::Base
attr_accessible :name
has_many :top_songs
has_many :users, through: :top_songs
end
TopSong Model
class TopSong < ActiveRecord::Base
belongs_to :user
belongs_to :song
# attr_accessible :title, :body
end
Controller
class MyTopFivesController < ApplicationController
def new
#favorites = current_user
#favorites=#favorites.movies.build()
#favorites=#favorites.songs.build()
respond_to do |format|
format.html # new.html.erb
format.json { render json: #useraccounts_my_top_fife }
end
end
def create
#favorites = current_user(params[:user])
#favorites.save!
# Here i have stuck. i am not sure how to save.
end
view form
<%=nested_form_for #favorites ,:url=>favorites_path(#favorites),:method=>'post' do |f| %>
<label >Songs</label>
<%= f.fields_for :songs do |songs| %>
<div id="Topsongs" >
<div class="input-control text span5 place-left ">
<%= songs.text_field :name,:placeholder=>"songs name.." %>
</div>
<div class="span1 place-left">
<%= songs.link_to_remove "", :class=>"icon-minus" %>
</div>
</div>
<% end %>
<span >
<%= f.link_to_add "", :songs, :class=>"icon-plus", :data => { :target => "#Topsongs" } %>
</span>
<label >movies</label>
<%= f.fields_for :movies do |movies| %>
<div id="Topmovies">
<div class="input-control text span5 place-left ">
<%= movies.text_field :name,:placeholder=>"movies name.." %>
</div>
<div class="span1 place-left">
<%= movies.link_to_remove "", :class=>"icon-minus" %>
</div>
</div>
<% end %>
<span>
<%= f.link_to_add "", :movies, :class=>"icon-plus",:style=>"font-size: 14px;", :data => { :target => "#Topmovies" } %>
</span>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
There are two options for setting up the associations here. One you have used by creating two join models for top songs and top movies. And other, to use polymorphic association.
Lets use polymorphic association. We are going to use User, Movie, Song and Favourite models for this stuff. The Favourite model will contain the polymorphic fields.
User.rb
class User < ActiveRecord::Base
attr_accessible :id, :name_special_char, :screenname, :fullname, :username, :prefix, :firstname, :lastname,:middlename, :suffix, :age, :sex, :email
has_many :favourites
has_many :movies, through: :favourites, source: :favouritable, source_type: 'Movie'
has_many :songs, through: :favourites, source: :favouritable, source_type: 'Song'
end
Movie.rb
class Movie < ActiveRecord::Base
attr_accessible :name
has_many :favourites, as: :favouritable
has_many :users, through: :favourites
end
Song.rb
class Song < ActiveRecord::Base
attr_accessible :name
has_many :favourites, as: :favouritable
has_many :users, through: :favourites
end
Favourite.rb
class Favourite < ActiveRecord::Base
belongs_to :users
belongs_to :favouritable, polymorphic: true
end
We also need to create the migration for new model "Favourite". As of now, we just need 3 columns ie. user_id, favouritable_id, favouritable_type. Here favouritable_type and favouritable_id are the polymorphic fields. favouritable_type is a string and favouritable_id is reference type.
Migration File
class CreateFavourites < ActiveRecord::Migration
def change
create_table :favourites do |t|
t.integer :user_id
t.references :favouritable, polymorphic: true
t.timestamps
end
end
end
Now, as we are going to mark some movies and songs to be favourite for a user, then we can place the code for building the data in UsersController instead of creating another controller or we can also create a controller for Favourites. I am going to use UsersController here. I am using update action to update the favourites as we don't need any extra functionality here. You can add a new action if you want.
In UsersController.rb
def edit_favourites #or some generic name
#user = current_user.includes(:movies, :songs)
#movies = Movie.all
#songs = Song.all
end
def update
#user = User.find(params[:id])
if #user.update_attributes(params[:user])
redirect_to users_path #user index page
else
if params[:user][:movie_ids].present? or params[:user][:song_ids].present?
render :edit_favourites
else
render :edit
end
end
end
edit_favourites.html.erb
<%= form_for(#user) do |f| %>
<div class="fields">
<%= f.label :movie_ids, "Favourite Movies: " %>
<%= f.collection_select :movie_ids, #movies, :id, :name, {}, multiple: true %>
</div>
<div class="fields">
<%= f.label :song_ids, "Favourite Songs: " %>
<%= f.collection_select :song_ids, #songs, :id, :name, {}, multiple: true %>
</div>
<% end %>
Also, Add the new action to routes.

Rails: How do I create a controller for a has_many :through using a join model?

I have two models "Stores" and "Vendors". I created a separate join model called "Partnerships" so a store can have many vendors and the Vendor can have many stores. When the user is logged in they are affiliated to either a store or vendor. I want them to be able to create partnerships. I think I have the model down based on my research, but I can't seem to get the controller right. Most of the online examples only show the models not the controller.
class Store < ActiveRecord::Base
attr_accessible :industry, :name
has_many :users
has_many :workorders
has_many :locations
has_many :partnerships
has_many :vendors, :through => :partnerships
class Vendor < ActiveRecord::Base
attr_accessible :industry, :name
has_many :users
has_many :workorders
has_many :locations
has_many :partnerships
has_many :stores, :through => :partnerships
class Partnership < ActiveRecord::Base
belongs_to :store
belongs_to :vendor
attr_accessible :store_id, :vendor_id, :store, :vendor
This is my current partnerships_controller#new where I get a type mismatch error during my test.
if params[:store_id]
#store = Store.where(:id => params[:store_id])
#partnership = Partnership.new(store: #store)
else
flash[:error] = "Store partnership required"
end
Here is my new.html.erb for Partnerships:
<% if flash[:error] %>
Not found.
<% else %>
<% if current_user.affiliation == 'Vendor' %>
<div class="page-header">
<h1> <%= #store.name %></h1>
</div>
<% else %>
<div class="page-header">
<h1> <%= #vendor.name %></h1>
</div>
<% end %>
<% end %>
My User model includes an affiliation field that is either "Store" or "Vendor" and also a company_id field.
What would my controller look like to create a new partnership if I am a user whose affiliation = 'Store'? Would I do it in the partnership controller?

Resources