Having a comment obtain a community_id as well - ruby-on-rails

I've tried figuring out the issue behind not being able to save the community_id I hope someone can help me with.
MODELS
User
has_one :profile
has_many :communities, dependent: :destroy
has_many :comment, dependent: :destroy
Community
extend FriendlyId
friendly_id :title, use: [:slugged, :finders]
has_many :comments
belongs_to :user
Comment
belongs_to :user
belongs_to :community
belongs_to :profile
CONTROLLERS
Communities
def index
#communities = Community.all
#comment = Comment.new
#comments = Comment.all
end
def create
#community = Community.new(community_params)
#community.user_id = session[:user_id]
if #community.save
flash[:notice] = "Post Created"
else
flash[:alert] = "Error post not created"
end
redirect_to "/"
end
def new
#community = Community.new
end
def edit
#community = Community.friendly.find(params[:id])
end
def show
#comment = Comment.new
#comments = Comment.all
#community = Community.friendly.find(params[:id])
#current_user = User.find(session[:user_id])
end
def update
#community = Community.friendly.find(params[:id])
if #community.update(params[:comment])
flash[:notice] = "post updated"
else
flash[:alert] = "post not updated"
end
end
def destroy
#community = Community.friendly.find(params[:id])
if #community.destroy
flash[:notice] = "Post was thrown away"
else
flash[:alert] = "Post was not deleted"
end
redirect_to "/"
end
private
def community_params
params.require(:community).permit(:user_id, :title, :bio)
end
Comments
def index
#comments = Comment.all
end
def create
#comment = Comment.new(comment_params)
#comment.user_id = session[:user_id]
if #comment.save && #comment.community_id
flash[:notice] = "Comment has been posted"
else
flash[:alert] = #comment.errors.full_messages
end
redirect_to :back
end
def new
#comment = Comment.new
end
def show
#comment = Comment.find(params[:id])
end
def destroy
#comment = Comment.find(params[:id])
#comment.destroy
redirect_to :back
end
private
def comment_params
params.require(:comment).permit(:text, :user_id, :community_id, :profile_id)
end
VIEWS
comments/_new
<%= form_for #comment do |f| %>
<%= f.hidden_field :community_id %>
<%= f.text_area :text, placeholder: "Enter New Comment Here ...", :cols => 50, :rows => 3, :class => 'text_field_message', :id => 'new_comment' %>
<%= f.submit :class => 'new_comment_button' %>
<% end %>
Whenever I check my console I notice the user_id gets registered with the comment but community_id is nil. Could someone point me in the right direction or help me understand where I made an error. Thank you for all your help.

Firstly,
#app/models/user.rb
has_many :comments, dependent: :destroy #-> this should be plural.
You have no value in your community_id input attribute:
#app/controllers/comments_controller.rb
class CommentsController < ApplicationController
def new
#comment = Comment.new
end
end
#app/views/comments/new.html.erb
<%= form_for #comment do |f| %>
<%= f.hidden_field :community_id, params[:community_id] %>
<% end %>
I am assuming you're passing your :community_id parameter through the routes (IE url.com/communities/:community_id/comments/new)
I would do the following:
#config/routes.rb
resources :communities do
resources :comments
end
#app/controllers/comments_controller.rb
class CommentsController < ApplicationController
def new
#comment = Comment.new
end
def create
#comment = Comment.new comment_params
#comment.save
end
private
def comment_params
params.require(:comment).permit(:text).merge(user_id: current_user.id, community_id: params[:community_id])
end
end
This will give you the ability to use the following view:
#app/views/comments/new.html.erb
<%= form_for #comment do |f| %>
<%= f.text_area :text, placeholder: "Enter New Comment Here ...", :cols => 50, :rows => 3, :class => 'text_field_message', :id => 'new_comment' %>
<%= f.submit :class => 'new_comment_button' %>
<% end %>

Related

How can i fix my commenting system from creating multiple comments? - Rails

