Rails comments do not save - ruby-on-rails

Edit: Log from form submission:
Started POST "/posts/1/comments" for 141.161.133.10 at 2015-03-19 17:10:19 +0000
Processing by CommentsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"9laIJxseq/x+7C3iJAdpvalFvMgN397lWC7c/6Ha/hEjKTE9A3e19liFlwGzZjePReFdh2F1fLj1itZzRjixgQ==", "comment"=>{"body"=>"Hi stackoverflow"}, "commit"=>"Submit", "post_id"=>"1"}
(0.3ms) begin transaction
SQL (1.9ms) INSERT INTO "comments" ("body", "created_at", "updated_at") VALUES (?, ?, ?) [["body", "Hi stackoverflow"], ["created_at", "2015-03-19 17:10:19.808006"], ["updated_at", "2015-03-19 17:10:19.808006"]]
(32.1ms) commit transaction
Redirected to https://blog-erikvdw.c9.io/posts.10
Completed 302 Found in 48ms (ActiveRecord: 34.2ms)
And comment_params method:
def comment_params
params.require(:comment).permit(:body)
end
I've looked around quite a while in a github repo and other SO questions similar to what I am doing, but haven't seen exactly what I'm doing wrong. My problem is that comments are not being created when the comments form is submitted in Posts/Show. I presume it to be an issue with an activerecord association:
Posts/Show
<% content_for(:title, #post.title ) %>
<p id="notice"><%= notice %></p>
<h1>Blog</h1>
<br>
<div>
<%= image_tag #post.image.full.url %>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h2><em><%= #post.title %></em></h2>
</div>
<div class="panel-body">
<p><%= #post.content %></p>
</div>
</div>
<%= link_to 'Edit', edit_post_path(#post) %> |
<%= link_to 'Back', posts_path %>
<% #post.comments.each do |comment| %>
<%= comment.body %>
<% end %>
<%= form_for [#post, #post.comments.build] do |f| %>
<%= f.text_area :body %>
<%= f.submit "Submit" %>
<% end %>
<p>Comments: <%= #post.comments.count %></p>
Posts Model
class Post < ActiveRecord::Base
has_many :comments, dependent: :destroy
mount_uploader :image, PostUploader
end
Comments Model
class Comment < ActiveRecord::Base
belongs_to :user
belongs_to :post
end
Schema File
create_table "comments", force: :cascade do |t|
t.string "body"
t.integer "user_id"
t.integer "employee_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "post_id"
end
add_index "comments", ["employee_id"], name: "index_comments_on_employee_id"
add_index "comments", ["post_id"], name: "index_comments_on_post_id"
add_index "comments", ["user_id"], name: "index_comments_on_user_id"
create_table "posts", force: :cascade do |t|
t.string "title"
t.text "content"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "image"
end
create_table "users", force: :cascade do |t|
t.string "first_name"
t.string "last_name"
t.string "username"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
end
add_index "users", ["email"], name: "index_users_on_email", unique: true
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
Comments_Controller New and Create Actions
def new
#comment = Comment.new
end
# POST /comments
# POST /comments.json
def create
#comment = Comment.new(comment_params)
respond_to do |format|
if #comment.save
format.html { redirect_to posts_path(#comment), notice: 'Comment was successfully created.' }
format.json { render :show, status: :created, location: #comment }
else
format.html { render :new }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end

You're not creating the Comment through the specific Post, so no association is being made. Try this in your create action:
#comment = Post.find(params[:post_id]).comments.new(comment_params)
This will populate the post_id in your comments table automatically which will then link it to the Post.

Related

Rails- Checkbox not turning true

I've added a checkbox to my Rails project. When the user marks tradeablestatus while creating a book, it should write true, but it is happening false regardless.
books/_form.html.erb
<%= form_with(model: book, local: true) do |form| %>
<% if book.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(book.errors.count, "error") %> prohibited this book from being saved:</h2>
<ul>
<% book.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<p> If you want your book to be available, tick the status and if you want your book to be tradeable, tick the tradeablestatus. </p>
<div class="field">
<%= form.label :title %>
<%= form.text_field :title %>
</div>
<div class="field">
<%= form.label :author %>
<%= form.text_field :author %>
</div>
<div class="field">
<%= form.label :pagecount %>
<%= form.number_field :pagecount %>
</div>
<div class="field">
<%= form.label :status %>
<%= form.check_box :status %>
</div>
<div class="field">
<%= form.label :tradeablestatus %>
<%= form.check_box :tradeablestatus %>
</div>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
tradeablestatus migration (I added the tradeablestatus later as a migration. But I don't know if I should add this to book migration)
class AddTradeableStatusToBooks < ActiveRecord::Migration[6.0]
def change
add_column :books, :tradeablestatus, :boolean
end
end
schema.rb (I suspect it is caused by default: false, null: false)
ActiveRecord::Schema.define(version: 2020_10_28_092816) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "books", force: :cascade do |t|
t.string "title"
t.string "author"
t.integer "pagecount"
t.boolean "status"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.integer "user_id"
t.string "username"
t.boolean "tradeablestatus", default: false, null: false
end
create_table "comments", force: :cascade do |t|
t.string "title"
t.string "content"
t.bigint "user_id", null: false
t.bigint "book_id", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.boolean "status", default: false, null: false
t.index ["book_id"], name: "index_comments_on_book_id"
t.index ["user_id"], name: "index_comments_on_user_id"
end
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.string "username"
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
add_foreign_key "comments", "books"
add_foreign_key "comments", "users"
end
Hello) 👋 If u want to receive "true" or "false" on your back-end side u should check this first https://apidock.com/rails/ActionView/Helpers/FormHelper/check_box.
There are smth like check_box("puppy", "gooddog", {}, "yes", "no").
Yes and no means that if checkbox are checked then yes value goes to back-end side otherwise no goes to back-end side. U should replace this values with yours)
If problem will not go then post your controller code please)

I can't show the creator of a comment in the view part

I am doing a facebook clone app and I am implementing comments in posts. I can show the comments from the post but when I try to put the name of the creator of the comment, it show me an error.
The error that I get
This is what I have right now.
schema
ActiveRecord::Schema.define(version: 2019_09_02_233213) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "comments", force: :cascade do |t|
t.text "body"
t.bigint "user_id", null: false
t.bigint "post_id", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["post_id"], name: "index_comments_on_post_id"
t.index ["user_id"], name: "index_comments_on_user_id"
end
create_table "likes", force: :cascade do |t|
t.bigint "user_id", null: false
t.bigint "post_id", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["post_id"], name: "index_likes_on_post_id"
t.index ["user_id"], name: "index_likes_on_user_id"
end
create_table "posts", force: :cascade do |t|
t.bigint "user_id", null: false
t.text "body", default: "", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["user_id"], name: "index_posts_on_user_id"
end
create_table "users", force: :cascade do |t|
t.string "name", default: "", null: false
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
add_foreign_key "comments", "posts"
add_foreign_key "comments", "users"
add_foreign_key "likes", "posts"
add_foreign_key "likes", "users"
add_foreign_key "posts", "users"
end
users show views
<h1><%= #user.name %></h1>
<% #posts.each do |post| %>
<%= post.body %><br>
<%= form_for(post.comments.build, url: post_comments_path(post)) do |f| %>
<%= f.text_area :body %><br>
<%= f.submit 'Comment' %><br>
<% end %>
<% post.comments.each do |comment| %>
<%= comment.user.name %>
<%= comment.body %><br>
<% end %>
<% end %>
users controllers
class UsersController < ApplicationController
before_action :authenticate_user!
def index
#users = User.all
end
def show
#user = User.find(params[:id])
#posts = #user.posts
end
end
comment controllers
class CommentsController < ApplicationController
def create
post = Post.find(params[:post_id])
comment = post.comments.build(comment_params.merge(user: current_user))
if comment.save
redirect_back(fallback_location: root_path)
else
flash[:error] = comment.errors.full_messages
redirect_back(fallback_location: root_path)
end
end
def destroy
end
private
def comment_params
params.require(:comment).permit(:body)
end
end
user model
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 :posts
has_many :likes
has_many :comments
end
post model
class Post < ApplicationRecord
validates :body, presence: true
belongs_to :user
has_many :likes
has_many :comments
end
comment model
class Comment < ApplicationRecord
validates :body, presence: true
belongs_to :user
belongs_to :post
end
It looks like you have a comment that is not attached to a user. This could just be test data that has been left hanging around but you should cater for this and only display the user if there is one
<%= comment.user.name %>
Could become
<%= comment.user.name unless comment.user.blank? %>
You should also cater for the occasion when a name is not present.
Anyway, if you add that fix you will be able to tell more easily which records are not what you expect them to be and sort them appropriately
Something like this might help
<% if comment.user %>
<%= comment.user.name unless comment.user.name.blank? %>
<%else%>
<p> The comment <%= comment.body %> has no user attached. Please fix this. The comment ID is: <%=comment.id%></p>
<%end%>
Code is untested so if you have a problem let me know
You can check for blank? if you prefer
UPDATE
<% post.comments.each do |comment| %>
<% if comment.user %>
<%= comment.user.name %>
<%= comment.body %><br>
<%else%>
No user for <%= comment.body %>
<%end%>
<% end %>

How to show the name of category instead of its ID?

I am trying to have the category name show up in the Post's show.html.erb.
This is the current code for it:
<p>
<strong>Title:</strong>
<%= #post.title %>
</p>
<p>
<strong>Text:</strong>
<%= #post.text %>
</p>
<p>
<strong>Category:</strong>
<%= #post.category_id %>
</p>
<h2>Comments</h2>
<%= render #post.comments %>
<h2>Add a comment</h2>
<%= render 'comments/form' %>
<%= link_to 'Back', posts_path %>
How do I deal with this part: <%= #post.category_id %> so it can show the name of the category instead?
The current schema is:
create_table "categories", force: :cascade do |t|
t.string "name"
t.text "description"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "comments", force: :cascade do |t|
t.string "name"
t.text "body"
t.integer "post_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["post_id"], name: "index_comments_on_post_id", using: :btree
end
create_table "posts", force: :cascade do |t|
t.string "title"
t.text "text"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "category_id"
t.index ["category_id"], name: "index_posts_on_category_id", using: :btree
end
add_foreign_key "comments", "posts"
add_foreign_key "posts", "categories"
end
Current models are:
Post:
class Post < ApplicationRecord
has_many :comments
belongs_to :category
validates :title, presence: true
validates :text, presence: true
end
Categories:
class Category < ApplicationRecord
has_many :posts
end
Comment:
class Comment < ApplicationRecord
belongs_to :post
end
You should access #post's category's name:
#post.category.name
Because you are using association belongs_to in Post model, you can get the category name in your view this way:
<%= #post.category.name %>

Rails update not saving values

Please help me. I've been tearing out my hair trying to figure out what I feel should be a simple thing.
My update function "succeeds" but it does not actually save the new values. The console log doesn't throw an error, but it does say "Unpermitted parameter: profiles"
edit.html.erb
<div class="col-md-7 col-md-offset-3 main">
<% provide(:title, "Edit user")%>
<center><h1>Update your profile</h1></center>
<%= form_for(#person) do |f| %>
<%= render 'shared/error_messages' %>
<div class="col-md-12">
<%= render 'layouts/profilefields', f: f %>
<%= f.submit "Save Changes", class: "btn btn-large btn-primary" %>
</div>
<% end %>
</div>
_profilefields.html.erb
<%= f.fields_for :profiles do |prf|%>
<!--
<% if !#profileInfo["avatar"].blank? %>
<%= image_tag #contactInfo.avatar_url(:medium).to_s, :class=>"profilePhoto" %>
<% end %>
<div class="photoPreview">
<i class="fa fa-upload photoUpload"></i>
<p id="uploadClick">Click to Upload</p>
</div>
<%= prf.file_field :avatar, accept: 'image/png,image/gif,image/jpeg, image/jpg', id: 'uploadAvatar' %>
<p class="deletePhoto">Delete</p>
-->
<%= prf.label :about %>
<%= prf.text_field :about, :class => "form-control" %>
<%= prf.label :why %>
<%= prf.text_field :why, :class => "form-control" %>
<%= prf.label :goals %>
<%= prf.text_field :goals, :class => "form-control" %>
<%= prf.hidden_field :traveler_id, value: current_traveler.id %>
<% end %>
travelers_controller.rb
class TravelersController < ApplicationController
def edit
#person = Traveler.find(params[:id])
#profileInfo = Profile.find_or_initialize_by(traveler_id: params[:id])
##profileInfo[:email] = current_traveler.email
#This builds the form
#person.build_profile(#profileInfo.attributes)
end
def show
end
def update
#trav = Traveler.find(params[:id])
#prof = Profile.find_or_create_by(traveler_id: current_traveler.id)
if #trav.update(update_traveler_params)
flash[:success] = "Profile updated"
redirect_to feed_path
else # Failed. Re-render the page as unsucessful
render :edit
end
end
private
def update_traveler_params
params.require(:traveler).permit(:id, profiles_attributes: [:id, :first_name, :last_name, :about, :why, :goals,
:avatar, :traveler_id])
end
end
and the models
class Profile < ApplicationRecord
belongs_to :traveler, foreign_key: "traveler_id"
end
class Traveler < ApplicationRecord
# Include default devise modules. Others available are:
# , :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable, :confirmable,
:recoverable, :rememberable, :trackable, :validatable
has_one :profile
accepts_nested_attributes_for :profile, update_only: true, allow_destroy: true
end
and the schema. Is the profile foreignkey set up correctly?
ActiveRecord::Schema.define(version: 20160825224710) do
create_table "profiles", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
t.string "first_name"
t.string "last_name"
t.text "about", limit: 65535
t.text "why", limit: 65535
t.text "goals", limit: 65535
t.string "avatar"
t.integer "traveler_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["traveler_id"], name: "index_profiles_on_traveler_id", using: :btree
end
create_table "travelers", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
t.string "first_name"
t.string "last_name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.string "confirmation_token"
t.datetime "confirmed_at"
t.datetime "confirmation_sent_at"
t.string "unconfirmed_email"
end
end
I believe the problem is caused by your use of "profiles", when your association is actually a has_one.
Try changing:
profiles_attributes to profile_attributes in travellers_controller#update_traveler_params
:profiles to :profile in _profilefields.html.erb

Rails - Form HABTM

I am new to Rails but I am stuck. I would like to create a form that will add data to two tables (books and books_authors). My view looks like:
<%= form_for :book, url: book_path do |f| %>
<p>
<%= f.label :title %> :<br/>
<%= f.text_field :title %><br/>
<ul>
<% #authors.each do |x| %>
<li> <%= f.check_box {...} %> <%= x.name + " " + x.surname%></li>
<% end %>
</ul>
</p>
<p><%= f.submit %></p>
and my create method in controller books_controller.rb looks like:
def create
#book = Book.new(params.require(:book).permit(:title))
#book.save
params[:authors].each do |author_id|
book.authors << Author.find(author_id)
end
redirect_to root_path
end
and my schema:
ActiveRecord::Schema.define(version: 20150709110928) do
create_table "author_books", id: false, force: :cascade do |t|
t.integer "author_id"
t.integer "book_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "author_books", ["author_id"], name:
"index_author_books_on_author_id"
add_index "author_books", ["book_id"],
name:"index_author_books_on_book_id"
create_table "authors", force: :cascade do |t|
t.string "name"
t.string "surname"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "books", force: :cascade do |t|
t.string "title"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
end
I need params for :authors but I dont know how to nest it inside the form
I n your _form
<% #authors.each do |author| %>
<%= check_box_tag "author_ids[]", author.id %>
<%= author.name %> // I assume that your author has a name which can be used as a label
<% end %>
in your controller,
def create
// you will get the authors in params[:author_ids]
#book = Book.new(params.require(:book).permit(:title, :author_ids => [])) // its a dirty code
// skip other codes
end
fresh code for controller
define a private method and put
def book_params
params.require(:book).permit(:title, :author_ids => [])
end
and in
def create
#book = Book.new(book_params)
end

Resources