How to add comments to statuses (like facebook) - ruby-on-rails

I am trying to improve an exercice that I did on treehouse, the idea was to remake a little version of facebook thing, where users could publish statuses.
Now I want that a user can comment any statuses... And I am kinda lost...
The idea is to have all on the same page (if possible?, like on the real facebook)
So the comment form and the "displaying" content...
I hope anyone could help me :)
This is my github repository
I think I haven't understand how to call variables from a controller to another...
If someone could explain me with very easy words ... I am not native english speaker... so sometime it's difficult..
Here are the statuses part
controllers/statuses_controller/rb
class StatusesController < ApplicationController
before_filter :authenticate_user!, only: [:new, :create, :edit, :update]
before_action :set_status, only: [:show, :edit, :update, :destroy]
def index
#statuses = Status.all
#comments = Comment.all
end
def show
#status = Status.find(params[:id])
#comments = #status.comments.all
end
def new
#status = Status.new
#comment = #status.comments.build
end
def create
#status = Status.new(status_params)
#status.user = current_user
respond_to do |format|
if #status.save
format.html { redirect_to #status, notice: 'Status was successfully created.' }
format.json { render :show, status: :created, location: #status }
else
format.html { render :new }
format.json { render json: #status.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #status.update(status_params)
format.html { redirect_to #status, notice: 'Status was successfully updated.' }
format.json { render :show, status: :ok, location: #status }
else
format.html { render :edit }
format.json { render json: #status.errors, status: :unprocessable_entity }
end
end
end
def destroy
#status.destroy
respond_to do |format|
format.html { redirect_to statuses_url, notice: 'Status was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_status
#status = Status.find(params[:id])
end
def status_params
params.require(:status).permit(:user_id, :content, :comments_attribute[:id, :status_id, :content])
end
end
models/status.rb
class Status < ActiveRecord::Base
belongs_to :user
has_many :comments
default_scope -> { order(created_at: :DESC)}
validates :content, presence: true,
length: {minimum: 2}
validates :user_id, presence: true
end
views/comments/_form.html.erb I create a render in my index below:
<% simple_form_for #status.comments do |f|%>
<%= f.input :content %>
<%= f.button :submit %>
<% end %>
view/statuses/index.html.erb
<div class="page-header">
<h1>All of the Statuses</h1>
</div>
<%= link_to "Post A New Status", new_status_path, class: "btn btn-success"%>
<br>
<br>
<% #statuses.each do |status| %>
<div class="status">
<div class="row">
<div class="col-xs-1 avatar">
<%= image_tag status.user.avatar.thumb if status.user.avatar?%>
</div>
<div class="col-xs-7">
<h4><%= status.user.full_name%></h4>
</div>
</div>
<div class="row">
<div class="col-xs-8">
<p><%= simple_format(status.content) %></p>
</div>
</div>
<div class="row">
<div class="col-xs-8">
<%= link_to time_ago_in_words(status.created_at) + " ago", status %>
<% if status.user == current_user %>
<span class="admin">
| <%= link_to "Edit", edit_status_path(status) %> |
<%= link_to "Delete", status, method: :delete, data: {confirm: "Are you sure?"} %>
</span>
<% end %>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<p>Comments</p>
<% #comments.each do |comment| %>
<%= comment.content %>
<% end %>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<%= render "comments/form" %>
</div>
</div>
</div>
Now the comments part:
model/comment.rb
class Comment < ActiveRecord::Base
belongs_to :status
belongs_to :user
end
controllers/comments_controller.rb
class CommentsController < ApplicationController
def create
#comment = Comment.new(params_comment)
end
def index
#statuses = Status.all
#comments = Comment.all
#comment = Comment.find_by(params[:id])
end
private
def params_comment
params.require(:comment).permit(:content)
end
end
routes.rb
resources :statuses do
resources :comments
end
user.rb
that's a part of what I have in there
has_many :statuses
has_many :comments

your comments creation method should look like this:
#status = Status.find(params[:status_id])
#comment = #status.comments.create(comment_params)
#comment.user_id = current_user.id if current_user
#comment.save

Related

Rails ActiveStorage picks random file when no file attached

Im kinda new with Rails and ActiveStorage, I've been creating a simple app where a user can create an image with a title and a description and attache a picture to it.
I used scaffold referenced to user to create the Image part, and here is the image model :
class Image < ApplicationRecord
belongs_to :user
has_one_attached :picture
end
and here is the form:
<%= form_with(model: image) do |form| %>
<% if image.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(image.errors.count, "error") %> prohibited this image from being saved:</h2>
<ul>
<% image.errors.each do |error| %>
<li><%= error.full_message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= form.label :title %>
<%= form.text_field :title %>
</div>
<div class="field">
<%= form.label :description %>
<%= form.text_field :description %>
</div>
<div class="field">
<%= form.label :picture %>
<%= form.file_field :picture, accept: 'image/png,image/jpeg,image/jpg' %>
</div>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
<script type="text/javascript">
$('#image_picture').bind('change', function(){
var size_in_megabytes = this.files[0].size/1024/1024;
if(size_in_megabytes > 5){
alert("Maximum file size is 5Mo")
}
})
</script>
and the image_controller :
class ImagesController < ApplicationController
before_action :set_image, only: %i[ show edit update destroy ]
# GET /images or /images.json
def index
#images = Image.all
end
# GET /images/1 or /images/1.json
def show
end
# GET /images/new
def new
#image = Image.new
end
# GET /images/1/edit
def edit
end
# POST /images or /images.json
def create
#image = Image.new(image_params)
#image.user = current_user
respond_to do |format|
if #image.save
format.html { redirect_to #image, notice: "Image was successfully created." }
format.json { render :show, status: :created, location: #image }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: #image.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /images/1 or /images/1.json
def update
respond_to do |format|
if #image.update(image_params)
format.html { redirect_to #image, notice: "Image was successfully updated." }
format.json { render :show, status: :ok, location: #image }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: #image.errors, status: :unprocessable_entity }
end
end
end
# DELETE /images/1 or /images/1.json
def destroy
#image.destroy
respond_to do |format|
format.html { redirect_to images_url, notice: "Image was successfully destroyed." }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_image
#image = Image.find(params[:id])
end
# Only allow a list of trusted parameters through.
def image_params
params.require(:image).permit(:title, :description, :user_id, :picture)
end
end
When I submit the form without an image, it choose a random image from my local repo and attache it to the record, I dnt know why and how to stop it

only create records in nested resources

I'm creating a form in which I create related records, so far it works pretty well, it creates the nested records but when I create them it shows in the same form the related records created before, I just need to save records and not show the ones created in the textfields, how can I do that? this is my form
<%= form_with(model: drugs_device, local: true, html: {class: "formulario_validado"}) do |form| %>
<div class="form-row">
<div class="form-group col-md-6">
<%= form.label :abbreviation,"Código / ATC" %>
<%= form.text_field :abbreviation, class:"form-control", required: "true"%>
</div>
<%=form.fields_for :detail_drugs_devices do |fd| %>
<div class="form-row">
<div class="form-group col-md-3">
<%= fd.label :drug_concentration,"Concentration:" %>
<%= fd.text_field :drug_concentration, class:"form-control" %>
</div>
<div class="form-group col-md-3">
<%= fd.label :route_id,"Vía de administración" %>
<%= fd.select :route_id, options_for_select(#routes.map{|e|[e.description, e.id]}), {:prompt => "Por favor seleccione"}, {:class => "form-control"} %>
</div>
</div>
<%end%>
<div class="row">
<div class="col-md-4 offset-md-8 ">
<%= submit_tag "Guardar", class: "btn btn-primary"%>
</div>
</div>
</div>
<%end%>
my model drugs_device:
class DrugsDevice < ApplicationRecord
belongs_to :group
has_many :detail_drugs_devices
accepts_nested_attributes_for :detail_drugs_devices, reject_if: proc { |attributes| attributes['pharmaceutical_form_id'].blank?}
end
my model DetailDrugsDevice
class DetailDrugsDevice < ApplicationRecord
belongs_to :drugs_device
belongs_to :pharmaceutical_form
belongs_to :unit_size
belongs_to :route
end
my controller:
class DrugsDevicesController < ApplicationController
before_action :set_drugs_device, only: [:show, :edit, :update, :destroy]
# GET /drugs_devices
# GET /drugs_devices.json
def index
##drugs_devices = DrugsDevice.Busqueda_general(params).paginate(page: params[:page]).per_page(3)
#drugs_devices = DrugsDevice.all.paginate(page: params[:page]).per_page(3)
end
# GET /drugs_devices/1
# GET /drugs_devices/1.json
def show
end
# GET /drugs_devices/new
def new
#drugs_device = DrugsDevice.new
#drugs_device.detail_drugs_devices.build
#grupos = Group.all
#pharmaceutical_forms = PharmaceuticalForm.all
#unit_sizes = UnitSize.all
#routes = Route.all
end
# GET /drugs_devices/1/edit
def edit
#drugs_device.detail_drugs_devices.build
#grupos = Group.all
#pharmaceutical_forms = PharmaceuticalForm.all
#unit_sizes = UnitSize.all
#routes = Route.all
end
# POST /drugs_devices
# POST /drugs_devices.json
def create
#drugs_device = DrugsDevice.new(drugs_device_params)
respond_to do |format|
if #drugs_device.save
format.html { redirect_to edit_drugs_device_path(#drugs_device), notice: 'Drugs device was successfully created.' }
format.json { render :show, status: :created, location: #drugs_device }
else
format.html { render :new }
format.json { render json: #drugs_device.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /drugs_devices/1
# PATCH/PUT /drugs_devices/1.json
def update
respond_to do |format|
if #drugs_device.update(drugs_device_params)
format.html { redirect_to edit_drugs_device_path(#drugs_device), notice: 'Drugs device was successfully updated.' }
format.json { render :show, status: :ok, location: #drugs_device }
else
format.html { render :edit }
format.json { render json: #drugs_device.errors, status: :unprocessable_entity }
end
end
end
# DELETE /drugs_devices/1
# DELETE /drugs_devices/1.json
def destroy
#drugs_device.destroy
respond_to do |format|
format.html { redirect_to drugs_devices_url, notice: 'Drugs device was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_drugs_device
#drugs_device = DrugsDevice.find(params[:id])
end
# Only allow a list of trusted parameters through.
def drugs_device_params
params.require(:drugs_device).permit(:group_id, :atc, :abbreviation, :cientific_name, :stated_at, detail_drugs_devices_attributes: [:pharmaceutical_form_id, :unit_size_id, :route_id, :drug_concentration, :id])
end
end

Paperclip image upload store nil and display missing image

I am using Paperclip to upload an image and display in a pin. But it display a missing image and the pin stores null value for image properties. I have gone through different post here but still unable to fix it.
<Pin id: 7, description: "Hello", created_at: "2016-08-14 20:13:10", updated_at: "2016-08-14 20:13:10",user_id: 2, image_file_name: nil, image_content_type: nil, image_file_size: nil, image_updated_at: nil>
pin model
class Pin < ActiveRecord::Base
belongs_to :user
has_attached_file :image
validates_attachment :image, content_type: { content_type: ["image/jpg",
"image/jpeg", "image/png", "image/gif"] }
end
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
end
def show
end
def new
#pin = current_user.pins.build
end
def edit
end
def create
#pin = current_user.pins.build(pin_params )
respond_to do |format|
if #pin.save
format.html { redirect_to #pin, notice: 'Pin was successfully created.' }
format.json { render :show, status: :created, location: #pin }
else
format.html { render :new }
format.json { render json: #pin.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #pin.update(pin_params)
format.html { redirect_to #pin, notice: 'Pin was successfully updated.' }
format.json { render :show, status: :ok, location: #pin }
else
format.html { render :edit }
format.json { render json: #pin.errors, status: :unprocessable_entity }
end
end
end
def destroy
#pin.destroy
respond_to do |format|
format.html { redirect_to pins_url, notice: 'Pin was successfully destroyed.' }
format.json { head :no_content }
end
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: "Unauthorized to edit" 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, :image)
end
end
View
<%= form_for #pin, html: {multipart: true} do |f| %>
<% if #pin.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#pin.errors.count, "error") %> prohibited this pin from being saved:</h2>
<ul>
<% #pin.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="col-sm-8">
<div class="form-horizontal">
<div class="form-group">
<div class="field">
<%= f.label :image , class: "col-sm-3 control-label" %>
<div class="col-sm-5"><%= f.file_field :image , class: "form-control" %>
</div>
</div>
</div>
<div class="form-group">
<div class="field">
<%= f.label :description , class: "col-sm-3 control-label" %>
<div class="col-sm-5"><%= f.text_field :description , class: "form-control" %>
</div>
</div>
</div>
<div class="form-group">
<div class="actions">
<div class="col-sm-3"></div>
<div class="col-sm-5">
<%= f.submit class: "btn btn-danger" %>
</div>
</div>
</div>
</div>

Issue of deleting record in Nested Model Form Rails 4

I am following RailsCast # 196 Nested Model Form Part 1. I have given the same name of controllers as well as model and it's all attributes. But now when I try to go in edit and remove the question. It doesn't delete the question if I select the checkbox.
Like this:
Model:
class Survey < ActiveRecord::Base
has_many :questions, :dependent => :destroy
accepts_nested_attributes_for :questions, :reject_if => lambda {|a| a[:content].blank?} , :allow_destroy => true
end
class Question < ActiveRecord::Base
belongs_to :survey
end
Survey Controller:
class SurveysController < ApplicationController
before_action :set_survey, only: [:show, :edit, :update, :destroy]
def index
#surveys = Survey.all
end
def show
end
def new
#survey = Survey.new
3.times {#survey.questions.build}
end
def edit
end
def create
#survey = Survey.new(survey_params)
respond_to do |format|
if #survey.save
format.html { redirect_to #survey, notice: 'Survey was successfully created.' }
format.json { render :show, status: :created, location: #survey }
else
format.html { render :new }
format.json { render json: #survey.errors, status: :unprocessable_entity }
end
end
end
def update
#abort params[:survey][:questions_attributes].inspect
respond_to do |format|
if #survey.update(survey_params)
format.html { redirect_to #survey, notice: 'Survey was successfully updated.' }
format.json { render :show, status: :ok, location: #survey }
else
format.html { render :edit }
format.json { render json: #survey.errors, status: :unprocessable_entity }
end
end
end
def destroy
#survey.destroy
respond_to do |format|
format.html { redirect_to surveys_url, notice: 'Survey was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_survey
#survey = Survey.find(params[:id])
end
def survey_params
params.require(:survey).permit(:name, questions_attributes: [ :id, :content ])
end
end
View File
<%= form_for(#survey) do |f| %>
<% if #survey.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#survey.errors.count, "error") %> prohibited this survey from being saved:</h2>
<ul>
<% #survey.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<%= f.fields_for :questions do |builder| %>
<div class="field">
<%= builder.label :content, 'Question' %><br>
<%= builder.text_area :content, :rows=>3 %><br>
<%= builder.check_box :_destroy %>
<%= builder.label :_destroy, "Remove Question" %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
And As I have commented in update method for abort. If that way I do abort I get
{"0"=>{"content"=>"SEM 1", "_destroy"=>"0", "id"=>"4"}, "1"=>{"content"=>"Sem 2", "_destroy"=>"0", "id"=>"5"}, "2"=>{"content"=>"Sem 3", "_destroy"=>"1", "id"=>"6"}}
Where I do mistake. Please guide me. Thanks in advance.
Add :_destroy to permitted params
def survey_params
params.require(:survey).permit(
:name,
questions_attributes: %i(
id
content
_destroy
survey_id
)
)
end
Also, make sure you have allow_destroy: true in line, where you define accepts_nested_attributes_for :questions

Post and Location Association with ancestry gem

My Rails application have two model. Location and Post, Location have many post.I am Using
ancestry gem.
class Post < ActiveRecord::Base
belongs_to :location, :counter_cache => true
end
class Location < ActiveRecord::Base
include Tree
has_ancestry :cache_depth => true
has_many :posts
end
My Post Controller
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
def index
#posts = Post.all
end
def show
end
def new
#post = Post.new
end
def edit
end
def create
#post = Post.new(post_params)
respond_to do |format|
if #post.save
format.html { redirect_to #post, notice: 'Post was successfully created.' }
format.json { render action: 'show', status: :created, location: #post }
else
format.html { render action: 'new' }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #post.update(post_params)
format.html { redirect_to #post, notice: 'Post was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
def destroy
#post.destroy
respond_to do |format|
format.html { redirect_to posts_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_post
#post = Post.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def post_params
params.require(:post).permit(:name)
end
end
If i am create new Post with which Location belongs in _form.html.erb
<%= form_for(#post) do |f| %>
<% if #post.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#post.errors.count, "error") %> prohibited this post from being saved: </h2>
<ul>
<% #post.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<%= select :location_id, Location.all.at_depth(4) { |l| [ l.name, l.id ] } %>
<div class="actions">
<%= f.submit %>
</div>
Browser show error message which is display bellow
ArgumentError in Posts#new
Not sure if this fixes your error, but:
To make the dropdown working, change the select line to:
<%= f.select :location_id, Location.all.at_depth(4) { |l| [ l.name, l.id ] } %>
This is because you want the formbuilder f to handle the creation of the form element.
You also have to whitelist the :location_id parameter in the controller:
def post_params
params.require(:post).permit(:name, :location_id)
end

Resources