Comment section not displaying - ruby-on-rails

I am working on my first rails application and I am attempting to add a comment section. The comments will fall under each topic. I am seeing comments that are being generated but I am not able to get it configured so that I can input my own comments. I will list below the changes I have made to my code as instructed by my assignment.
Heres a change to my app/models/comment.rb
class Comment < ActiveRecord::Base
belongs_to :post
belongs_to :user
validates :body, length: { minimum: 5 }
validates :body, presence: true
validates :user_id, presence: true
end
Heres my app/models/user.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :confirmable
has_many :posts
has_many :comments
mount_uploader :avatar, AvatarUploader
def admin?
role == 'admin'
end
def moderator?
role == 'moderator'
end
end
I have to also update db/seeds.rb
# Create Comments
100.times do
Comment.create!(
# user: users.sample, # we have not yet associated Users with Comments
post: posts.sample,
user: users.sample,
body: Faker::Lorem.paragraph
)
end
Updated my config/routes.rb
resources :comments, only: [:create]
Updated my app/controllers/comments_controller.rb
class CommentsController < ApplicationController
def create
#post = Post.find(params[:post_id])
#comment = current_user.comments.new(comment_params)
#comment.post = #post
#new_comment = Comment.new
authorize #comment
end
end
The final adjustments I made was to app/views/comments/_form.html.erb
<% if current_user %>
<h4>Add a comment:</h4>
<%= form_for [#post, #post.comments.build], remote: true do |f| %>
<%= f.label :body %>
<%= f.text_field :body %>
<%= f.submit %>
<% end %>
<% end %>
I hope that this is sufficient enough for some type of a response as to what I may be missing. I do not get an error, the box that I am looking for to create a comment just does not appear. Here is an example of what I am trying to accomplish:
http://oi62.tinypic.com/f35h5y.jpg
edit:
Here is the app/views/posts/show.html.erb
<h1><%= markdown #post.title %></h1>
<div class="row">
<div class="col-md-8">
<small>
<%= image_tag(#post.user.avatar.tiny.url) if #post.user.avatar? %>
submitted <%= time_ago_in_words(#post.created_at) %> ago by
<%= #post.user.name %>
</small>
<p><%= markdown #post.body %></p>
<p><%= image_tag(#post.image_url) if #post.image? %></p>
</div>
<div class="col-md-4">
<% if policy(#post).edit? %>
<%= link_to "Edit", edit_topic_post_path(#topic, #post), class: 'btn btn-success' %>
<% end %>
</div>
</div>

Related

Nested fields in form is not rendering

Im new to ruby on rails so i need some tips please.
Im trying to render some checkboxes on the edit view for a user.
I have tried to follow the documentation for the nested_attributes but the checkboes does not render.
Here is the relation between the two models:
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_many :softwares
has_many :courses
accepts_nested_attributes_for :softwares
accepts_nested_attributes_for :courses
The Edit view for a user
<div class="container">
<div class="row">
<div class="col-md-12 mt-5">
<%= form_for #student, url: auth_student_path(#student), method: :put do |f| %>
<div class="col-md-12 mb-5 mt-5">
<div class="row">
<h3 class="mb-3 filter_heading">Softwares</h3>
<% #softwares.each do |sf|%>
<%= f.fields_for :softwares do |software| %>
<div class="col-md-3">
<div class="courses">
<%= software.label sf.title %>
<%= software.check_box :title, {multiple: true}, sf.title, nil %>
</div>
<% sf.courses.each do |crs|%>
<%= f.fields_for :courses do |course|%>
<div class="mt-1 courses-checkbox">
<%= course.label crs.name %>
<%= course.check_box :name, {multiple: true}, crs.name , nil %>
</div>
<% end %>
<% end%>
</div>
<% end %>
<% end%>
</div>
<div class="form-group">
<%= f.submit "Save", class:"btn btn-primary"%>
</div>
<% end %>
</div>
</div>
</div>
The Controller
module Auth
class StudentsController < ApplicationController
before_action :authenticate_user!
before_action :set_student, only: %i[delete_certificates]
def edit
authorize! :edit, #user
#softwares = Software.all
#student = User.find(params[:id])
end
def update
authorize! :update, #user
#student = User.find(params[:id])
if #student.update(student_params)
redirect_to edit_auth_student_path(#student)
else
redirect_to edit_auth_student_path(#student)
end
end
def show
def set_student
#student = User.find(params[:student_id])
end
private
def student_params
params.require(:user).permit(
:email,
:firstname,
:lastname,
:phone,
:locked,
:approved,
:role,
badges: [],
certificates: [],
softwares_attributes: [:title],
courses_attributes: [:name],
)
end
end
end
Please help me.
You don't need accepts_nested_attributes_for just to select existing records and associate them with something. Its only needed if you need to create/update the other record (the course or software) at the same time.
I'm also guessing you don't actually want to have a one-to-many assocation and duplicate every course and every software for each user - instead you want a many to many assocation and some data normalization.
So create a join table to hold the assocation between users and courses for example:
class User < ApplicationRecord
has_many :enrollments, foreign_key: :student_id
has_many :courses, through: :enrollments
end
# rails g model enrollment student:belongs_to course:belongs_to
class Enrollment < ApplicationRecord
belongs_to :student, class_name: 'User'
belongs_to :course
end
class Course < ApplicationRecord
has_many :enrollments
has_many :students, through: :enrollments
end
And then you just create inputs that use the course_ids / course_ids= setter and getter created by has_many :courses, through: :enrollments.
<%= form_with(model: #student, url: auth_student_path(#student), method: :put) do |f| %>
<div class="field">
<%= f.label :course_ids, 'Select your courses' %>
<%= f.collection_select :course_ids, #courses, :id, :name, multiple: true %>
</div>
# ...
<% end %>
And then you just whitelist an array of ids in your controller:
params.require(:user)
.permit(
# ...
course_ids: []
)
In fact if your ever passing existing records as anything but an ID you're doing it very wrong.
There are still plenty of issues with this code but this should at least be nudge in the correct direction.

Cocoon Gem not displaying form - rails 4

I am unsure why my cocoon nested form is not appearing and any help would be much appreciated
the <button><%= link_to_add_association 'add a required skill', f, :requiredskills %></button> works perfectly well in displaying a form
but i am unsure why this is not rendering the form <%= render 'requiredskill_fields', :f => duty %>
what i would like to do is to have a form already displayed and when a user clicks add a required skill another form is displayed.
At present when a user clicks add a required skill that displays
another form - the main issue is having a form to be displayed
initially. I am assuming this <%= render 'requiredskill_fields', :f
=> duty %> is suppose to put a form in place but i am unsure why it is not working
user/_form.html.erb
<%= simple_form_for(#user) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :firstname %>
<%= f.input :lastname %>
<h3>required skills & expertise</h3>
<div>
<div class="requiredskill_info" id="skill">
<%= f.simple_fields_for :requiredskills do |skill| %>
<%= render 'requiredskill_fields', :f => skill %>
<% end %>
<div class="add_requiredskill"><button><%= link_to_add_association 'add a required skill', f, :requiredskills %></button></div>
</div>
</div>
</div>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
user/_requiredskill_fields.html.erb
<div class="nested-fields">
<%= f.association :category_advert, collection: CategoryAdvert.all, prompt: "select a category" %>
<%= f.grouped_collection_select :category_advertskill_id, CategoryAdvert.order(:name), :category_advertskills, :name, :id, :name, {prompt: "Select a category"}, {class: "category_advertskill"} %>
<button><%= link_to_remove_association 'remove required skill', f %></button>
</div>
users_controller.rb
class UsersController < ApplicationController
respond_to :html, :xml, :json
before_action :set_user, only: [:show, :edit, :update, :destroy]
def index
#users = User.all
#user = current_user
end
def show
#resume = #user.resume
end
def edit
end
def update
#user.update(user_params)
redirect_to #user
end
private
def set_user
#user = User.find(params[:id])
end
def user_params
params.require(:user).permit(:email, :firstname, :lastname, :city, :category_qualification_id, :category_careerlevel_id, :desiredjob, :category_distance_id, :preferedlocation, :category_notice_id, :category_country_id, :category_positiontype_id, :image, :cvattachment, :hidecv, :jobadvice, :validlicense, :owntransport, :considerrelocation, :preferredlocation, :neednotice, :stratdate, :availabletowork, :category_outsource_id, :category_advertskill_id, :category_age_id, languages_attributes: [:id, :name, :_destroy], requiredskills_attributes: [:id, :name, :category_advert_id, :category_advertskill_id, :category_year_id, :category_level_id, :_destroy])
end
end
user.rb
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 :requiredskills
has_many :category_advertskills, through: :requiredskills
has_many :category_adverts, through: :requiredskills
has_one :resume
accepts_nested_attributes_for :languages, :reject_if => :all_blank, :allow_destroy => true
accepts_nested_attributes_for :requiredskills, :reject_if => :all_blank, :allow_destroy => true
end
def edit
#requiredskills = #user.requiredskills.present? ? #user.requiredskills : #user.requiredskills.build
end
change this code in controller

Rating for the teacher doesn't show up after the user logged in and rated

In my rails project, a user can only rate his teacher if he already signed up and logged in. However, after the user logged in and rated the teacher, I couldn't see his rating. I don't know what cause the problem. Any suggestions would be appreciated.
Here is my ratings_controller.rb:
class RatingsController < ApplicationController
before_action :authenticate_user!
before_action :get_teacher
def new
get_teacher
#rating = current_user.ratings.build
end
def create
get_teacher
#rating = current_user.ratings.create(rating_params)
if #rating.save
redirect_to school_teacher_path(#teacher.school, #teacher)
else
render 'new'
end
end
def destroy
get_teacher
#rating = #teacher.ratings.find(params[:id])
#rating.destroy
redirect_to school_teacher_path(#teacher.school, #teacher)
end
def get_teacher
#teacher = Teacher.find(params[:teacher_id])
end
private
def rating_params
params.require(:rating).permit(:easiness, :helpfulness, :clarity, :comment,
:teacher_id, :school_id)
end
end
teachers/show.html.erb:
<!-- Caculate the average rating of the teacher -->
<h1>Average ratings:</h1>
<p>Clarity:
<%= #teacher.ratings.average(:clarity) %>
</p>
<p>Easiness:
<%= #teacher.ratings.average(:easiness) %>
</p>
<p>Helpfulness:
<%= #teacher.ratings.average(:helpfulness) %>
</p>
<hr>
<!-- Show all the ratings -->
<h2>All the ratings:</h2>
<div>
<%= #teacher.ratings.each do |rating| %>
<p>Clarity:
<%= rating.clarity %>
</p>
<p>Helpfulness:
<%= rating.helpfulness %>
</p>
<p>Easiness:
<%= rating.easiness %>
</p>
<p>Comment:
<%= rating.comment %>
</p>
<%= link_to "Delete rating", [rating.teacher, rating], method: :delete, data: { confirm: 'Are you sure?' }, class: "btn btn-warning" %>
<hr>
<% end %>
</div>
<p>
<%= link_to "Rate teacher", new_teacher_rating_path(#teacher), class: "btn btn-primary" %>
</p>
<p>
<%= link_to "Back to school", school_path(#school), class: "btn btn-primary" %>
</p>
ratings/new.html.erb:
<h1>Teacher Rating</h1>
<%= form_for([#teacher, #rating]) do |f| %>
<p>
<%= f.label :clarity %>
<%= f.text_field :clarity %>
</p>
<p>
<%= f.label :easiness %>
<%= f.text_field :easiness %>
</p>
<p>
<%= f.label :helpfulness %>
<%= f.text_field :helpfulness %>
</p>
<p>
<%= f.label :comment %>
<br>
<%= f.text_area :comment %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
rating.rb:
class Rating < ActiveRecord::Base
belongs_to :teacher
belongs_to :user
end
user.rb:
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 :ratings
has_many :teachers
end
teacher.rb:
class Teacher < ActiveRecord::Base
belongs_to :school
has_many :ratings, dependent: :destroy
has_many :users
def name
"#{firstName} #{middleName} #{lastName}"
end
def to_s
name
end
end
I think your problem is rating, not associated with user. You can use build method, it will add user_id to rating automatically,
#rating = current_user.ratings.build(rating_params)
and you not associating teacher id,
#rating.teacher_id = #teacher.id
And your the relation between user and teacher, both has has_many it's incorrect syntax, you should use has_and_belongs_to_many. I'm not sure about your database schema, If you have ratings as relation in between user and teachers you can use 'has_many through:', as suggested below
user.rb:
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 :ratings
has_many :teachers, through: :ratings
end
teacher.rb:
class Teacher < ActiveRecord::Base
belongs_to :school
has_many :ratings, dependent: :destroy
has_many :users, through: :ratings
def name
"#{firstName} #{middleName} #{lastName}"
end
def to_s
name
end
end

Using form_for to add a user to Collaboration model

I'm building a very basic wiki-style app that uses 3 models: User, Wiki, and Collaboration. My goal is, via the edit wiki page, a user should be able to add another user to the wiki as a "collaborator". This is what I have so far:
Wiki Model
class Wiki < ActiveRecord::Base
belongs_to :user
has_many :collaborations
has_many :collaboration_users, through: :collaborations, :source => :user
scope :visible_to, -> (user) { user.role == 'admin' || user.role == 'premium' ? all : where(private: false) }
end
User Model
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :confirmable
has_many :wikis
has_many :collaborations
has_many :collaboration_wikis, through: :collaborations, :source => :wiki
after_initialize :set_default_role
def set_default_role
self.role ||= 'standard'
end
def upgrade_to_premium
self.update_attribute(:role, "premium")
end
def admin?
role == 'admin'
end
def standard?
role == 'standard'
end
def premium?
role == 'premium'
end
end
Collaboration Model
class Collaboration < ActiveRecord::Base
belongs_to :user
belongs_to :wiki
end
My _form.html.erb
<%= form_for wiki do |f| %>
<% if wiki.errors.any? %>
<div class="alert alert-danger">
<h4>There are <%= pluralize(wiki.errors.count, "error") %>.</h4>
<ul>
<% wiki.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= form_group_tag(wiki.errors[:title]) do %>
<%= f.label :title %>
<%= f.text_field :title, class:'form-control', placeholder: "Enter Wiki name" %>
<% end %>
<div class="form-group">
<%= f.label :body %>
<%= f.text_area :body, rows: 8, class:'form-control', placeholder: "Enter Wiki body" %>
</div>
<% if current_user.role == 'premium' || current_user.role == 'admin' %>
<div class="form-group">
<%= f.label :private, class: 'checkbox' do %>
<%= f.check_box :private %> Private Wiki
<% end %>
</div>
<% end %>
<%= f.submit "Save", class: 'btn btn-success' %>
<% end %>
My goal is to show a list of all users (if role == premium or admin) with the option to add or delete as a collaborator. Can someone point me in the right direction?
Thank you!
When you add a user to a wiki, as a collaborator, you are creating a collaboration record. You can do this via the "collaboration_user_ids=" method on a wiki: the association gives you this method, among many others.
For example, you could add user 123, and user 456 as a collaborator to wiki 789 by saying
#wiki = Wiki.find(789)
#wiki.collaboration_user_ids = [123, 456]
#wiki.save
This will delete or create collaboration records as appropriate, ie delete any collaborations where wiki_id = 789 and user_id NOT IN (123,456), and create a collaboration for user 123 and user 456, if they don't exist already.
So, now we know that we can set the list of collaborating users just by passing an array of their ids to #wiki.collaboration_user_ids, we just need to set up our form to pass this array through as params[:wiki][:collaboration_user_ids], and we can call #wiki.update_attributes(params[:wiki]) as normal.
You could do this by adding this to your form:
<div class="form-group">
<p>Collaborators</p>
<% collaboration_user_ids = #wiki.collaboration_user_ids %>
<%# this should more properly use a variable set in your controller rather than User.all - for example you might want to limit the list of possible collaborators according to some condition %>
<% User.all.each do |user| %>
<div class="user">
<%= check_box_tag "wiki[collaboration_user_ids][]", user.id, collaboration_user_ids.include?(user.id) %>
<%= user.name %>
</div>
<% end %>
</div>

'merge' error with check_box field in rails

In my Rails app, I need to show user email id's with checkboxes in a form to allocate users to a particular project. I have an array object #programmers and each row in the object contains email id's which I need to show inside the form with checkboxes.
My partial view containing form is:
_allocate_programmer.html.erb
<h1> Allocate programmers </h1>(Please check the programmers that you want to add)<br />
<%= form_for(#project) do |f| %>
<% if #project.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#project.errors.count, "error") %> prohibited this project from being saved:</h2>
<ul>
<% #project.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<% unless #programmers.nil? %>
<% #programmers.each do |programmer| %>
<%= f.check_box :programmer, programmer.email %>
<% end %>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
My routes.rb has:
match 'projects/:id/allocate_programmers' => 'projects#allocate'
My projects_controller.rb has the following code:
def allocate
#project = Project.find(params[:id])
#programmers = User.where(:role => 'programmer')
render "_allocate_programmer"
end
I am getting following error in the view
NoMethodError in Projects#allocate
Showing /home/local/Rajesh/ticket_system/app/views/projects/_allocate_programmer.html.erb where line #18 raised:
undefined method 'merge' for "test#gmail.com":String
I think its an issue with checkbox hash. Please help.
User.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable, :token_authenticatable,
:rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me, :role
# attr_accessible :title, :body
has_many :assignments
has_many :projects, :through => :assignments
has_many :tickets
ROLES = ['admin', 'network/system admin', 'manager', 'programmer']
def role?(base_role)
ROLES.index(base_role.to_s) <= ROLES.index(role)
end
end
Project.rb
class Project < ActiveRecord::Base
attr_accessible :project_name, :description, :duration_from, :duration_upto, :user_id
has_many :assignments
has_many :users, :through => :assignments
validates :project_name, :presence => true
validates :description, :presence => true
validates :duration_from, :presence => true
validates :duration_upto, :presence => true
#validates :user_id, :presence => true //this gives error
end
Assignment.rb
class Assignment < ActiveRecord::Base
attr_accessible :user_id, :project_id
belongs_to :user
belongs_to :project
end
Please check. I have updated the question with 3 models.
Supposing that you have set up your associations correctly.
<% #programmers.each do |programmer| %>
<%= check_box_tag "project[programmer_ids][]", programmer.id, #project.programmers.include?(programmer) %>
<%= programmer.email %>
<% end %>
ref this
check_box does not work when the check box goes within an array-like parameter
Following should work for you
<% #programmers.each do |programmer| %>
<%= check_box_tag "project[programmer]", programmer.email %>
<% end %>

Resources