Ruby on Rails - Adding comments to post - ruby-on-rails

Trying to learn RoR. Currently adding comments to posts by user. So far I have a posts model, comments model and post_comments model (to associate the two). So for in 'rails console' I can run: (say I set p = Post.first and c = Comment.first)
p.comments << c
This forms an association so it works in the console. I just can't seem to get the comments to form this association from the UI. So far I am creating the comments at "comments/new" (not sure if this is the issue. Do they need to be created on the "show view" for "post").
Here are some code snippets
Controllers
comments_controller.rb
class CommentsController < ApplicationController
def index
#comment = Comment.all
end
def new
#comment = Comment.new
end
def create
#comment = Comment.new(commentParams)
if #comment.save
flash[:success] = "Comment successfully added"
redirect_to comments_path(#comment)
else
render 'new'
end
end
def show
#comment = Comment.find(params[:id])
end
private
def commentParams
params.require(:comment).permit(:comment)
end
end
posts_controller
class PostsController < ApplicationController
before_action :setPost, only: [:edit, :update, :show, :destroy, :sold]
before_action :requireUser, except: [:index, :show]
before_action :requireSameUser, only: [:edit, :update, :destroy, :sold]
def index
#posts = Post.paginate(page: params[:page], per_page: 20)
end
def new
#post = Post.new
end
def create
#post = Post.new(postParams)
#post.user = currentUser
if #post.save
flash[:success] = "Post successfully added."
redirect_to post_path(#post)
else
render 'new'
end
end
def update
if #post.update(postParams)
flash[:success] = "Post successfully updated."
redirect_to post_path(#post)
else
render 'edit'
end
end
def show
end
def edit
end
def sold
#post.toggle(:sold)
#post.save
redirect_to post_path(#post)
end
def destroy
#post.destroy
flash[:danger] = "Item successfully deleted."
redirect_to posts_path
end
private
def postParams
params.require(:post).permit(:title, :price, :description, category_ids:[])
end
def setPost
#post = Post.find(params[:id])
end
def requireSameUser
if currentUser != #post.user and !currentUser.admin
flash[:danger] = "You can only edit or delete your own items"
redirect_to root_path
end
end
end
Models
comment.rb
class Comment < ActiveRecord::Base
belongs_to :post_comments
belongs_to :user
belongs_to :post
end
post_comment.rb
class PostComment < ActiveRecord::Base
belongs_to :post
belongs_to :comment
end
post.rb
class Post < ActiveRecord::Base
belongs_to :user
has_many :post_categories
has_many :categories, through: :post_categories
has_many :post_comments
has_many :comments, through: :post_comments
validates :title, presence: true,
length: { minimum: 4, maximum: 20 }
validates :description, presence: true,
length: { maximum: 1000 }
validates :user_id, presence: true
end
Views
posts/show.html.erb
<p>Comments: <%= render #post.comments %></p>
This renders the partial below
comments/_comment.html.erb
<%= link_to comment.name, comment_path(comment) %>
Finally is the new comment page as it is.
comments/new.html.erb
<h1>New Comment</h1>
<%= render 'shared/errors', obj: #comment %>
<div class="row">
<div class="col-xs-12">
<%= form_for(#comment, :html => {class: "form-horizontal", role: "form"}) do |f| %>
<div class="form-group">
<div class="control-label col-sm-2">
<%= f.label :comment %>
</div>
<div class="col-sm-8">
<%= f.text_area :comment, rows: 3, class: "form-control", placeholder: "Please enter a comment", autofocus: true %>
</div>
</div>
<div class="form-group">
<div class="center col-sm-offset-1 col-sm-10">
<%= f.submit class: "btn btn-primary btn-lg" %>
</div>
</div>
<% end %>
Any help would be greatly received.
Update
Log
Started GET "/posts/2" for ::1 at 2016-01-15 12:39:55 +0000
Processing by PostsController#show as HTML
Parameters: {"id"=>"2"}
[1m[36mPost Load (0.1ms)[0m [1mSELECT "posts".* FROM "posts" WHERE "posts"."id" = ? LIMIT 1[0m [["id", 2]]
[1m[35mUser Load (0.1ms)[0m SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 1]]
[1m[36m (0.1ms)[0m [1mSELECT COUNT(*) FROM "posts" WHERE "posts"."user_id" = ?[0m [["user_id", 1]]
[1m[35mCategory Exists (0.1ms)[0m SELECT 1 AS one FROM "categories" INNER JOIN "post_categories" ON "categories"."id" = "post_categories"."category_id" WHERE "post_categories"."post_id" = ? LIMIT 1 [["post_id", 2]]
[1m[36mCategory Load (0.0ms)[0m [1mSELECT "categories".* FROM "categories" INNER JOIN "post_categories" ON "categories"."id" = "post_categories"."category_id" WHERE "post_categories"."post_id" = ?[0m [["post_id", 2]]
Rendered categories/_category.html.erb (0.2ms)
[1m[35mComment Load (0.1ms)[0m SELECT "comments".* FROM "comments" WHERE "comments"."post_id" = ? [["post_id", 2]]
Rendered comments/_comment.html.erb (0.1ms)
Rendered posts/show.html.erb within layouts/application (6.5ms)
[1m[36mCategory Load (0.1ms)[0m [1mSELECT "categories".* FROM "categories"[0m
Rendered layouts/_navigation.html.erb (0.9ms)
Rendered layouts/_messages.html.erb (0.1ms)
Rendered layouts/_footer.html.erb (0.1ms)
Completed 200 OK in 52ms (Views: 50.3ms | ActiveRecord: 0.5ms)

As a comment can belong to a single post only, you do not need an association table (post_comments). You just need a simple one-to-many relationship.
Your post comment would be:
class Post < ActiveRecord::Base
has_many :comments
...
end
And comment would be like this:
class Comment < ActiveRecord::Base
belongs_to :post
...
end
Just make sure that you have the necessary post_id column in the comments table (you can check the db/schema.rb file). If that is missing, you can use the following migration to add it:
class AddPostIdToComments < ActiveRecord::Migration
def change
add_column :comments, :post_id, :integer
add_index :comments, :post_id
end
end
You also need to make sure you keep somewhere the reference to the post, whenever a user tries to create a comment to a post. You can add this in a hidden field to your comments/new.html.erb template. You could set the hidden field in the new action, in PostsController, after passing it through the URL.
So, in your posts/show.html.erb template you would have:
<%= link_to "Add Comment", new_comment_path(post_id: #post.id) %>
In your new action, in PostsController:
def new
#comment = Comment.new(post_id: params[:post_id])
end
And finally the hidden field in your form would be:
<%= f.hidden_field :post_id %>
Finally, add the post_id parameter to the list of permitted parameters in CommentsController.

instead of
In your new action, in PostsController:
def new
#comment = Comment.new(post_id: params[:post_id])
end
you can use this in the form views
<%= form.hidden_field :post_id, value: "#{params[:post_id]}" %>

Related

nested attributes, update and create diferents tables and fields at the same time

In my application I have a goal, this goal belongs to a company and has start and end date, when it is created automatically values ​​are created in the day table that go between the start date and end date defined in the goal, this field has the name of date_day.
In addition to this field each Day has a value field, which is the total amount collected during the day, this value is not automatically defined when the user creates a goal, ie it comes null, it is necessary to edit the Day to define how much was collected in that day. When I go to do the edition of the day I would like to add an employee in my model Salesman, that employee would be tied to that Day.
I managed through the Day edit form to add an employee, but that's it, the edition of the day value is not updated and I also have no increment of the DaySalesman tables.
My models:
class Day < ApplicationRecord
belongs_to :goal
has_many :day_salesmen, dependent: :destroy
has_many :salesmen, through: :day_salesmen
validates_presence_of :date_day, :goal_id
accepts_nested_attributes_for :day_salesmen
end
class DaySalesman < ApplicationRecord
belongs_to :day
belongs_to :salesman
accepts_nested_attributes_for :salesman
end
class Salesman < ApplicationRecord
belongs_to :company
has_many :goal_salesmen, dependent: :destroy
has_many :goals, through: :goal_salesmen
has_many :day_salesmen, dependent: :destroy
has_many :days, through: :day_salesmen
end
Below are my controllers and the result of my controllers:
class DaysController < ApplicationController
before_action :find_day, only: [:show, :edit, :update]
before_action :find_company, only: [:show, :edit]
def index
#day = current_owner.companies.find(params[:company_id]).goal.find(params[:goal_id]).days
end
def show
end
def edit
#dayup = Day.new
#day_salesmen = #dayup.day_salesmen.build
#salesman = #day_salesmen.build_salesman
end
def update
if #day.update(params_day)
flash[:notice] = "Day updated!"
redirect_to company_salesman_path(:id => #day.id)
else
flash.now[:error] = "Could not update day!"
render :edit
end
end
private
def find_company
#company = Company.find(params[:company_id])
end
def find_day
#day = Day.find(params[:id])
end
def params_day
params.require(:day).permit(:value, day_salesman_attributes: [:id, salesman_attributes:[:id, :name]]).merge(goal_id: params[:goal_id])
end
end
Salesman:
class SalesmenController < ApplicationController
before_action :find_salesman, only: [:edit, :update, :destroy]
def index
#salesmen = current_owner.companies.find(params[:company_id]).salesman
#company = Company.find(params[:company_id])
end
def create
#salesman = Salesman.new(params_salesman)
if #salesman.save
flash[:notice] = "Salesman saved!"
else
flash.now[:error] = "Cannot create salesman!"
render :new
end
end
def update
if #salesman.update(params_salesman)
flash[:notice] = "salesman updated!"
else
flash.now[:error] = "Could not update salesman!"
render :edit
end
end
def destroy
#salesman.destroy
end
private
def find_salesman
#salesman = Salesman.find(params[:id])
end
def params_salesman
params.require(:day).require(:salesman).permit(:name, :id).merge(company_id: params[:company_id])
end
end
My controller day view edit is:
<%= render "shared/sidebar2" %>
<div class="container">
<div class="row">
<div class="col s10 offset-s2">
<div class="row">
<h4>Edit day</h4>
<%= form_for(#dayup, url: company_salesmen_path) do |f| %>
<%= f.label :value_of_day %>
<%= f.number_field :value %>
<%= f.fields_for :day_salesman do |ff| %>
<%= f.fields_for :salesman do |fff| %>
<%= fff.label :names_of_salesmen %>
<%= fff.text_field :name %>
<% end %>
<% end %>
<%= f.submit "Create" %>
<% end %>
</div>
</div>
</div>
</div>
My log when I click the submit button on this view is:
Started POST "/companies/1/salesmen" for 172.26.0.1 at 2017-10-31 22:11:56 +0000
Cannot render console from 172.26.0.1! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by SalesmenController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"CQaRlVPYsPK8ilOQJCdw04htgXFkUQOKEVsOIDAmRXOM1X3QO+HfOzY2PGnmItMTK9jRj0YFZDYRJPg7qBV27A==", "day"=>{"value"=>"100", "salesman"=>{"name"=>"Renata"}}, "commit"=>"Create", "company_id"=>"1"}
[1m[36mOwner Load (0.7ms)[0m [1m[34mSELECT "owners".* FROM "owners" WHERE "owners"."id" = $1 ORDER BY "owners"."id" ASC LIMIT $2[0m [["id", 1], ["LIMIT", 1]]
[1m[35m (12.4ms)[0m [1m[35mBEGIN[0m
[1m[36mCompany Load (0.4ms)[0m [1m[34mSELECT "companies".* FROM "companies" WHERE "companies"."id" = $1 LIMIT $2[0m [["id", 1], ["LIMIT", 1]]
[1m[35mSQL (111.1ms)[0m [1m[32mINSERT INTO "salesmen" ("name", "company_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id"[0m [["name", "Renata"], ["company_id", 1], ["created_at", "2017-10-31 22:11:56.344478"], ["updated_at", "2017-10-31 22:11:56.344478"]]
[1m[35m (36.3ms)[0m [1m[35mCOMMIT[0m
No template found for SalesmenController#create, rendering head :no_content
Completed 204 No Content in 436ms (ActiveRecord: 161.0ms)
I wanted to know how through this day's edit form I can update the value for day, create a new employee and associate it to that day through the Daysalesmen table.

Cannot create answer through word by using accepts_nested_attributes_for

I am newbie on RoR. I try to create answer through word controller by using accepts_nested_attributes_for but when I click submit button, I get nothing and button got disable.
Here is my code.
word.rb
class Word < ApplicationRecord
belongs_to :category
belongs_to :exam
has_many :answers, dependent: :destroy
accepts_nested_attributes_for :answers
has_many :exam_words, dependent: :destroy
scope :alphabet, ->{order :content}
end
answer.rb
class Answer < ApplicationRecord
belongs_to :wordscope :alphabel, ->{order "content"}
validates :content, presence: true
end
new.html.erb
<% provide(:title, "Create word" )%>
<h1></h1>
<%= form_for #word do |f| %>
<%= f.label :word_content %>
<%= f.text_field :content, class: "form-control" %>
<%= f.fields_for :answers do |answer| %>
<%= answer.label :answer_content %>
<%= answer.text_area :content, class: "form-control" %>
<%= answer.label :is_correct %>
<%= answer.check_box :is_correct %>
<%end%>
<%= f.submit "create", class: "btn btn-primary"%>
<%end%>
words_controller.rb
class WordsController < ApplicationController
before_action :load_category, except: [:show, :new]
def index
#words = #category.words.includes(:answers).paginate(page: params[:page])
end
def new
#word = Word.new
#word.answers.new
end
def show
#word = Word.find_by_id(params[:id])
session[:w_id] = #word.id
end
def create
#word = #category.words.new(word_params)
#word.category_id = session[:cat_id]
#word.exam_id = 1
if #word.save
redirect_to category_path(session[:cat_id])
end
end
def destroy
#word = Word.find(params[:id])
if #word.present?
#word.destroy
end
redirect_to :back
end
def edit
#word = Word.find(params[:id])
end
def update
#word = Word.find(params[:id])
if #word.update_attributes(word_params)
flash[:success] = "Updated"
redirect_to category_path(session[:cat_id])
else
render 'edit'
end
end
private
def word_params
params.require(:word).permit :content,
answers_attributes: [:id, :content, :is_correct]
end
def load_category
#category = Category.find_by id: session[:cat_id]
unless #category
flash[:danger] = t "category_not_found"
redirect_to categories_path
end
end
end
This is what i get in server in terminal
Started POST "/words" for 127.0.0.1 at 2016-11-29 14:52:26 +0000
Processing by WordsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"qr4qCFAh6omymmgJK7aOjZO0HFtkyT3uwB0KGl6EL60MOipdCFgS0l+XwEi7adhPt1uF1TL2RdRGwsK79FX3iw==", "word"=>{"content"=>"new", "answers_attributes"=>{"0"=>{"content"=>"moi", "is_correct"=>"1"}}}, "commit"=>"create"}
Category Load (0.9ms) SELECT "categories".* FROM "categories" WHERE "categories"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
(0.2ms) begin transaction
Exam Load (0.3ms) SELECT "exams".* FROM "exams" WHERE "exams"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
(0.4ms) rollback transaction
No template found for WordsController#create, rendering head :no_content
Completed 204 No Content in 48ms (ActiveRecord: 2.7ms)
This is what show in my local web
==============SOLVED========================
I just find out how to solve, I forgot optional: true in answer.rd.
class Answer < ApplicationRecord
belongs_to :word, optional: true
scope :alphabel, ->{order "content"}
validates :content, presence: true
end

rails 4 ajax edit form not firing update

I'm trying to update comments on a post in place, and I can get the edit form partial to render correctly, but trying to save does nothing--there's no console error, no error in the server logs, and the record isn't saved.
edit.js.erb
$('#comment-<%= #post.id %>-<%= #comment.id %>').find('.comment-content').html("<%= j render partial: 'comments/comment_form', locals: { comment: comment, post: post } %>");
comments/_comment_form.html.erb
<div class="comment-form col-sm-11">
<%= form_for([post, comment], :remote => true) do |f| %>
<%= f.text_area :content, class: "comment_content", id: "comment_content_#{post.id}" %>
</div>
<div class="col-sm-1">
<%= f.submit "Save", class: "btn btn-primary btn-xs" %>
<% end %>
</div>
update.js.erb
$('comment-form').hide();
$('#comment-<%= #post.id %>-<%= #comment.id %>').find('.comment-content').html('<%= #comment.content %>');
routes.rb
resources :users do
end
resources :posts do
resources :comments
end
class Post < ActiveRecord::Base
belongs_to :user
has_many :comments, dependent: :destroy
end
class User < ActiveRecord::Base
has_many :posts, dependent: :destroy
has_many :comments, dependent: :destroy
end
class Comment < ActiveRecord::Base
belongs_to :user
belongs_to :post
end
Below is the last thing in the server log when the edit_post_comment_path link is clicked; literally nothing happens when save is clicked in the edit form partial, and a test alert in update.js.erb doesn't fire.
Started GET "/posts/471/comments/30/edit" for 72.231.138.82 at 2016-07-17 01:25:27 +0000
Processing by CommentsController#edit as JS
Parameters: {"post_id"=>"471", "id"=>"30"}
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT 1 [["id", 2]]
RailsSettings::SettingObject Load (0.2ms) SELECT "settings".* FROM "settings" WHERE "settings"."target_id" = ? AND "settings"."target_type" = ? [["target_id", 2], ["target_type", "User"]]
Post Load (0.1ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" = ? ORDER BY "posts"."created_at" DESC LIMIT 1 [["id", 471]]
Comment Load (0.2ms) SELECT "comments".* FROM "comments" WHERE "comments"."user_id" = ? AND "comments"."id" = ? LIMIT 1 [["user_id", 2], ["id", 30]]
Comment Load (0.1ms) SELECT "comments".* FROM "comments" WHERE "comments"."id" = ? LIMIT 1 [["id", 30]]
User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 2]]
Rendered comments/_comment_form.html.erb (1.2ms)
Rendered comments/edit.js.erb (13.8ms)
Completed 200 OK in 102ms (Views: 34.4ms | ActiveRecord: 1.7ms)
I have similar create, destroy and custom actions (including an update_attributes method) that are firing correctly, so I'm not sure why this form can't submit. Any help is appreciated, I'm very new to js.
Update with the comment controller actions:
class CommentsController < ApplicationController
before_action :set_post
before_action :user_signed_in?, only: [:create, :destroy]
before_action :authenticate_user!, only: [:create, :edit, :new, :destroy, :update]
before_action :correct_user, only: [:edit, :update, :destroy]
...
def edit
#comment = Comment.find(params[:id])
respond_to do |format|
format.js { render 'comments/edit', locals: {comment: #comment, post: #post } }
end
end
def update
#comment = Comment.find(params[:id])
respond_to do |format|
format.js
end
if #comment.update_attributes(comment_params)
#comment.toggle!(:edited)
flash[:success] = "Comment edited!"
redirect_to root_path
else
render 'edit'
end
end
private
def comment_params
params.require(:comment).permit(:content, :user_id, :post_id)
end
def set_post
#post = Post.find(params[:post_id])
end
def correct_user
#comment = current_user.comments.find_by(id: params[:id])
redirect_to root_url if #comment.nil?
redirect_to root_url if #comment.userlocked?
end
end
I've updated the edit form with :method => :put, to no effect, and thanks for the typo catch #Emu.
As you're submitting an edit form, you should define the method in the form like:
<%= form_for([post,comment ], :remote=>true, :method => :put) do |f| %>
Also, in the update.js.erb the following line missing the "." or "#"
$('.comment-form').hide();

has_many belongs_to relationship not passing through params

I am making a small store admin
Product.rb
class Product < ActiveRecord::Base
has_many :product_options
accepts_nested_attributes_for :product_options
end
ProductOption.rb
class ProductOption < ActiveRecord::Base
belongs_to :product
end
products_controller.rb
class Admin::ProductsController < AdminApplicationController
def index
#products = Product.all
end
def new
#product = Product.new
end
def create
#product = Product.new(product_params)
if #product.save
redirect_to admin_products_path
end
#product_option = #product.product_options.create(params[:product_option])
end
def edit
#product = Product.find(params[:id])
end
def update
#product = Product.find(params[:id])
if #product.update(product_params)
redirect_to admin_products_path
end
end
def destroy
#product = Product.find(params[:id])
#product.destroy
flash[:notice] = "#{#product.name} has been deleted."
redirect_to admin_products_path
end
def upload
uploaded_io = params[:id]
File.open(Rails.root.join('public', 'product_pics', uploaded_io.original_filename), 'wb') do |file|
file.write(uploaded_io.read)
end
end
private
def product_params
params.require(:product).permit(:name, :product_id, :position, :product_description, :product_image_type, :product_image, :product_detail, :product_option_id, :option_name, :product_option )
end
end
product_option_controller.rb
class Admin::ProductOptionsController < AdminApplicationController
def index
#product_options = ProductOption.all
end
def new
#product_option = ProductOption.new
end
def create
#product_option = ProductOption.new(product_option_params)
end
def show
#product_option = ProductOption.find(params[:id])
end
end
private
def product_option_params
params.require(:product_option).permit(:option_name, :ranking, :total_redeemed, :product_id)
end
end
_form.html.erb
<%= simple_form_for([:admin, #product] , :html => {:multipart => true}) do |f| %>
<section class="main_content-header">
<div class="main_content-header-wrapper">
<nav class="main_content-breadcrumbs">
<ul class="breadcrumbs">
<li><%= link_to "All Products", admin_products_path %></li>
<h1> Edit Product </h1>
</ul>
</nav>
<div class="main_content-header-save">
<%= link_to "Cancel", admin_products_path, id: "main_content-header-save-cancel" %>
<%= f.submit %>
</div>
</div>
</section>
<div class="main_content-section">
<section class="main_content-section">
<div class="main_content-section-area">
<%= f.input :name %>
<%= f.input :product_description %>
<%= f.input :product_detail %>
<%= f.file_field :product_image %>
<p> If this product has options, enter them below</p>
<%= f.simple_fields_for :product_option, #product_option do |option_form| %>
<%= option_form.input :option_name %>
<% end %>
</div>
</section>
</div>
<% end %>
server output: ... keeps saying that :product_option is not permitted
Started POST "/admin/products" for 127.0.0.1 at 2014-10-15 16:13:25 -0700
Processing by Admin::ProductsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"t96EMVlDND42HuVUzxWuss2bYDVhBokieTqN2Gz3N9I=", "commit"=>"Create Product", "product"=>{"name"=>"cvncvbn", "product_description"=>"cvbn", "product_detail"=>"", "product_option"=>{"option_name"=>"cvnbnvcb"}}}
Unpermitted parameters: product_option
SQL (1.5ms) BEGIN
SQL (0.4ms) INSERT INTO `products` (`created_at`, `name`, `product_description`, `product_detail`, `updated_at`) VALUES (?, ?, ?, ?, ?) [["created_at", "2014-10-15 23:13:25"], ["name", "cvncvbn"], ["product_description", "cvbn"], ["product_detail", ""], ["updated_at", "2014-10-15 23:13:25"]]
(0.4ms) COMMIT
Redirected to http://localhost:3000/admin/products
SQL (0.1ms) BEGIN
SQL (0.2ms) INSERT INTO `product_options` (`product_id`) VALUES (?) [["product_id", 119]]
(0.3ms) COMMIT
Completed 302 Found in 10ms (ActiveRecord: 2.8ms)
Started GET "/admin/products" for 127.0.0.1 at 2014-10-15 16:13:25 -0700
Processing by Admin::ProductsController#index as HTML
Product Load (0.3ms) SELECT `products`.* FROM `products`
Rendered admin/products/index.html.erb within layouts/admin (11.7ms)
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 7 ORDER BY `users`.`id` ASC LIMIT 1
Rendered admin/_header.html.erb (1.4ms)
Rendered admin/_nav.html.erb (0.4ms)
Completed 200 OK in 21ms (Views: 19.8ms | ActiveRecord: 0.6ms)
The record gets saved, so in the products options table there is just the product_id, .. but no other params....have tried a million things over the past 6 hours... so i dont really have a list of all the possible options, .. but if someone can see a glaring mistake your wisdom would be greatly appreciated.
--------------------------------------------------------------------------------------------
I figured it out, i was not using accepts_nested_attributes correctly these are the changes I had to get it all work.
-deleted the product_options controller (it was not needed)
-changed the product_params:
private
def product_params
params.require(:product).permit(:name, :product_id, :position, :product_description, :product_image_type, :product_image, :product_detail, :product_option_id,
:product_options_attributes => [:id, :option_name, :ranking, :total_redeemed, :product_id])
end
end
-deleted this line from the create action of the products controller
#product_option = #product.product_options.create(params[:product_option])
-added this line to the new action of the products controller
#product.product_options.build
-added an s to the ":product_option" in this loop (and deleted the '#product_option")
<%= f.simple_fields_for :product_option, #product_option do |option_form| %>
<%= option_form.input :option_name %>
<% end %>
the main change was adding the S... without it nested attributes was not being called at all
Try something like
def product_params
params.require(:product).permit(:name, :product_id, :position, :product_description, :product_image_type, :product_image, :product_detail, :product_option_id, :option_name, product_option: [:option_name] )
end

Rails 4: Create new records through has_many association

I am trying to create a new record for 'campaign' via the 'customer' as follows. The form submits correctly, however no new campaign record is created for the customer. Any advise would be greatly appreciated.
Models
class Customer::Customer < User
has_one :library, dependent: :destroy
has_many :campaigns, dependent: :destroy
accepts_nested_attributes_for :campaigns, :library, allow_destroy: true
end
class Customer::Campaign < ActiveRecord::Base
belongs_to :customer
end
Customer Controller - Update Method only shown
class Customer::CustomersController < ApplicationController
layout "customer_layout"
def update
session[:return_to] ||= request.referer
#customer = User.find(params[:id])
if #customer.update_attributes(customer_params)
flash[:success] = "Profile updated"
redirect_to #customer
else
flash[:notice] = "Invalid"
redirect_to session.delete(:return_to)
end
end
def customer_params
params.require('customer_customer').permit(:name, :email, :password, :password_confirmation, :country_code, :state_code, :postcode, :first_name, :surname, campaigns_attributes:[:name, :description, :start_date, :complete_date ])
end
end
And the form I am using
<%= form_for #customer do |f| %>
<%= render 'shared/customer_error_messages' %>
<%= f.fields_for :campaign do |builder| %>
<%= builder.label :name, "Campaign Name" %></br>
<%= builder.text_field :name %>
<% end %>
<div class="actions">
<%= f.submit class: "btn btn-large btn-primary"%>
</div>
<% end %>
And the console output (with error, is as follows)
Started PATCH "/customer/customers/38" for 127.0.0.1 at 2014-05-26 23:13:10 +1000
Processing by Customer::CustomersController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"9ChLYna0/VfZSMJOa2yGgvWTT61XkjoYwlVup/Pbbeg=", "customer_customer"=>{"campaign"=>{"name"=>"My new campaign"}}, "commit"=>"Update Customer", "id"=>"38"}
User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = '0e8b4ba6dc957e76948fc22bae57673404deb9fe' LIMIT 1
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", "38"]]
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", "38"]]
Unpermitted parameters: campaign
If this form performs adding only one campaign i guess you should handly add this exect campaign to customer. If you update all campaign model in such way, you should have all your campaigns in array. So it implies another controller action for this.
Another way: to check if params contains field campain and then just add it to customer object:
def update
session[:return_to] ||= request.referer
#customer = User.find(params[:id])
if new_campaign_customer_params.has_key? :campaign
#customer.campaigns << Campaign.new(new_campaign_customer_params)
if #customer.save
flash[:success] = "Profile updated"
redirect_to #customer
else
flash[:notice] = "Invalid"
# you should rerender your view here, set it path
render 'your_view'
end
else
if #customer.update_attributes(customer_params)
flash[:success] = "Profile updated"
redirect_to #customer
else
flash[:notice] = "Invalid"
redirect_to session.delete(:return_to)
end
end
end
def new_campaign_customer_params
params.require('customer_customer').permit(campaign_attributes:[:name, :description, :start_date, :complete_date ])
end
Check this out, not sure it works.
Or maybe it would work how to suggests in comment: change campaigns_attributes => campaign_attributes in customer_params method, and f.fields_for :campaigns in form (belongs to #Nikita Chernov)

Resources