The problem is in replying, each time i submit a reply it a new reply and comment is created.
Here's my comments controller
def new
#comment = Comment.new
end
def create
#post = Post.find(params[:post_id])
if params[:parent_id].present?
#comment = Comment.find(params[:parent_id]).replies.new.(comment_params)
elsif params[:parent_id].blank?
#comment = #post.comments.new(comment_params)
#comment.user = current_user
end
if #comment.save
flash[:success] = 'Your comment was successfully added!'
redirect_to :back
else
render 'new'
end
end
def destroy
#comment = Comment.find(params[:id])
#comment.destroy
if #comment.destroy
redirect_to :back
end
end
private
def comment_params
params.require(:comment).permit(:body, :parent_id)
end
end
and
and in my _comment.html.erb
<%= render comment.replies if comment.replies.any? %>
<%= form_for [comment.post, comment.replies.new] do |f| %>
<%= f.hidden_field :parent_id, :value => comment.id %>
<%= f.text_field :body %>
<%= f.submit 'reply', name: 'reply' %>
<% end %>
in my model
belongs_to :parent, class_name: "Comment"
has_many :replies, class_name: "Comment", foreign_key: :parent_id, dependent: :destroy
When the reply is submitted the a params[:parent_id] is passed.
The problem
If-Else statement is not working, I need it to know if a comment or a reply is submitted.
If it did work I don't know how to get the comment I'm creating the reply in.
Hope everything is clear, thanks.
Based on your form parent_id is coming under comment params, so it should be something like this
#post = Post.find(params[:post_id])
if params[:comment][:parent_id].present?
#comment = Comment.find(params[:parent_id]).replies.new.(comment_params)
elsif params[:comment][:parent_id].blank?
#comment = #post.comments.new(comment_params)
#comment.user = current_user
end
Hope it helps!

Rails: ActionController::ParameterMissing

