nested user-specific forms in rails - mysql

I'm attempting to build a nested form for my Devise users to fill out and then later update. The form consists of two models; one for questions and another for users. My controller looks like this:
class LegalFormsController < ApplicationController
before_action :set_legal_form, only: [:show, :edit, :update, :destroy, :answers]
respond_to :html
def index
#legal_forms = LegalForm.all
respond_with(#legal_forms)
end
def show
respond_with(#legal_form)
end
def new
#legal_form = LegalForm.new
respond_with(#legal_form)
end
def edit
end
def create
#legal_form = LegalForm.new(legal_form_params)
#legal_form.save
respond_with(#legal_form)
end
def update
#legal_form.update(legal_form_params)
respond_with(#legal_form)
end
def destroy
#legal_form.destroy
respond_with(#legal_form)
end
def answers
#users = User.all
#questions = #legal_form.questions
end
private
def set_legal_form
#legal_form = LegalForm.find(params[:id])
end
def legal_form_params
params.require(:legal_form).permit(:name,
:questions_attributes => [:id, :content,
:answers_attributes =>[:id, :content, :participant_id]
])
end
end
and the view for the answers is (currently) as follows:
<h1><%= #legal_form.name %> Answers</h1>
<%= form_for(#legal_form) do |f| %>
<% #users.each do |user| -%>
<h3><%= user.id %></h3>
<table>
<thead>
<tr>
<td>Questions</td>
<td>Answer</td>
</tr>
<tbody>
<% #questions.each do |question| -%>
<tr>
<td><%= question.content %></td>
<td>
<%= f.fields_for :questions, question do |q| -%>
<%=q.fields_for :answers, question.answers.find_or_initialize_by(user: #user) do |a| -%>
<%= a.text_area :content %>
<%= a.hidden_field :user_id, :value => current_user %>
<% end -%>
<% end -%>
</td>
</tr>
<% end -%>
</tbody>
</table>
<% end -%>
<div class="actions">
<%= f.submit %>
</div>
<% end =%>
As you can see, this currently brings up all questions/answers for all users.
My question is two-fold:
How might I set this up to just bring up the current user?
Using this line <%= a.hidden_field :user_id, :value => current_user %>, I am attempting to provide the current user id for each answer saved to the answers database under user_id. However, it doesn't seem to be working. What might I be missing?
Many thanks for any help on this!
As requested, below are my model associations
class Answer < ActiveRecord::Base
belongs_to :question
belongs_to :user
end
class LegalForm < ActiveRecord::Base
has_many :questions
accepts_nested_attributes_for :questions
end
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :answers
has_many :questions, through: :answers
end
class Question < ActiveRecord::Base
belongs_to :legal_form
has_many :answers
has_many :users, through: :answers
accepts_nested_attributes_for :answers
end

You can set user_id value like this
<%= f.hidden_field :user_id, value: current_user.id %>

Related

uninitialized constant User::follow Extracted source (around line #28):

i have an error in my user.rb model (around line #28):
27def following?(user)
28 following.include?(user)
29end
Any idea what I could be doing wrong here?
Showing C:/instagramm/instagram-clone/app/views/accounts/profile.html.erb where line #11 raised:
my profile.html.erb :
<% if #users.image.present %>
<%= image_tag #users.image %>
<% end %>
<strong><h1><%= #users.full_name %></h1></strong>
<% if user_signed_in? && #user == current_user %>
<%= link_to"Edit Profile", edit_user_registration_path(#user) %>
<% if current_user.following?(#user) %>
<%= link_to"Unfollow", follows_path(user_id: #user.id), method: :delete %>
<% else %>
<%= link_to"Follow", follows_path(user_id: #user.id) %>
<% end %>
<% end %>
<div> <%= #users.posts.count %> Posts </div>
<p><%= #users.full_name %></p>
<p><%= #users.description %></p>
<p><%= link_to 'User Website', #users.website if #users.website.present? %></p>
<%= #posts.each do |post|%>
<%= image_tag post.image %>
<% end %>
my model : follow.rb
class Follow < ApplicationRecord
belongs_to :follower, class_name: 'user'
belongs_to :followed, class_name: 'user'
validates :follower_id, presence: true
validates :followed_id, presence: true
end
and this is my user.rb model : the error is around(#line28) in def following?(user)
class User < ApplicationRecord
has_many :posts
validates :username, presence: true
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_one_attached :image
has_many :active_follows, class_name: "follow", foreign_key: "follower_id", dependent: :destroy
has_many :passive_follows, class_name: "follow", foreign_key: "followed_id", dependent: :destroy
has_many :following, through: :active_follows, source: :followed
has_many :followers, through: :passive_follows, source: :follower
def follow(user)
active_follows.create(followed_id: user.id)
end
def unfollow(user)
active_follows.find_by(followed_id: user.id).destroy
end
def following?(user)
following.include?(user)
end
def full_name
"#{first_name} #{last_name}"
end
end
Rails assumes that association points to a class with matching name, so in this case your following association will search for Following class.
Obviously it is not what you need here - having a quick guess by the code structure that you expect following to return a collection of Users, so you need to tell that to your association:
has_many :following, through: :active_follows, source: :followed, class_name: 'User'
It is also important to use correct class names given to class_name option. It has to match the name of the ActiveRecord class exactly, so it must be "Follow" not "follow" and, similarly, "User" not "user"
You already got response from #BroiStase you are using incorrect name of classes in your code. Please change your Follow.rb
class Follow < ApplicationRecord
belongs_to :follower, class_name: 'User'
belongs_to :followed, class_name: 'User'
validates :follower_id, presence: true
validates :followed_id, presence: true
end
In your User.rb following you have to do following changes.
class User < ApplicationRecord
has_many :posts
validates :username, presence: true
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_one_attached :image
has_many :active_follows, class_name: "Follow", foreign_key: "follower_id", dependent: :destroy
has_many :passive_follows, class_name: "Follow", foreign_key: "followed_id", dependent: :destroy
has_many :following, through: :active_follows, source: :followed
has_many :followers, through: :passive_follows, source: :follower
def follow(user)
active_follows.create(followed_id: user.id)
end
def unfollow(user)
active_follows.find_by(followed_id: user.id).destroy
end
def following?(user)
following.include?(user)
end
def full_name
"#{first_name} #{last_name}"
end
end
Please when you code avoid any extra spaces, line breaks and give proper 2 space indentions it will help you to understand code better. If still error please share error message also.

How to show all the Users who have liked my post

I apologize for the newbie questions still relatively new to rails. I'm trying to show all the users who have liked my specific posts. I took a look at this similar question How to list the users who LIKE a given Post but it couldn't solve my problem. I listed below all the relevant simple code - thank you so much guys!!
Items Controller
class ItemsController < ApplicationController
before_action :authenticate_user!, only: [:new, :create]
before_action :set_item, only: [:show, :edit, :update, :destroy, :share]
def index
#items = Item.order("created_at DESC")
end
end
Index.html.erb
<% if user_signed_in? %>
<%= image_tag current_user.avatar, width: 70, class: "css-style" %>
<br>
<strong><%= link_to current_user.username, current_user, class: "profile-style" %></strong>
<ul><!--Trying to show all the users who have liked my specific posts here -->
<% item.likes.each do |like| %>
<li> <%= link_to(like.user.username, like.user) %></li>
<% end %>
</ul>
<br>
<br>
<% else %>
<%= link_to 'Login/SignUp', new_user_session_path %>
<% end %>
<% #items.each do |item| %>
<%= image_tag item.avatar.url(:medium), class: "block" %>
<div>
<%= render partial: "likes", locals: {item: item} %></span><%= item.likes_count %>
</div>
<% end %>
Items.rb
class Item < ApplicationRecord
has_many :likes, :counter_cache => true
belongs_to :user
has_attached_file :avatar, styles: { medium: "300x300>", thumb: "100x100>" }, default_url: "/images/:style/missing.png"
validates_attachment_content_type :avatar, content_type: /\Aimage\/.*\z/
end
User.rb
class User < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :omniauthable, omniauth_providers: [:facebook]
has_many :likes
has_attached_file :avatar, styles: { medium: "300x300>", thumb: "100x100>" }, default_url: "/images/:style/missing.png"
validates_attachment_content_type :avatar, content_type: /\Aimage\/.*\z/
def likes?(post)
post.likes.where(user_id: id).any?
end
end
Users Controller
class UsersController < ApplicationController
before_action :set_user, only: [:show, :edit, :update, :destroy, :share]
def index
#users = User.all
end
def show
#user = User.find(params[:id])
#items = Item.all
end
private
def set_user
#user = User.find(params[:id])
end
def item_params
params.require(:item).permit(:product, :amount, :city_id, :avatar)
end
end
Like.rb
class Like < ApplicationRecord
belongs_to :item, :counter_cache => true
belongs_to :user
end
Likes Controller
class Items::LikesController < ApplicationController
before_action :authenticate_user!
before_action :set_book
def create
#item.likes.where(user_id: current_user.id).first_or_create
respond_to do |format|
format.html {redirect_to #item}
format.js
end
end
def destroy
#item.likes.where(user_id: current_user.id).destroy_all
respond_to do |format|
format.html {redirect_to #item}
format.js
end
end
private
def set_book
#item = Item.find(params[:item_id])
end
end
Logs
Processing by ItemsController#index as HTML
Rendering items/index.html.erb within layouts/application
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ? [["id", 1], ["LIMIT", 1]]
Item Load (0.3ms) SELECT "items".* FROM "items" ORDER BY created_at DESC
Rendered items/index.html.erb within layouts/application (287.6ms)
Completed 500 Internal Server Error in 313ms (ActiveRecord: 0.6ms)
ActionView::Template::Error (undefined local variable or method `item' for #<#:0x007f9afbfd14f0>
Did you mean? item_url
items_url
item_path
#items):
5:
6: <%= link_to current_user.username, current_user, class: "profile-style" %>
7:
8: <% item.likes.each do |like| %>
9: <%= link_to(like.user.username, like.user) %>
10: <% end %>
11:
app/views/items/index.html.erb:8:in `_app_views_items_index_html_erb___2312434021832006771_70151814680620'
Rendering /usr/local/lib/ruby/gems/2.3.0/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb within rescues/layout
Rendering /usr/local/lib/ruby/gems/2.3.0/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/_source.html.erb
Rendered /usr/local/lib/ruby/gems/2.3.0/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/_source.html.erb (8.3ms)
Rendering /usr/local/lib/ruby/gems/2.3.0/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb
Rendered /usr/local/lib/ruby/gems/2.3.0/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (3.3ms)
Rendering /usr/local/lib/ruby/gems/2.3.0/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb
Rendered /usr/local/lib/ruby/gems/2.3.0/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (1.2ms)
Rendered /usr/local/lib/ruby/gems/2.3.0/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb within rescues/layout (94.4ms)
In items/index.html.erb you are referencing #item.likes.each on line 9, but the instance variable #item has not been set in items_controller#index. You have only defined #items, hence the error you are receiving about nil not responding to #likes.
If you want to see the likes for all items, there are a number of ways to achieve this with Arel.
It's a simple mistake. I think the problem is with your partial.. you're calling the partial with locals and inside your template code you are referring to it with #item instead of item, here item is not an instance variable.
<% #items.each do |item| %>
<%= image_tag item.avatar.url(:medium), class: "block" %>
<div>
<%= render partial: "likes", locals: {item: item} %></span><%= item.likes_count %>
</div>
<% end %>
The thing is when you render a partial with locals you need to use the locals as normal variables not as instance variables.
This should work.
<% item.likes.each do |like| %>
<li> <%= link_to(like.user.username, like.user) %></li>
<% end %>
You need one more table(model) "likes" and association has-many-through. Something like this:
class Item
has_many :likes
has_many :users, through: :likes
end
class Like
belongs_to :user
belongs_to :item
end
class User
has_many :likes
has_many :items
has_many :liked_items, through: :likes
end

undefined method `cliq_requests' for nil:NilClass

I keep getting this annoying error consistently and I cannot solve it. I recently posted a question on the same topic and got no productive help.
I want users to request to join a group. Cliqs = Groups. All of my console tests seem correct, but I cannot seem to find a solution to my problem. The association is showing up, but I can't seem to get the update/accept method to run.
This is driving me crazy! How do I fix this?
Here is my code:
My Models:
class User < ActiveRecord::Base
has_many :uploads
has_one :owned_cliq, foreign_key: 'owner_id', class_name: 'Cliq', dependent: :destroy
has_many :cliq_memberships, dependent: :destroy
has_many :cliqs, through: :cliq_memberships
has_many :cliq_requests, dependent: :destroy
...
end
class Cliq < ActiveRecord::Base
belongs_to :owner, class_name: 'User'
has_many :cliq_memberships, dependent: :destroy
has_many :members, through: :cliq_memberships, source: :user
has_many :cliq_requests, dependent: :destroy #cliq_request_sender
has_many :pending_members, through: :cliq_requests, source: :user, foreign_key: 'user_id'
end
class CliqRequest < ActiveRecord::Base
#from
belongs_to :user
#to
belongs_to :cliq
#validate :not_member
#validate :not_pending
def accept
cliq.members << pending_member
destroy
end
end
My controller:
class CliqRequestsController < ApplicationController
def index
#incoming
##cliq_requests_received = CliqRequest.where(cliq: cliq)
#outgoing
##cliq_requests_sent = current_user.cliq_requests
end
def show
end
def create
cliq = Cliq.find_by(params[:id])
#cliq_request = current_user.cliq_requests.new(cliq: cliq)
if #cliq_request.save
redirect_to current_user #change to cliqs/cliq path later
else
redirect_to cliq_path
end
end
def update
#cliq = Cliq.find_by(id: params[:cliq_id])
#cliq_request = #cliq.cliq_requests.find_by(id: params[:id])
#cliq_request.accept
end
def destroy
#cliq_request.destroy
end
end
My View:
<h1><%= #cliq.name %></h1>
<%= link_to 'Request to join Cliq', '/cliqs/:cliq_id/cliq_requests', :method => :post %>
<% #cliq_members.each do |cliq_member| %>
<ul><%= link_to cliq_member.username, user_path(cliq_member) %></ul>
<% end %>
<% if #current_user = #cliq.owner %>
<% #cliq.pending_members.each do |pending_member| %>
<ul><%= link_to pending_member.username, user_path %>
<%= link_to "Accept", "/cliqs/:cliq_id/cliq_requests/:id/", :method => :put %>
<%= link_to "Deny", "/cliqs/:cliq_id/cliq_requests/:id/", :method => :delete %>
</ul>
<% end %>
<% end %>
My Routes:
resources :cliqs do
resources :cliq_requests
end
These lines appear malformed:
<%= link_to 'Request to join Cliq', '/cliqs/:cliq_id/cliq_requests', :method => :post %>
<%= link_to "Accept", "/cliqs/:cliq_id/cliq_requests/:id/", :method => :put %>
<%= link_to "Deny", "/cliqs/:cliq_id/cliq_requests/:id/", :method => :delete %>
I recommend you use path helpers [e.g. cliq_cliq_request_path(cliq, cliq_request) if you are using resourceful routing]. You can use rake routes for help. If you are seeing things like :cliq_id and and :id in your development.log or test.log as part of the URLs that are hit, those should instead be numbers. You can also interpolate the strings yourself (e.g. "/cliqs/#{cliq_id}/cliq_requests/#{cliq_request.id}") but this is usually more typing and certainly more fragile over time.
One of your problems may be that you are looping through a list of pending member names, which doesn't have all the data you need to form the link correctly. So your update action may be working fine, but you may not be passing it the right data.
Also this line:
if #current_user = #cliq.owner
is an assignment, and so will always return true. Presumably you mean ==

Setting up associations and forms for my Quora Like Rails App

Hello I am trying to build a quora like app using ruby on rails. I have decided to call my questions pins in this case, and my answers are still answers. However When I try to answer a question I get this error:
NameError at /pins/2 undefined local variable or method `answer' for #<#<Class:0x007fc934792fc0>:0x007fc93428fb18>
I am using Devise as well. Here is my associations thus far.
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :pins
has_many :answers
has_attached_file :image, :styles => { :medium => "400x400", :thumb => "200x200" }, : :default_url => "avatar/missing.jpg"
validates_attachment_content_type :image, :content_type => /\Aimage\/.*\Z/
end
Here is my Pin Model
class Pin < ActiveRecord::Base
belongs_to :user
validates :description, presence: true
has_many :answers
end
Here is my Answer Model
class Answer < ActiveRecord::Base
belongs_to :pin
belongs_to :user
validates :description, presence: true
end
Here is my Pins Controller
class PinsController < ApplicationController
before_action :set_pin, only: [:show, :edit, :update, :destroy]
before_action :correct_user, only: [:edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
def index
#pins = Pin.all.order("created_at DESC").paginate(:page => params[:page], :per_page => 50)
end
def show
end
def new
#pin = current_user.pins.build
end
def edit
end
def create
#pin = current_user.pins.build(pin_params)
if #pin.save
redirect_to #pin, notice: 'Pin was successfully created.'
else
render action: 'new'
end
end
def update
if #pin.update(pin_params)
redirect_to #pin, notice: 'Pin was successfully updated.'
else
render action: 'edit'
end
end
def destroy
#pin.destroy
redirect_to pins_url
end
private
# Use callbacks to share common setup or constraints between actions.
def set_pin
#pin = Pin.find(params[:id])
end
def correct_user
#pin = current_user.pins.find_by(id: params[:id])
redirect_to pins_path, notice: "Not authorized to edit this pin" if #pin.nil?
end
# Never trust parameters from the scary internet, only allow the white list through.
def pin_params
params.require(:pin).permit(:description)
end
end
and Here is my Answer Controller
class AnswersController < ApplicationController
before_action :set_answer, only: [:show, :edit, :update, :destroy]
before_action :correct_user, only: [:edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
def create
#pin = Pin.find(params[:pin_id])
#answer = #pin.answers.create(answer_params)
redirect_to pin_path(#pin)
end
private
def set_answer
#answer = Answer.find(params[:id])
end
def correct_user
#answer = current_user.answers.find_by(id: params[:id])
redirect_to answers_path, notice: "Not authorized to edit this pin" if #answer.nil?
end
def answer_params
params.require(:answer).permit(:description)
end
end
And Here is my show form
<%= render 'layouts/header' %>
<%= notice %>
<p>
<strong>Description:</strong>
<%= #pin.description %>
</p>
<h2>Answers</h2>
<% #pin.answers.each do |comment| %>
<p>
<strong>Answer:</strong>
<%= answer.description %>
</p>
<% end %>
<h2>Answer this questions:</h2>
<%= form_for([#pin, #pin.answers.build]) do |f| %>
<p>
<%= f.label :description %><br>
<%= f.text_field :description %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
<%= link_to 'Edit', edit_pin_path(#pin) %> |
<%= link_to 'Back', pins_path %>
Could anyone tell me the problem. Thanks in an advance.
You have a mistake in view:
<% #pin.answers.each do |comment| %> # Here you have "comment"
<p>
<strong>Answer:</strong>
<%= answer.description %> # And here "answer", change it to "comment" or vice versa
</p>
<% end %>

Destroy action deleting from wrong table

I have a users model that can have many holidays through a rich join table.. My destroy statement on my view is deleting from the holidays table and NOT the user_holidays table as it should.. see below:
class HolidaysController < ApplicationController
def destroy
#user = User.find(params[:user_id])
#user_holiday = #user.holidays.find(params[:id])
#user_holiday.destroy
redirect_to #user
end
end
Heres the view button:
<% #user.holidays.each do |hld| %>
<td><%= hld.name %></td>
<td><%= hld.date %></td>
<td>
<%= button_to('Destroy', user_holiday_path(#user, hld), :method => 'delete', :class => 'btn btn-large btn-primary') %>
Models:
class User < ActiveRecord::Base
has_many :user_holidays
has_many :holidays, :through => :user_holidays
class UserHoliday < ActiveRecord::Base
attr_accessible :holiday_id, :user_id
belongs_to :user
belongs_to :holiday
class Holiday < ActiveRecord::Base
attr_accessible :name, :date
has_many :user_holidays
has_many :users, :through => :user_holidays
Any ideas? Thanks!!!!
You should use #user.user_holidays instead of #user.holidays
#user_holiday = #user.user_holidays.where(holiday_id: params[:id])
(my bad didn't read you question properly)
#user = User.find(params[:user_id])
#user.holidays.delete(#user.holidays.find(params[:id]))