while Form sumbitting extra blank item - ruby-on-rails

When I submit an answer form, the first item is getting the only empty string, how I can fix it and guide me.
Extra item picture:
question model
class Question < ApplicationRecord
has_many :answers, dependent: :destroy
end
answer model
class Answer < ApplicationRecord
belongs_to :question
end
answer controller
class AnswersController < ApplicationController
def create
#question = Question.find(params[:question_id])
#answer = #question.answers.create(params[:answer].permit(:body))
redirect_to question_path(#question)
end
def destroy
#question = Question.find(params[:question_id])
#answer = #question.answers.find(params[:id])
#answer.destroy
redirect_to question_path(#question)
end
end
answer form
<%= form_for([#question,#question.answers.build]) do |f| %>
<div class="row">
<div class="input-field col s12 m9">
<%= f.text_area :body ,:id=>"ans_form" %>
<label for="first_name"style="text-indent:15px;line-height:15px">Create Possible Answer</label>
</div>
<div class="input-field col s12 m3">
<%= button_tag(type: 'submit', class: "col s12 btn waves-effect accent-4") do %>
Create Answer
<% end %>
</div>
</div>
<% end %>
in my view (show page )
<%= #question.answers.each do |answer| %>
<%= answer.body %>
<%= link_to 'delete',[answer.question, answer], method: :delete %>
<% end %>

Related

Cloudinary images aren't displaying on live site

Pretty new to Rails, but I'm having an issue getting images to display on a live site. The images are uploaded by the user as part of creating a post, but I'm running into two issues:
The media library is not updating when an image is uploaded
On localhost the upload works fine and is displayed, however on the live site the images are not being displayed. The page loads fine but the Cloudinary image src generated doesn't point anywhere
Example:
<img class="main-post-image" src="https://res.cloudinary.com/hw2ugvhic/image/upload/vfvhamrbx0jz8rj6y17c2vy4m2gp">
New post view:
<div class="text-center mt-3">
<h1>New post</h1>
</div>
<div class = "main-form-container">
<div class= "post-form-container">
<div data-controller="multi-upload">
<%= simple_form_for [#country, #area, #post] do |f| %>
<%= f.input :title %>
<%= f.input :summary %>
<%= f.input :description, as: :rich_text_area %>
<%= f.input :category , collection: %w(bar restaurant activity nature memory) %>
<%= f.input :main_image, as: :file, label: "square image only"%>
<%= f.file_field :images, multiple: true, data: {action: "multi-upload#addFile"} %>
<div data-multi-upload-target="files"></div>
<div class = "d-flex justify-content-center">
<%= f.button :submit, class: "green-button mt-3"%>
</div>
<div class = "text-link text-center mt-2">
<%= link_to "Go back", country_area_path(#country, #area) %>
</div>
<% end %>
</div>
</div>
</div>
Posts controller:
class PostsController < ApplicationController
def new
#country = Country.find(params[:country_id])
#area = Area.find(params[:area_id])
#post = Post.new
end
def create
#country = Country.find(params[:country_id])
#area = Area.find(params[:area_id])
#post = Post.new(post_params)
#post.user = current_user
#post.area = #area
if #post.save
redirect_to country_area_path(#country, #area)
else
render :new
end
end
def show
#country = Country.find(params[:country_id])
#area = Area.find(params[:area_id])
#post = Post.find(params[:id])
end
def edit
#post = Post.find(params[:id])
#area = Area.find(params[:area_id])
#country = Country.find(params[:country_id])
end
def update
#area = Area.find(params[:area_id])
#country = Country.find(params[:country_id])
#post = Post.find(params[:id])
#post.update(post_params)
redirect_to country_area_post_path(#country, #area, #post)
end
private
def post_params
params.require(:post).permit(:title, :summary, :description, :category, :area_id, :main_image, images: [])
end
end
Post model:
class Post < ApplicationRecord
belongs_to :user
belongs_to :area
has_one_attached :main_image, dependent: :destroy
has_many_attached :images, dependent: :destroy
has_rich_text :description
validates :title, :summary, :description, :category, :main_image, presence: true
end
Area show view page (where the posts can be viewed)
<nav aria-label="breadcrumb" class="mt-2 pl-2">
<ol class="breadcrumb">
<li class="breadcrumb-item"><%= link_to "Home", root_path %></li>
<li class="breadcrumb-item"><%= link_to #country.name, country_path(#country) %></li>
<li class="breadcrumb-item active" aria-current="page"><%= #area.name %></li>
</ol>
</nav>
<% unless #posts.empty?%>
<div class = main-posts-div>
<div>
<%= "Welcome to #{#area.name}, #{#country.name}"%>
</div>
<%= link_to "New post", new_country_area_post_path(#country, #area), class: "green-button mt-3"%>
<div>
<div class="area-main-div">
<% #posts.each do |post| %>
<%= link_to country_area_post_path(#country, #area, post) do %>
<div class= "post-card">
<div>
<% if post.main_image.nil? %>
<%= image_tag("https://picsum.photos/300/300") %>
<% else %>
<%= cl_image_tag(post.main_image.key, class:"main-post-image") %>
<% end %>
</div>
<div class = "lower-post-card">
<div>
<%= post.title %>
</div>
<div>
<em><%= post.category %></em>
</div>
</div>
<% end %>
</div>
<% end %>
</div>
</div>
</div>
<% else %>
<div class="main-posts-div-blank">
<div>
<%= "Welcome to #{#area.name}, #{#country.name}. #{#area.name} is yet to be explored, please document your experience"%><br>
</div>
<%= link_to "New post", new_country_area_post_path(#country, #area), class: "green-button mt-3"%>
</div>
<% end %>
Areas controller
class AreasController < ApplicationController
def new
#area = Area.new
end
def create
#country = Country.find(params[:country_id])
#area = Area.new(area_params)
#area.country = #country
#area.save
redirect_to country_path(#country)
end
def show
#area = Area.find(params[:id])
#country = Country.find(params[:country_id])
#post = Post.new
#posts = Post.where(area_id: #area)
end
private
def area_params
params.require(:area).permit(:name, :country_id)
end
end
Steps already taken
Added Cloudinary to Heroku
Created a dotenv file with the cloudinary key
added cloudinary gem
Updated the following:
storage.yml
cloudinary:
service: Cloudinary
folder: <%= Rails.env %>
development.rb
config.active_storage.service = :cloudinary
What can I try next?
I think the only thing that might be missing is that active storage does not store the folder as part of the key e.g. post.main_image.key would be a random string but is missing folderName/<random-string> which you defined in the storage.yml file.
I believe you just need to include the folder name in the cl_image_tag(post.main_image.key, class:"main-post-image") should be cl_image_tag("folderName/"+post.main_image.key, class:"main-post-image")
There probably is a way to pass that dynamically.

Trying to create comments inside posts - rails

I'm traying to create a social media with posts and comments inside the posts.
I'm trying to link the comments to the posts but I'm not going well. I dont know if the bug is from the controllers or the views. That`s what I have:
Comment model:
class Comment < ApplicationRecord
belongs_to :user
belongs_to :post
end
post model:
class Post < ApplicationRecord
belongs_to :user
has_many :comments
end
routes:
resources :posts do
member do
resources :comments
end
end
posts controller (the idea is to show the comment form and show inside the posts, and make a kind of feed, like facebook, instagram.. ):
class PostsController < ApplicationController
def index
#posts = Post.includes(:user).order(updated_at: :desc)
#comment = Comment.new
end
def new
#post = Post.new
end
def create
#post = Post.new(post_params)
#post.user = current_user
if #post.save
redirect_to request.referrer
# redirect_to feed_users_path
else
render :new
end
end
private
def post_params
params.require(:post).permit(:content, :user)
end
end
comments controller:
class CommentsController < ApplicationController
def create
#comment = Comment.new(comment_params)
#comment.user = current_user
#comment.post = #post
if #comment.save
redirect_to request.referrer
end
end
private
def comment_params
params.require(:comment).permit(:content, :post, :user)
end
end
this is the post index:
<% #posts.each do |post| %>
<div class="row" id="post-<%= post.id %>">
<div class="col-12 post-container">
<!-- header -->
<div class="post-header d-flex justify-content-start">
<%= link_to user_path(post.user) do %>
<h5><%= post.user.first_name %> <%= post.user.last_name %></h5>
<% end %>
<p>
<%= link_to user_path(post.user) do %>
#<%= post.user.first_name %>
<% end %>
<span><%= distance_of_time_in_words(Time.now, post.created_at) %></span> ago
</p>
</div>
<!-- content -->
<div class="post-content">
<div class="post-text">
<h4><%= post.content %></h4>
</div>
</div>
<hr>
<div class="form--input">
<%= simple_form_for([#post.comment], remote: true) do |f| %>
<div class="form--input">
<%= f.input :content, input_html: { class: "form-txt py-3" }, placeholder: "What do you want to comment?", label: false %>
</div>
<div class="form--input_elements d-flex justify-content-between mx-4">
<div class="form--input_submit">
<%= f.submit "Post Comment", class: "btn btn-flat", id: "post-submit", role: "status", remote: true %>
</div>
</div>
<% end %>
</div>
</div>
</div>
<% end %>
You have a problem in the routes file, it should be like this :
resources :posts do
resources :comments
end

Accessing Model ID inside of rails form helper

First off I'm new to rails, I have a join table Menus_orders which I'm trying to load ID's into on create.
I have this form helper which has access to Order.new(:id, :name) fields and fields_for Menus_order(:menu_id, :order_id). I can insert the menu_id from a select but I can't for the life of me figure out how to populate a hidden input with the current order_id which the form holds in #order.
look at ORDER_ID HERE
<div class="form">
<h1>Create a new order</h1>
<%= form_for #order do |f| %>
<%= f.label :name%><br>
<%= f.text_field :name%><br>
<h3>Select meals</h3>
<%= fields_for(#menus_order) do |i| %>
<div class="field">
<%= i.select :menu_id, options_for_select(Menu.all.pluck(:id)) %>
<%= i.hidden_field :order_id, :value => ORDER_ID HERE %>
</div>
<% end %>
<br>
<%= f.submit "Create"%><br>
<% end %>
</div>
Thanks, DW
You should use nested attributes for order model just apply
the conventions right & it will be handled, you can achieve this by
following example :
order.rb should be like :
class Order < ActiveRecord::Base
has_many :menu_orders
accepts_nested_attributes_for :menu_orders
end
menu_order.rb be like :
class MenuOrder < ActiveRecord::Base
belongs_to :order
end
orders/new.html
<div class="form">
<h1>Create a new order</h1>
<%= form_for #order do |f| %>
<%= f.label :name%><br>
<%= f.text_field :name%><br>
<h3>Select meals</h3>
<%= f.fields_for :menu_orders do |i| %>
<div class="field">
<%= i.select :menu_id, options_for_select(Menu.all.pluck(:id)) %>
</div>
<% end %>
<br>
<%= f.submit "Create"%><br>
<% end %>
</div>
OrdersController
class OrdersController < ApplicationController
def new
#order = Order.new
#order.menu_orders.build
end
def create
#order = Order.new(order_params)
if #order.save
redirect_to orders_path
flash[:success] = "Order created"
else
render 'new'
end
end
private
def order_params
params.require(:order).permit(:name, menu_orders_attributes: [ :menu_id, :order_id ])
end
end

How to pass data from view to controller in rails

I'd like to actualise the function that current_user answers a question. In order to achieve it, I need to pass question_id data from view to controller.
In particular,
1) Pass question_id from views/homes/popular.html.erb to answers_controller.rb
2) Pass question_id from answers_controller.rb to views/answers/new.html.erb
3) Pass question_id from views/answers/new.html.erb to answers_controller.rb
I'd like to pass question_id to hogehoge at answers_controller.rb. Could you tell me how to do it?
#app/controllers/homes_controller.rb
class HomesController < ApplicationController
def popular
#questions = Question.all
#questions.each do |question|
#answer = question.answers.highest
end
end
end
#app/views/homes/popular.html.erb
<div class="row">
<div class="row">
<h3>Popular</h3>
<% #questions.each do |question| %>
<li><%= link_to question.body, new_answer_path ,question_id:question.id%></li>
<% end %>
</div>
</div>
#app/controllers/answers_controller.rb
class AnswersController < ApplicationController
def new
#answer = Answer.new
end
def create
#answer = current_user.answers.create(answer_params)
if #answer.save
redirect_to root_url
else
render 'new'
end
end
private
def answer_params
hogehoge
end
end
#app/views/answers/new.html.erb
<%= form_for #answer, :url => answers_path do |f| %>
<div class="page-header">
<h2>Please answer</h2>
</div>
<div class="span6 offset3">
<%= f.label :body %><br>
<%= f.text_field :body %>
</div>
<%= f.submit 'post', class: 'btn btn-primary' %>
<% end %>
To send data from view to controller you can use query string as you used in popular.html.erb and in answer controller you get data in params[:question_id] , use instance variable in new action as #question = params[:question_id] and in answer/new.html use hidden field f.hidden_field :#question to send data.

Rails 4 Nested Form.

I am building a dynamic form for a client. A form has many form questions which has many form answers. As of now, I am able to create everything nicely in Active Admin and have it displaying through the show action on the app interface. Here is the problem I have. I want to display the form title (which is working), along with the form questions (which is working), along with input fields to submit new form answers on the fly (which is the part that is not working). I feel like I have exhausted everything when it comes to nested forms. I will post my code below.
Form
<%= form_for #form do |f| %>
<div class="field">
<h1><%= #form.name %></h1>
</div>
<%= f.fields_for :form_questions do |ff| %>
<div class="field">
<%= ff.label :title %>
<%= ff.text_field :form_answers %>
</div>
<% end %>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
Here is the models
class Form < ActiveRecord::Base
has_many :form_questions, dependent: :destroy
accepts_nested_attributes_for :form_questions, allow_destroy: true
end
class FormQuestion < ActiveRecord::Base
belongs_to :form
has_many :field_types
has_many :form_answers, dependent: :destroy
accepts_nested_attributes_for :field_types
accepts_nested_attributes_for :form_answers
end
class FormAnswer < ActiveRecord::Base
belongs_to :form_question
end
And my form controller
class FormsController < ApplicationController
def new
#form = Form.new
# form_questions = #form.form_questions.build
# form_answers = form_questions.form_answers.build
end
def create
#form = Form.new(form_params)
end
def index
#forms = Form.includes(:form_questions).all
end
def show
#form = Form.find(params[:id])
end
def edit
#form = Form.find(params[:id])
end
def form_params
params.require(:form).permit(:id, :name, form_questions_attributes: [:title, form_answers_attributes: [:answer]])
end
end
Firstly,you should uncomment those two lines in your new method.I guess they are correct.
def new
#form = Form.new
#form_questions = #form.form_questions.build
#form_answers = #form_questions.form_answers.build
end
And in your create action,you are not saving the data
def create
#form = Form.new(form_params)
if #form.save
.....
else
.....
end
end
Secondly,your form code should look like this
<%= form_for #form do |f| %>
<div class="field">
<h1><%= #form.name %></h1>
</div>
<%= f.fields_for #form_questions do |ff| %>
<div class="field">
<%= ff.label :title %>
<%= ff.text_field :title %>
</div>
<%= ff.fields_for #form_answers do |fa| %> #Here comes the important step
<div class="field" %>
<%= fa.label :answer %>
<%= fa.text_field :answer %>
</div>
<% end %>
<% end %>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>

Resources