I'm building an app that lets :users place :orders at :places. I am defining orders_params in PlacesController, but Rails says ParameterMissing ("params is missing or the value is empty: order")
How can I fix this, so that one can create an :order for :place_id through app/place/PLACE_ID/book ?
PlacesController:
def book
#place = Place.find(params[:id])
#order = Order.new(order_params)
if #order.save
flash[:success] = "Success"
redirect_to #place
else
render 'book'
end
end
private
def place_params
params.require(:place).permit(:place_name)
end
def order_params
params.require(:order).permit(:place_id, :user_id)
end
Routes.rb
get 'book' => 'places#show#book'
get '/places/:id/book' => 'places#book', as: :place_book
resources :places
OrdersController
class OrdersController < ApplicationController
def new
end
def create
#place = Place.find(#order.place_id)
#order = Order.new(user_id: current_user.id, place_id: #place)
if #order.save
flash[:success] = "Order placed"
redirect_to #place
else
render 'book'
end
end
def show
end
def edit
end
def update
end
def destroy
end
private
def order_params
params.require(:order).permit(:place_id, :user_id)
end
end
Model: Order.rb
belongs_to :user
has_one :place
validates :user_id, presence: true
validates :place_id, presence: true
## OTHER VALIDATIONS
View: app/views/places/book
<%= form_for(#order) do |f| %>
<!-- SOME FORM_FORS -->
<%= f.submit "Place order", class: "btn btn-primary" %>
<% end %>

Different notification partials for different models?

notifications/index has <%= render partial: "notifications/notification", collection: #notifications %>, which contains:
<%= link_to "", notifications_habit_path(notification.id), method: :delete, class: "glyphicon glyphicon-remove" %>
<%= link_to Comment.find_by(notification.comment_id).user.name, user_path(Comment.find_by(notification.comment_id).user.id) %>
commented on <%= link_to "your habit", habit_path(notification) %>
which shows:
This is problematic because it should say 3x ".com commented on your habit" and 2x ".com commented on your value".
We need to create two separate partials notifications/_habits & notifications/_values.
My confusion is how to make the code know when to direct to the habit partial or the value partial based on whether it's a habit or value.
notifications_controller
def index
#habits = current_user.habits
#valuations = current_user.valuations #aka values
#notifications = current_user.notifications
#notifications.each do |notification|
notification.update_attribute(:read, true)
end
The notifications are based on if a user comments on one of your habits or values:
comment.rb
class Comment < ActiveRecord::Base
after_save :create_notification
has_many :notifications
belongs_to :commentable, polymorphic: true
belongs_to :user
validates :user, presence: true
private
def create_notification
Notification.create(
user_id: self.user_id,
comment_id: self.id,
read: false
)
end
end
I followed this tutorial but it is based on using just one model: http://evanamccullough.com/2014/11/ruby-on-rails-simple-notifications-system-tutorial/
UPDATE FOR VALADAN
class CommentsController < ApplicationController
before_action :load_commentable
before_action :set_comment, only: [:show, :edit, :update, :destroy, :like]
before_action :logged_in_user, only: [:create, :destroy]
def index
#comments = #commentable.comments
end
def new
#comment = #commentable.comments.new
end
def create
#comment = #commentable.comments.new(comment_params)
if #comment.save
redirect_to #commentable, notice: "comment created."
else
render :new
end
end
def edit
#comment = current_user.comments.find(params[:id])
end
def update
#comment = current_user.comments.find(params[:id])
if #comment.update_attributes(comment_params)
redirect_to #commentable, notice: "Comment was updated."
else
render :edit
end
end
def destroy
#comment = current_user.comments.find(params[:id])
#comment.destroy
redirect_to #commentable, notice: "comment destroyed."
end
def like
#comment = Comment.find(params[:id])
#comment_like = current_user.comment_likes.build(comment: #comment)
if #comment_like.save
#comment.increment!(:likes)
flash[:success] = 'Thanks for liking!'
else
flash[:error] = 'Two many likes'
end
redirect_to(:back)
end
private
def set_comment
#comment = Comment.find(params[:id])
end
def load_commentable
resource, id = request.path.split('/')[1, 2]
#commentable = resource.singularize.classify.constantize.find(id)
end
def comment_params
params[:comment][:user_id] = current_user.id
params.require(:comment).permit(:content, :commentable, :user_id, :like)
end
end
Your notification is associated with comment, and comment can have commentable of type Habit or Value (you havent show those two model, so lets call them Habit and Value models).
So you can check if notification is for Habit or Value by checking commentable type like this:
Comment.find_by(notification.comment_id).commentable.class == Habit
or check if its value notification:
Comment.find_by(notification.comment_id).commentable.class == Value
Similar way is checking polymorphic type on the comment, like:
Comment.find_by(notification.comment_id).commentable_type == 'Habit'
So on the end, you dont actualy need two partials just IF and two different link_to, one for value and one for habit.
<%= link_to "", notifications_habit_path(notification.id), method: :delete, class: "glyphicon glyphicon-remove" %>
<%= link_to Comment.find_by(notification.comment_id).user.name, user_path(Comment.find_by(notification.comment_id).user.id) %> commented on
<% if Comment.find_by(notification.comment_id).commentable.class == Habit %>
<%= link_to "your habit", habit_path(notification) %>
<% else %>
<%= link_to "your value", value_path(notification) %>
<% end %>
I needed
<% if notification.habit_id %>
<%= link_to "your habit", habit_path(notification) %>
<% elsif notification.valuation_id %>
<%= link_to "your value", valuation_path(notification) %>
<% elsif notification.quantified_id %>
<%= link_to "your stat", quantified_path(notification) %>
<% elsif notification.goal_id %>
<%= link_to "your goal", goal_path(notification) %>
<% end %>
and in the comment model:
def create_notification
Notification.create(
habit_id: self.habit_id,
valuation_id: self.valuation_id,
quantified_id: self.quantified_id,
goal_id: self.goal_id,
user_id: self.user_id,
comment_id: self.id,
read: false
)
end

collection_select doesn't save through form

I know there is a lot of similar posts where people have the same problem, but none of them helped me. If i create new article then it won't have a category. But if i edit article created earlier in seed.rb then the category is updated.
What's wrong?
Categories table:
class CreateCategories < ActiveRecord::Migration
def change
create_table :categories do |t|
t.string :name
t.timestamps
end
end
end
category.rb
class Category < ActiveRecord::Base
has_many :articles
end
article.rb
class Article < ActiveRecord::Base
belongs_to :category
end
and then i have a _form file
<%= form_for(#article) do |f| %>
<div class="title">
<%= f.label :title %>
<%= f.text_field :title %>
</div>
<div class="content">
<%= f.label :content %>
<%= f.text_field :content %>
</div>
<div class="category">
<%= f.label :category %>
<%= collection_select(:article, :category_id, Category.all, :id, :name) %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
There is a categories_controller file:
class CategoriesController < ApplicationController
def index
#categories = Category.all
end
def show
#category = Category.find(params[:id])
#articles = #category.articles
end
def new
#category = Category.new
end
def create
#category = Category.new(category_params)
if #category.save
redirect_to(:action => 'index')
else
render('new')
end
end
def edit
#category = Category.find(params[:id])
end
def update
#category = Category.find(params[:id])
if #category.update_attributes(category_params)
redirect_to(:action => 'show', :id => #category.id)
else
render('index')
end
end
def delete
#category = Category.find(params[:id])
end
def destroy
Category.find(params[:id]).destroy
redirect_to(:action => 'index')
end
private
def category_params
params.require(:category).permit(:name)
end
end
Articles controller file:
class ArticlesController < ApplicationController
def index
#articles = Article.all
end
def show
#article = Article.find(params[:id])
end
def new
#article = Article.new
end
def create
#article = Article.new(article_params)
if #article.save
redirect_to(:action => 'index')
else
render('new')
end
end
def edit
#article = Article.find(params[:id])
end
def update
#article = Article.find(params[:id])
if #article.update_attributes(article_params)
redirect_to(:action => 'show', :id => #article.id)
else
render('index')
end
end
def delete
#article = Article.find(params[:id])
end
def destroy
Article.find(params[:id]).destroy
redirect_to(:action => 'index')
end
private
def article_params
params.require(:article).permit(:title, :content)
end
end
It looks like you're not building the association in the articles#create action. The category_id is being sent through your form, but you still need to to build the Active Record association. You could try something like this in the articles controller:
def create
#article = Article.new(article_params)
#category = Category.find(params[:category_id])
#article.category = #category
if #article.save
redirect_to(:action => 'index')
else
render('new')
end
end
Keep in mind, there are multiple ways to create an association. Your Article class has the following five methods to manipulate the association:
#article.category
#article.category=
#article.build_category
#article.create_category
#article.create_category!

Getting nested form to work rails?

I have these models:
class List < ActiveRecord::Base
has_many :list_items, :dependent => :destroy
accepts_nested_attributes_for :list_items, :reject_if => lambda { |a| a(:task.blank?)}
end
class ListItem < ActiveRecord::Base
belongs_to :list
end
and this controller:
class ListsController < ApplicationController
def index
#lists = List.order("lists.created_at DESC")
end
def show
#list = List.find(params[:id])
end
def new
#list = List.new({:name => Time.now.strftime("%A %d %B")})
3.times { #list.list_items.build}
end
def create
#list = List.new(list_params)
if #list.save
flash[:notice] = "List successfully added."
redirect_to(:action => 'index')
else
render(:action => 'new')
end
end
def edit
#list = List.find(params[:id])
end
def update
#list = List.find(params[:id])
if #list.update_attributes
flash[:notice] = "List updated successfully."
redirect_to(:action => 'index')
else
render(:action => 'edit')
end
end
def delete
#list = List.find(params[:id])
end
def destroy
#list = List.find(params[:id]).destroy
flash[:notice] = "List successfully deleted"
redirect_to(:action => 'index')
end
private
def list_params
params.require(:list).permit(:name, :task)
end
end
and this form:
<%= form_for #list do |f| %>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<%= f.fields_for :list_items do |builder| %>
<p>
<%= builder.label :task %><br />
<%= builder.text_field :task %>
</p>
<% end %>
<p><%= f.submit "Create" %></p>
<% end %>
You can probably see what I am trying to do -> create a form where it creates a new list and then adds task to that list but for some reason whenever I hit submit on the form the name stays but tasks don't save?
I solved the problem turns out i needed to add the list_item attributes to the list controller. I was trying to do this the rails 3 way in teh model with attr_accessible which kept giving me an error. I needed to update the controller to have this at the bottom:
def list_params
params.require(:list).permit(:name, :list_items_attributes => :task)
end

Resources