User_id is not fetched in join table - ruby-on-rails

I have a the following form:
<h2>Add collaborators to the wiki <strong><%= #wiki.title %></strong></h2>
<%= form_for ([#wiki, #collaboration]) do |f| %>
<% #users.each do |user| %>
<p><%= check_box_tag 'user_ids[]', user.id %>
<%= label_tag 'user_ids[]', user.email %>
<% end %>
<p> <%= f.submit %> <p>
<% end %>
It should do the following, provide the possible the check users => an then all this users should be able to edit this particular form (#wiki)
I therefor created a join table which takes a user_id and wiki_id. If i try to
to save the collaborators in through the form it does not seem to work however.
I get this in my rails c
#<Collaboration id: 1, user_id: nil, wiki_id: 1, created_at: "2015-02-20 10:40:49", updated_at: "2015-02-20 10:40:49">,
So it does not seem to fetch the user.
My controller is set up like this
class CollaborationsController < ApplicationController
def new
#wiki = Wiki.find(params[:wiki_id])
#collaboration = #wiki.collaborations.new
#users = User.all
end
def create
#wiki = Wiki.find(params[:wiki_id])
#selected users
#collaboration = #wiki.collaborations.build(user_id: params[:user_id])
if #collaboration.save
redirect_to wikis_path, notice: "Wiki shared."
else
flash[:error] = "Error creating wiki. Try again."
render :new
end
end
end
And my schema file looks like this:
create_table "collaborations", force: :cascade do |t|
t.integer "user_id"
t.integer "wiki_id"
t.datetime "created_at"
t.datetime "updated_at"
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.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.datetime "created_at"
t.datetime "updated_at"
t.string "role"
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
create_table "wikis", force: :cascade do |t|
t.string "title"
t.text "body"
t.boolean "private"
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "wikis", ["user_id"], name: "index_wikis_on_user_id"
create_table "wikis_and_collaborators", force: :cascade do |t|
t.integer "user_id"
t.integer "wiki_id"
t.datetime "created_at"
t.datetime "updated_at"
end
end
Any thoughts on what goes wrong here?

Let's say we have params[:user_ids] = [123, 456, 789]
You can say #wiki.user_ids = [123, 456, 789]; #wiki.save and that will make the join records automatically. So, this is actually an update on the wiki object, and your form should be editing the Wiki object too. I would do it like so:
<h2>Add collaborators to the wiki <strong><%= #wiki.title %></strong></h2>
<%= form_for (#wiki) do |f| %>
<% #users.each do |user| %>
<p><%= check_box_tag 'wiki[user_ids][]', user.id, #wiki.user_ids.include?(user.id) %>
<%= label_tag 'wiki[user_ids][]', user.email %>
<% end %>
<p> <%= f.submit %> <p>
<% end %>
This will submit to the WikiController#update action, or the WikiController#create action, depending on whether #wiki is a new record or not.
params will be params = {:id => 6, :wiki => {:user_ids => [123, 456, 789]}}, where 6 is an example wiki id.
Following convention, you wouldn't be accessing the CollaborationsController at all, you'd be accessing the WikisController, since it's a Wiki that's being updated. The WikisController#update action would be totally standard:
def update
#wiki = Wiki.find_by_id(params[:id])
#wiki.update_attributes(params[:wiki])
redirect_to wiki_path(#wiki) #or whatever
end

Related

Can't update User belongs_to association in Rails

I've got a page where a User (using Devise) sets up multiple preferences through checkboxes and then radio buttons of predefined data. So far I have the user able to update a has_and_belongs_to_many association but I can't get my belongs_to one's working.
At the moment I've got this error with the following parameters shown:
PG::ForeignKeyViolation: ERROR: insert or update on table "users" violates foreign key constraint
{"utf8"=>"✓",
"_method"=>"patch",
"user"=>{"sport_ids"=>["4"], "goal_ids"=>["6"], "moment_id"=>"moment_id", "workout_id"=>"workout_id"},
"commit"=>"Save Changes",
"id"=>"1"}
It seems clear that I'm not passing an id number through but I don't know how to fix it. When I don't get an error nothing happens.
Here are my files
models/user.rb
class User < ApplicationRecord
belongs_to :city
belongs_to :workout
belongs_to :fitness_level
belongs_to :moment
has_and_belongs_to_many :sports
has_and_belongs_to_many :goals
has_and_belongs_to_many :gyms
end
controllers/users_controller.rb
class UsersController < ApplicationController
...
def edit
#user = User.find(params[:id])
#auth = current_user.id
# To make sure you can't edit someone elses profile
if #auth != #user.id
redirect_to #user
end
#sports = Sport.all.order(name: :asc)
#goals = Goal.all.order(name: :asc)
#workouts = Workout.all.order(:name)
#moments = Moment.all
end
def update
#user = User.find(params[:id])
if #user.update(user_params)
redirect_to #user
else
render 'edit'
end
end
def show
#user = User.find(params[:id])
end
private
def user_params
params.require(:user).permit(sport_ids: [], goal_ids: [])
params.require(:user).permit(:workout_id, :moment_id)
end
end
users/edit.html.erb
<%= simple_form_for #user do |f| %>
# The following two work
<% #sports.each do |sport| %>
<%= check_box_tag "user[sport_ids][]", sport.id, form.object.sports.include?(sport) %>
<%= sport.name %>
<% end %>
<% #goals.each do |goal| %>
<%= check_box_tag "user[goal_ids][]", goal.id, form.object.goal.include?(goal) %>
<%= sport.name %>
<% end %>
# the below doesn't work
<% #moments.each do |moment| %>
<%= radio_button_tag 'user[moment_id]', :moment_id %>
<h4><%= moment.name %></h4>
<% end %> <!-- end moments-->
<% #workouts.each do |workout| %>
<%= radio_button_tag 'user[workout_id]', :workout_id %>
<% end %> <!-- end workouts-->
<% end %> <! -- end form -->
I have some important styling with the forms using tags so that will need to stay.
EDIT: Adding Users table in schema
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.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.inet "current_sign_in_ip"
t.inet "last_sign_in_ip"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.jsonb "settings", default: {}, null: false
t.string "first_name"
t.string "last_name"
t.date "date_of_birth"
t.integer "city_id"
t.text "bio"
t.integer "workout_id"
t.integer "fitness_level_id"
t.integer "moment_id"
t.index ["city_id"], name: "index_users_on_city_id", using: :btree
t.index ["email"], name: "index_users_on_email", unique: true, using: :btree
t.index ["fitness_level_id"], name: "index_users_on_fitness_level_id", using: :btree
t.index ["moment_id"], name: "index_users_on_moment_id", using: :btree
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
t.index ["settings"], name: "index_users_on_settings", using: :gin
t.index ["workout_id"], name: "index_users_on_workout_id", using: :btree
end
Im pretty sure the problem in that line:
<%= radio_button_tag 'user[moment_id]', :moment_id %>
You dont pass moment_id and workout_id from the view to controller`s update action.
Try to change it to:
<% #moments.each do |moment| %>
<%= radio_button_tag 'user[moment_id]', moment.id %>
<h4><%= moment.name %></h4>
<% end %> <!-- end moments-->
The same is for workout:
<% #workouts.each do |workout| %>
<%= radio_button_tag 'user[workout_id]', workout.id %>
<% end %> <!-- end workouts-->
Also why dont you pass permitted params in one line? Like this:
def user_params
params.require(:user).permit(:moment_id, :workout_id, sport_ids: [], goal_ids: [])
end

Rails searching a has_many relationship

Heyo. Been trying to figure this out but I've been stuck too long and it's just getting painful!
I'm trying to do an Advanced Search form allowing you to search for Users based off settings that are in other models. e.g. Search for a User named Jim, who does Running, and has weight loss as his goal.
I have three models:
User (using Devise)
Sport (many-to-many with user)
Goals (user has_many goals, goal belongs_to user)
So far I have managed to get it working so I can search for things in the User model (such as name) and also for Users Sports through a select box. What I haven't been able to get working is searching for the Users goals and I don't get why.
What I get is "Nobody seems to have these preferences" when searching ONLY for Goals and no other fields.
I have tried using the same code as my Sports but that didn't work (guessing because of the different relationships?)
# searches/show.html.erb
<% if #search.search_users.empty? %>
<p>Nobody seems to have these preferences</p>
<% else %>
<% #search.search_users.each do |u| %>
<tr>
<td><%= u.name %></td>
<% u.sports.each do |s| %>
<td><%= s.name %></td>
<% end %>
<% u.goals.each do |g| %>
<td><%= g.name %></td>
<% end %>
</tr>
<% end %>
I've done associations in the console and when I type for example u.goals I get this (and the opposite when I query what users are associated with a goal):
irb(main):015:0> u.goals
=> #<ActiveRecord::Associations::CollectionProxy [#<Goal id: 1, name: "Weight Loss", user_id: 1>, #<Goal id: 3, name: "Strength", user_id: 1>]>
Here's my current code:
# user.rb
class User < ApplicationRecord
has_and_belongs_to_many :sports
has_many :goals, :foreign_key => :goal_id
end
# sport.rb
class Sport < ApplicationRecord
has_and_belongs_to_many :users
end
# goal.rb
class Goal < ApplicationRecord
belongs_to :user, :foreign_key => :goal_id
end
And my searches stuff:
# search.rb
def search_users
users = User.all
users = users.where("users.name ILIKE ?", "%#{keywords}%") if keywords.present?
users = users.joins(:sports).where("sports.name ILIKE ?", "%#{name}%") if name.present?
users = users.where(goal_id: goal_id) if goal_id.present?
return users
end
# searches/new.html.erb
<%= form_for #search do |s| %>
<div class="form-group">
<%= s.label :keywords %>
<%= s.text_field :keywords %>
</div>
<div class="form-group">
<%= s.label :exercise %>
<%= s.select :name, options_for_select(#s_names), include_blank: true %>
</div>
<div class="form-group">
<%= s.label :goals %>
<%= s.collection_select :goal_id, Goal.order(:name), :id, :name, include_blank: true %>
</div>
<%= s.submit "Search", class: "btn btn-primary" %>
<% end %>
# searches_controller.rb
class SearchesController < ApplicationController
def new
#search = Search.new
#s_names = Sport.uniq.pluck(:name)
#users = User.uniq.pluck(:name)
end
def create
#search = Search.create(search_params)
redirect_to #search
end
def show
#search = Search.find(params[:id])
end
private
def search_params
params.require(:search).permit(:keywords, :name, :goal_id)
end
end
and then my schema for reference:
create_table "goals", force: :cascade do |t|
t.string "name"
t.integer "user_id"
t.index ["user_id"], name: "index_goals_on_user_id", using: :btree
end
create_table "searches", force: :cascade do |t|
t.string "keywords"
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "goal_id"
t.index ["goal_id"], name: "index_searches_on_goal_id", using: :btree
end
create_table "sports", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "sports_users", id: false, force: :cascade do |t|
t.integer "user_id", null: false
t.integer "sport_id", null: false
t.index ["user_id", "sport_id"], name: "index_sports_users_on_user_id_and_sport_id", using: :btree
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.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.inet "current_sign_in_ip"
t.inet "last_sign_in_ip"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "name"
t.integer "movement_id"
t.integer "goal_id"
t.index ["email"], name: "index_users_on_email", unique: true, using: :btree
t.index ["goal_id"], name: "index_users_on_goal_id", using: :btree
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
end
add_foreign_key "goals", "users"
end
Extremely sorry for the huge amount of messy code but I'm just tripping over myself at this point and getting confused.
Thank you greatly in advance.
I would change
users = users.where(goal_id: goal_id) if goal_id.present?
To
users = users.joins(:goals).where(goals: {id: goal_id})
For advanced searching I've recently used approach presented in this article: http://www.justinweiss.com/articles/search-and-filter-rails-models-without-bloating-your-controller/ and I think it's worth reading if you think about expanding search options.
EDIT: full response in comments below
:foreign_key => :goal_id needed to be removed

Rails: How to sum quantities by category in the different models

I'd like to sum quantities by category in the different models (Shop and Item).
models
class Order < ActiveRecord::Base
has_many :shops
end
class Shop < ActiveRecord::Base
belongs_to :order
has_many :items
end
class Item < ActiveRecord::Base
belongs_to :shop
has_one :order, autosave: false, through: :shop
end
There are the columns category and quantity in the both shops and items table as below.
I'd like to sum and display both quantity by category.
schema.rb
ActiveRecord::Schema.define(version: 20160610051929) do
create_table "orders", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "shops", force: :cascade do |t|
t.string "name"
t.integer "order_id"
t.integer "category"
t.integer "quantity"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "items", force: :cascade do |t|
t.string "name"
t.integer "category"
t.integer "quantity"
t.integer "shop_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
end
orders_controller.rb
class OrdersController < ApplicationController
def show
#orders = Order.find(params[:id])
end
end
view/orders/show.html.erb
<%= render #orders %>
My current view is as follows;
Although it only calculate in items table, I'd like to add the quantity in shops.
view/orders/ _order.html.erb
<% order.shops.each do |shop| %>
<% shop.items.group(:category).sum(:quantity).each do |category, sum| %>
Category <%=category%> : <%= sum %><br>
<% end %>
<% end %>
Although I also tried the following view instead of the above code, it only works when the shop's category exist in item's category.
If there is no category same as shop's category in the item, the result is not what I'd like to.
view/orders/ _order.html.erb
<% order.shops.each do |shop| %>
<% shop.items.group(:category).sum(:quantity).each do |category, sum| %>
<% if shop.category.present? && shop.quantity.present? && category == shop.category %>
<% sum = sum + shop.quantity %>
<% end %>
Category <%=category%> : <%= sum %><br>
<% end %>
<% end %>
It would be appreciated if you could give me how to sum and display both quantities or better way.
SOLVED
I could do what I'd like to do as followings;
schema.rb
create_table "categories", force: :cascade do |t|
t.integer "category"
t.integer "quantity"
t.integer "shop_id"
t.integer "item_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "order_id"
end
create_table "items", force: :cascade do |t|
t.string "name"
t.integer "shop_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "orders", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "shops", force: :cascade do |t|
t.string "name"
t.integer "order_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
end
orders_controller.rb
class OrdersController < ApplicationController
def show
#orders = Order.find(params[:id])
#categories = Category.where(order_id: params[:id])
end
end
_order.html.erb
<% order.shops.each do |shop| %>
<% #categories.where("order_id = ?", order.id).each do |cate| %>
<%= cate.order_id %>, <%= cate.shop_id%>, <%= cate.item_id%>, <%= cate.category%>, <%= cate.quantity%> <br>
<% end %>
<% #categories.where("shop_id = ?", shop.id).group(:category).sum(:quantity).each do |category, sum|%>
Category <%=category%> : <%= sum %><br>
<% end %>
<% end %>
Your second approach should work, style-wise you can write it much shorter:
sum += shop.quantity.to_i if shop.category == category
nil.to_i is 0, so no matter if shop.quantity is nil or not you can safely add it as long as shop.category == category And if shop.categoryis nil, it won't be equal to category, so there is no need to ask for it's presence either.
That said, I still think you might want to rethink the way your models are.

Rails - acts-as-taggable-on gem - How to change a tag's CSS style depending on it's tag count

Tried all sorts of different methods - just can't seem to solve this issue - your help would be amazing!
When a User creates a Post they can tag it via the acts-as-taggable-on gem. If the User writes a tag 2 times or more across Posts I am trying to make that tag then have a different CSS style than the other tags used.
For example, if a user creates three posts: http://imgur.com/zQEWcRo
Post1 tagged with "#foo #bar #foobar"
Post2 tagged with "#foobar #placeholder"
Post3 tagged with "#foobar #foo"
I am trying to get the #foobar to have a different CSS style than the other tags (#foo #bar #placeholder) across all posts (& preferably move #foobar to be the first hashtag in the sequence)
new.html.erb
<%= form_for #post, html: { multipart: true } do |f| %>
<%= f.text_field :tag_list %>
<%= f.submit %>
<% end %>
posts_controller.rb
class PostsController < ApplicationController
def index
if params[:tag]
#posts = Post.tagged_with(params[:tag]).order(created_at: :desc).page(params[:page]).per_page(2)
else
#posts = Post.all.order(created_at: :desc).page(params[:page]).per_page(2)
end
end
index.html.erb
<div id="posts">
<%= render #posts %>
</div>
<%= will_paginate #posts %>
_post.html.erb
<div class="post">
<%= raw post.tag_list.map {|t| link_to t, tag_path(t)}.join(' ') %>
</div>
<% post.things.order(:order).each do |thing| %>
<%= thing.try(:text) %>
<% end %>
Schema
ActiveRecord::Schema.define(version: 20160227154831) do
create_table "posts", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "taggings", force: :cascade do |t|
t.integer "tag_id"
t.integer "taggable_id"
t.string "taggable_type"
t.integer "tagger_id"
t.string "tagger_type"
t.string "context", limit: 128
t.datetime "created_at"
end
add_index "taggings", ["tag_id", "taggable_id", "taggable_type", "context", "tagger_id", "tagger_type"], name: "taggings_idx", unique: true
add_index "taggings", ["taggable_id", "taggable_type", "context"], name: "index_taggings_on_taggable_id_and_taggable_type_and_context"
create_table "tags", force: :cascade do |t|
t.string "name"
t.integer "taggings_count", default: 0
end
add_index "tags", ["name"], name: "index_tags_on_name", unique: true
create_table "things", force: :cascade do |t|
t.text "text"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
end
This is actually rather easy. Each acts-as-taggable-on tag has a taggings count.
For example:
post.tags.order("taggings_count DESC")
for post 1 of your example will give you this:
<ActsAsTaggableOn::Tag id: some_id, name: "foobar", taggings_count: 3>,
<ActsAsTaggableOn::Tag id: some_id, name: "foo", taggings_count: 2>,
<ActsAsTaggableOn::Tag id: some_id, name: "bar", taggings_count: 1>
Now you have your tags sorted by number of occurrence and you can also display a different class depending on taggings_count.
Edit:
This is how you could render the tags for example:
<div class="post">
<%= raw post.tags.order("taggings_count DESC").map {|t| link_to t.name, tag_path(t.name), class: css_class_for_tag(t.taggings_count)}.join(' ') %>
</div>
You will then need to define the helper method css_class_for_tag, for example like this:
def css_class_for_tag count
case count
when 0
'new_tag'
else
'used_tag'
end
end
Firstly you need to know whether some tag was used before or not. You can achieve this with:
Post.tag_counts_on(:tags).where(name: your_tag_name).present?
I'd suggest you to put this into a post.rb like:
def self.tag_used?(tag)
self.tag_counts_on(:tags).where(name: tag.name).present?
end
(Switch self with your wanted scope of posts (e.g. user.posts))
So when you know if a tag was used before or not you can add a specific class (let's say 'used') in _post.html.erb (also I suggest you to lookup slim/haml markup languages):
<div class="post">
<%= raw post.tag_list.map { |t| link_to t, tag_path(t), class: ('used' if Post.tag_used?(t)) }.join(' ') %>
</div>

object is being saved but the params are not

I am trying to make a simple blog app with rails as part of an exercise. Right now, you have the ability to add a comment on the post_path directly on show page of a post.
I'd like to be able to save a Comment object and have it be nested under a Post object so they are related.
My form looks like this:
#_form.html.erb
<%= form_for #comment, :url => post_comments_path(#post) do |f| %>
<%= f.label :content %>
<%= f.text_field :content %>
<%= f.submit %>
<% end %>
I click submit and I am transported to the comments controller:
#comments_controller.rb
def create
#post = Post.find(params[:post_id])
#comment = #post.comments.new
#comment.save(comment_params) # #comment is saved but :content is nil
if #comment.save(comment_params)
redirect_to post_path(#post)
end
end
if I look at comment_params inside the create action I see:
=> {"content"=>"asdfasdfasdfasdf"}. The comment gets saved, however the :content portion is empty as you can see below:
=> #<Comment:0x007fd1da63ce60
id: 4,
content: nil,
post_id: "1",
created_at: Mon, 26 Oct 2015 21:45:22 UTC +00:00,
updated_at: Mon, 26 Oct 2015 21:45:22 UTC +00:00,
user_id: nil>
I do have :content white listed in my strong params:
def comment_params
params.require(:comment).permit(:content, :post_id)
end
Here are my models..
#post.rb
class Post < ActiveRecord::Base
has_and_belongs_to_many :tags
has_many :comments
belongs_to :user
validates :title, :presence => true
validates :body, :presence => true
###methods###
def all_tags=(names)
self.tags = names.split(",").map do |name|
Tag.where(name: name.strip).first_or_create!
end
end
def all_tags
self.tags.map(&:name).join(", ")
end
end
#comment.rb
class Comment < ActiveRecord::Base
belongs_to :post
end
and my schema.
# schema..
create_table "comments", force: :cascade do |t|
t.string "content"
t.string "post_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id"
end
create_table "posts", force: :cascade do |t|
t.string "title"
t.text "body"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id"
end
create_table "posts_tags", force: :cascade do |t|
t.integer "post_id"
t.integer "tag_id"
end
create_table "tags", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
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.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.inet "current_sign_in_ip"
t.inet "last_sign_in_ip"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "username"
end
add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
end
Try changing to:
#comments_controller.rb
def create
#post = Post.find(params[:post_id])
#comment = #post.comments.new(comment_params)
if #comment.save
redirect_to post_path(#post)
end
end
Update with explanation:
old:
# creates empty comment that belongs to #post
#comment = #post.comments.new
new:
#creates a comment that belongs to #post and has the content of comment_params
#comment = #post.comments.new(comment_params)
old:
#comment.save(comment_params)
if #comment.save(comment_params)
redirect_to post_path(#post)
end
# is the same as #comment.save({}) as far as save is concerned.
# save takes a hash for options. It only uses the options it knows
# So that is why it didn't complain. It didn't find anything it knew
# in the hash comment_params. So it just saved the empty comment
new:
if #comment.save # save the new comment that was generated with comment_params
redirect_to post_path(#post)
end

Resources