Rails and ancestry - form submits 'parent_id' empty - ruby-on-rails

I've followed Railscast episode #262 tutorial on ancestry. But when I submit my form, the rails server log says that parent_id is empty:
rails server log:
Started POST "/posts/1/comments" for 127.0.0.1 at 2013-09-26 16:14:59 +0200
Processing by CommentsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"9+9U/etsazbrJxwWah/eRD9v3fKBnjpy+y5s+g7N/Bw=", "comment"=>{"parent_id"=>"", "author"=>"some name", "author_email"=>"mail#domain.com", "author_url"=>"", "content"=>"banane"}, "commit"=>"Post Comment", "post_id"=>"1"}
Post Load (0.1ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" = ? LIMIT 1 [["id", "1"]]
(0.1ms) begin transaction
SQL (0.4ms) INSERT INTO "comments" ("author", "author_email", "author_url", "content", "created_at", "post_id", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?) [["author", "some name"], ["author_email", "mail#domain.com"], ["author_url", ""], ["content", "banane"], ["created_at", Thu, 26 Sep 2013 14:14:59 UTC +00:00], ["post_id", 1], ["updated_at", Thu, 26 Sep 2013 14:14:59 UTC +00:00]]
(38.6ms) commit transaction
(0.1ms) begin transaction
(0.1ms) commit transaction
Redirected to http://0.0.0.0:3000/posts/1
Completed 302 Found in 49ms (ActiveRecord: 39.4ms)
comments_controller.rb:
def new
#comment = Comment.new
#comment.parent_id=params[:parent_id]
end
def create
#post = Post.find(params[:post_id])
#comment = #post.comments.create(params[:comment].permit(:author, :author_email, :author_url, :content, :parent_id))
respond_to do |format|
if #comment.save
stuff
else
other stuff
end
end
end
def comment_params
params.require(:comment).permit(...some stuff..., :parent_id)
end
comment.rb:
class Comment < ActiveRecord::Base
belongs_to :post
has_ancestry
end
post.rb:
class Post < ActiveRecord::Base
belongs_to :user
has_many :comments, :dependent => :destroy
accepts_nested_attributes_for :comments
end
views/posts/show.html.erb:
<% #post.comments.each do |comment| %>
<%= show some stuff %>
<%= link_to (post_path(:anchor => "respond", :parent_id => comment)) do%>
<%= "Reply"%>
<% end %>
<% end %>
<%= render 'comments/comment_form'%>
_comment_form.html.erb:
<%= form_for [#post, #post.comments.build], html: { :id => "commentform"} do |f| %>
<%= f.hidden_field :parent_id %>
<%= some fields %>
<%= f.submit "Post Comment"%>
Rails debug info:
--- !ruby/hash:ActionController::Parameters
parent_id: '17'
action: show
controller: posts
id: '1'
I guess somethings wrong with my create method in the CommentsController, but I can't figure out what's missing. So, I got this working. I was submitting the form from my posts/show view, so I had to call #comment = Comment.new(:parent_id => params[:parent_id]) in the show action of the post-controller as well.

If you are using Rails >3.0.0 try this in your comments controller:
#comment = Comment.new
#comment.parent_id=params[:parent_id]
instead of
#comment = Comment.new(:parent_id => params[:parent_id])

Add :parent_id to comment_params in the comments controller.

Related

Rails4: Why insert a new record when delete a image uploaded with carrierwave?

When I delete a image which was uploaded using carrierwave, a new record is inserted at the same time.
How can I avoid inserting a new record?
article has many photo.
sqlite> .schema photos
CREATE TABLE "photos" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "articl_id" integer, "image" varchar(255), "created_at" datetime, "updated_at" datetim);
The id 93 and 94 exist before deleting photo.
sqlite> select * from photos;
93|27|DSCN0722_070.JPG|2014-09-07 01:59:03.320092|2014-09-07 01:59:03.320092
94|27|DSCN0725_070.JPG|2014-09-07 01:59:03.332093|2014-09-07 01:59:03.332093
When I checked check box to delete id=93 and submitted, id=93 is deleted I expected but a new record id=95 is inserted with no image, I'm not sure.
sqlite> select * from photos;
94|27|DSCN0725_070.JPG|2014-09-07 01:59:03.332093|2014-09-07
95|27||2014-09-07 02:01:58.634119|2014-09-07 02:01:58.634119
If there are 3 records, it works (a new record isn't inserted).
But there are 2 records like above, it occurs.
Thanks in advance.
log/development.log
.
.
Started PATCH "/articles/27" for 127.0.0.1 at 2014-09-07 11:01:58 +0900
Processing by ArticlesController#update as HTML
Parameters: {"utf8"=>"笨・, "authenticity_token"=>"xxx=", "article"=>{"category_id"=>"1379", "photos_attributes"=>{"0"=>{"article_id"=>"27", "_destroy"=>"1", "id"=>"93"}, "1"=>{"article_id"=>"27", "_destroy"=>"0", "id"=>"94"}, "2"=>{"article_id"=>"27"}}, "content"=>"test"}, "commit"=>"譖エ譁ー縺吶k", "id"=>"27"}
[1m[35mUser Load (1.0ms)[0m SELECT "users".* FROM "users" WHERE "users"."remember_token" = 'xxxx' LIMIT 1
[1m[36mArticle Load (0.0ms)[0m [1mSELECT "articles".* FROM "articles" WHERE "articles"."user_id" = ? AND "articles"."id" = 27 ORDER BY created_at DESC LIMIT 1[0m [["user_id", 1]]
[1m[35mArticle Load (0.0ms)[0m SELECT "articles".* FROM "articles" WHERE "articles"."id" = ? ORDER BY created_at DESC LIMIT 1 [["id", "27"]]
[1m[36m (0.0ms)[0m [1mbegin transaction[0m
[1m[35mPhoto Load (1.0ms)[0m SELECT "photos".* FROM "photos" WHERE "photos"."article_id" = ? AND "photos"."id" IN (93, 94) [["article_id", 27]]
[1m[36m (0.0ms)[0m [1mSELECT COUNT(*) FROM "photos" WHERE "photos"."article_id" = ?[0m [["article_id", 27]]
#Delete id=93
[1m[35mSQL (0.0ms)[0m DELETE FROM "photos" WHERE "photos"."id" = ? [["id", 93]]
#Why new record is inserted?
[1m[36mSQL (0.0ms)[0m [1mINSERT INTO "photos" ("article_id", "created_at", "updated_at") VALUES (?, ?, ?)[0m [["article_id", 27], ["created_at", Sun, 07 Sep 2014 02:01:58 UTC +00:00], ["updated_at", Sun, 07 Sep 2014 02:01:58 UTC +00:00]]
[1m[35m (5.0ms)[0m commit transaction
Redirected to http://localhost:3000/users/1
Completed 302 Found in 48ms (ActiveRecord: 7.0ms)
\models\article.rb
# encoding: utf-8
class Article < ActiveRecord::Base
belongs_to :user
belongs_to :category
has_many :photos, dependent: :destroy
accepts_nested_attributes_for :photos, reject_if: :all_blank, allow_destroy: true
default_scope -> { order('created_at DESC') }
validates :content, presence: true, length: { maximum: 140 }
validates :user_id, presence: true
validates :category_id, presence: true
validate :check_for_at_least_image
def build_images
(3 - self.photos.size).times {self.photos.build}
end
def check_for_at_least_image
errors.add(:image, "select...") if self.photos.size <= 0
end
end
\models\photo.rb
class Photo < ActiveRecord::Base
belongs_to :article
mount_uploader :image, ImageUploader
end
\view\articles\edit.html.erb
<div class="row">
<div class="span8">
<%= render 'shared/article_form' %>
</div>
</div>
\view\shared\ _article_form.html.erb
<%= form_for(#article) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.hidden_field :category_id %>
<%= f.fields_for :photos do |p| %>
<%= p.hidden_field :article_id %>
<div class="photo">
<% if p.object.image and p.object.image.file %>
<%= image_tag p.object.image.thumb.url %>
<p>article:<%= #article.id %></p>
<p>photo:<%= p.object.id %></p>
<%= p.hidden_field :image_cache if p.object.image_cache %>
<label><%= p.check_box :_destroy %>delete</label>
<% end %>
<%= p.file_field :image %>
</div>
<% end %>
<%= f.text_area :content, placeholder: "Enter content..." %>
</div>
<%= f.submit class: "btn btn-large btn-primary" %>
<% end %>
\controllers\articles_controller.rb
class ArticlesController < ApplicationController
before_action :signed_in_user, only: [:create, :destroy]
before_action :correct_user, only: [:update, :destroy]
.
.
def new
#article = Article.new
#category = Category.find(params[:category])
#article.category_id = #category.id
3.times { #article.photos.build }
end
def create
#article = current_user.articles.build(article_params)
if #article.save
flash[:success] = "article created!"
redirect_to current_user #root_url
else
#article.build_images
render 'new'
end
end
.
.
def edit
#article = Article.find(params[:id])
#article.build_images
end
def update
#article = Article.find(params[:id])
if #article.update(article_params)
redirect_to current_user
else
render 'edit'
end
end
def destroy
#article.destroy
redirect_to root_url
end
private
def article_params
params.require(:article).permit(:content, :category_id, photos_attributes: [:id, :article_id, :image, :image_cache, :_destroy])
end
.
.
end
If you look at your logs attributes for other image are still passed to the update action when you are deleting a image
"article"=>{"category_id"=>"1379", "photos_attributes"=>{"0"=>{"article_id"=>"27", "_destroy"=>"1", "id"=>"93"}, "1"=>{"article_id"=>"27", "_destroy"=>"0", "id"=>"94"}, "2"=>{"article_id"=>"27"}}, "content"=>"test"}, "commit"=>"譖エ譁ー縺吶k", "id"=>"27"}
FIX
You have two options:
a. Don't build a new image in edit action:.
You are building a new image in your edit action which is then passed on to your update method when you submit your form so you can remove this line in edit action and fix your issue
#article.build_images
b. Use a Proc instead of blank_all:
If you look at your code you have
accepts_nested_attributes_for :photos, reject_if: :all_blank, allow_destroy: true
You are using reject_if: :all_blank instead of a Proc, if you look at docs, it says
Passing :all_blank instead of a Proc will create a proc that will reject a record where all the attributes are blank excluding any value for _destroy.
and in your case attributes are still being passed for other image so it's creating a new image for you. You can use a Proc to eliminate this:
accepts_nested_attributes_for :photos, reject_if: proc { |attributes| attributes['image'].blank? }, allow_destroy: true
You are building images for three times always in your article model. When you try to delete image from two images there is also a blank object present for photo that is created by build and when you submit in update action this part #article.update(article_params) add a blank object and also delete an object for photo table. That's why you are getting this issue. Check your params before updating record for photo will solve your issue.

How do I permit date selector attributes in Rails and Formtastic

Latest
I have switched to Simple form. No problem with permitting date attributes there.
Recent attempts
I have put a demo repository on Github illustrating the problem:
This one uses formtastic and displays my problem with:
Unpermitted parameters: date_of_receipt(1i), date_of_receipt(2i), date_of_receipt(3i), date_of_receipt(i)
https://github.com/bigos/permit_date_selector/commit/9f142b79c51e71dca35c988125a2912b83b91972
This one doesn't use formtastic and works fine;
https://github.com/bigos/permit_date_selector/commit/4c53b934ac5cd3f04241bf462e7b677ef5d28335
Initial post
When I try to submit my form I get this message
Unpermitted parameters: date_of_receipt(i)
I have :date_of_receipt in the list of permitted parameters.
My form input selecting the date looks as follows:
<%= f.input :date_of_receipt, as: :date_select %>
Should I give up on formtastic and go back to standard forms?
I've created a fresh Rails app (using Rails 4.1.5 and Formtastic 2.3.1) to try to replicate, and I can't, so I'm closing. Here's what I had:
# Migration
class CreatePosts < ActiveRecord::Migration
def change
create_table :posts do |t|
t.string :title
t.string :body
t.datetime :published_at
t.timestamps
end
end
end
# Model
class Post < ActiveRecord::Base
end
# Controller
class PostsController < ApplicationController
def new
#post = Post.new
end
def create
#post = Post.new(post_params)
if #post.save
redirect_to #post
else
render :new
end
end
def show
#post = Post.find(params[:id])
end
protected
def post_params
params[:post].permit(:title, :body, :published_at)
end
end
# View
<%= semantic_form_for #post do |f| %>
<%= f.inputs do %>
<%= f.input :title %>
<%= f.input :body %>
<%= f.input :published_at %>
<% end %>
<%= f.actions do %>
<%= f.action :submit %>
<% end %>
<% end %>
By simply permitting :published_at, I was able to successfully save a Post into the database with the time I had selected. Here's the development.log:
Started POST "/posts" for 127.0.0.1 at 2014-09-06 21:13:37 +1000
Processing by PostsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"Jv4Pd7aNgvjkCtzrX+gHNeCNfX3L8t6IpEOEAWzdeIo=", "post"=>{"title"=>"sdfgs", "body"=>"sdgfdfg", "published_at(1i)"=>"2019", "published_at(2i)"=>"1", "published_at(3i)"=>"1", "published_at(4i)"=>"00", "published_at(5i)"=>"01"}, "commit"=>"Create Post"}
(0.1ms) begin transaction
SQL (0.2ms) INSERT INTO "posts" ("body", "created_at", "published_at", "title", "updated_at") VALUES (?, ?, ?, ?, ?) [["body", "sdgfdfg"], ["created_at", "2014-09-06 11:13:37.685160"], ["published_at", "2019-01-01 00:01:00 .000000"], ["title", "sdfgs"], ["updated_at", "2014-09-06 11:13:37.685160"]]
(8.8ms) commit transaction
Redirected to http://localhost:3000/posts/3
Completed 302 Found in 12ms (ActiveRecord: 9.1ms)
There's no extra trickery required, this is how you do it :)
When you inspect the element on the page, you will see three different elements for date_select.
model[date_of_receipt(1i)], model[date_of_receipt(2i)], model[date_of_receipt(3i)]
So you will have to permit
date_of_receipt(1i), date_of_receipt(2i), date_of_receipt(3i)
in your controller

RAILS 3.2 - Submit form posts "nil" variable using params

I'm stuck on something that doesn't make sense! I'm simply trying to submit a form with "comments" on a blog post.
Here is my form view:
<%= form_for #comment, :remote => true, :url => forumpost_comments_path(forumpost) do |s| %>
<div class="field">
<%= s.label :content, "Write a comment" %>
<%= s.text_area :content, :rows => "3" %>
</div>
<%= s.submit "Reply"%>
<% end %>
Here is my controller:
def create
#forumpost = Forumpost.find_by_id(params[:forumpost_id])
#comment = #forumpost.comments.build(params[:comment])
#comment.user_id = current_user.id
if #comment.save
redirect_to search_static_pages_path
else
redirect_to search_static_pages_path
end
end
Here is my model:
class Comment < ActiveRecord::Base
attr_accessible :content
belongs_to :user
belongs_to :forumpost
validates :user_id, presence: true
validates :forumpost_id, presence: true
end
And here are my logs:
Started POST "/forumposts/331/comments" for 127.0.0.1 at 2013-12-14 11:41:24 -0800
Processing by CommentsController#create as JS
Parameters: {"utf8"=>"✓", "authenticity_token"=>"3w3WACRYA6JEwvIg9C66k+cR1ZdRSWwA5Z+W0et1sS8=",
"forumpost"=>{"content"=>"test"}, "commit"=>"Reply", "forumpost_id"=>"331"}
(0.1ms) begin transaction
SQL (0.8ms) INSERT INTO "comments" ("content", "created_at", "forumpost_id", "updated_at", "user_id")
VALUES (?, ?, ?, ?, ?) [["content", nil], ["created_at", Sat, 14 Dec 2013 18:58:58 UTC +00:00],
["forumpost_id", 331], ["updated_at", Sat, 14 Dec 2013 18:58:58 UTC +00:00], ["user_id", 1]]
(14.3ms) commit transaction
As you can see, the content portion is nil even though I have filled out the content field and submitted it.
I would really appreciate any guidance on the matter! Thanks!

Nested resource wont create data, rollback transaction right after begin transaction

My problem is that a tag wont be created which is nested in posts.
I have Post which have tags nested in them. Like this
resources :posts do
resources :tags, :only => [:new, :create, :destroy]
end
In my tags controller i have this
class TagsController < ApplicationController
before_filter :authenticate_user!
def new
#post = Post.find(params[:post_id])
#tag = Tag.new
end
def create
#post = Post.find(params[:post_id])
#tag = #post.tags.build(params[:tags])
if #tag.save
flash[:notice] = "Tag created"
redirect_to #tag.post
else
flash[:error] = "Could not add tag at this time"
redirect_to #tag.post
end
end
end
new.html.erb
<%= form_for [#post, #tag] do |f| %>
<% if #tag.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#tag.errors.count, "error") %> prohibited this tag from being saved:</h2>
<ul>
<% #tag.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.text_field :tagable_type, :placeholder => "Type" %>
</div>
<div class="field">
<%= f.text_field :tagable_id, :placeholder => "Id" %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Tag model
class Tag < ActiveRecord::Base
attr_accessible :post_id, :user_id, :tagable_type, :tagable_id
validates :post_id, presence: true
belongs_to :tagable, :polymorphic => true
belongs_to :post
belongs_to :user
end
Post model
class Post < ActiveRecord::Base
attr_accessible :body, :link, :thumbnail, :title, :user_id, :youtube, :youtube_id, :website_name, :image_field
default_scope order: 'posts.active DESC'
has_many :tags, :dependent => :destroy
has_many :comments, :as => :commentable, :dependent => :destroy
belongs_to :user
end
UPDATE:
Now i can create a tag but the tagable_type and tagable_id fields are not being created for some reaseon
Started POST "/posts/18/tags" for 127.0.0.1 at 2013-06-26 15:54:14 +0200
Processing by TagsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"gwpTs0Qqcrre4tH974RrfpaENGZKtSbkJx2U0H67AcM=", "tag"=>{"tagable_type"=>"Player", "tagable_id"=>"2"}, "commit"=>"Create Tag", "post_id"=>"18"}
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
Post Load (0.1ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" = ? ORDER BY posts.active DESC LIMIT 1 [["id", "18"]]
(0.1ms) begin transaction
SQL (0.4ms) INSERT INTO "tags" ("created_at", "post_id", "tagable_id", "tagable_type", "updated_at", "user_id") VALUES (?, ?, ?, ?, ?, ?) [["created_at", Wed, 26 Jun 2013 13:54:14 UTC +00:00], ["post_id", 18], ["tagable_id", nil], ["tagable_type", nil], ["updated_at", Wed, 26 Jun 2013 13:54:14 UTC +00:00], ["user_id", 1]]
(6.9ms) commit transaction
Post Load (0.2ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" = 18 ORDER BY posts.active DESC LIMIT 1
Redirected to http://localhost:3000/posts/18
Completed 302 Found in 15ms (ActiveRecord: 7.9ms)
There is a typo in the create() action of your TagsController:
#tag = #post.tags.build(params[:tags])
The hash used to create the tag should be params[:tag], not params[:tags].

Nested form not saving in rails 3.1

Noob question, I'm sure, but I can't seem to find my mistake. SymptomSets are saving w/ the proper user_id, but the nested symptoms disappear. Note that the user model structure is identical to that in the Rails Tutorial (save that it has_many :symptom_sets)
Models:
class SymptomSet < ActiveRecord::Base
attr_accessible :symptoms, :symptoms_attributes
belongs_to :user
has_many :symptoms, :dependent => :destroy
accepts_nested_attributes_for :symptoms, allow_destroy: true
end
class Symptom < ActiveRecord::Base
attr_accessible :name, :duration, :symptom_set_id
belongs_to :symptom_set
end
Controller:
class SymptomSetsController < ApplicationController
before_filter :signed_in_user, only: [:create, :new]
def new
#symptom_set = SymptomSet.new
3.times do
symptom = #symptom_set.symptoms.build
end
end
def create
#symptom_set = current_user.symptom_sets.build(params[:symptom_sets])
if #symptom_set.save
flash[:success] = "Symptoms submitted!"
redirect_to root_url
else
render 'static_pages/home'
end
end
And the View:
<%= simple_form_for #symptom_set, :html => { :class => 'form-inline' } do |f| %>
<%= f.fields_for :symptoms do |builder| %>
<%= render 'symptom_fields', f: builder %>
<% end %>
<div class="actions"><%= f.submit %></div>
<% end %>
And the partial:
<%= f.input :name,
:collection=> ["Cough", "Fever", "Headache", "Lethargy"],
label: "Symptom",
prompt: "Select a symptom",
:input_html => { :class => "span3" }%>
<%= f.input :duration,
:collection => 1..14,
label: "Duration",
prompt: "How many days?" %>
finally, the rails server console outputs the following:
Parameters: {"utf8"=>"✓", "authenticity_token"=>"s7ksuk40M2r76Nq4PGEEpTpkCECxFniP4TtpfSHszQk=", "symptom_set"=>{"symptoms_attributes"=>{"0"=>{"name"=>"Cough", "_destroy"=>"false", "duration"=>"2"}, "1
"=>{"name"=>"Fever", "_destroy"=>"false", "duration"=>"2"}, "2"=>{"name"=>"", "_destroy"=>"1", "duration"=>""}}}, "commit"=>"Create Symptom set"}
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" ='OH6_nuvySNjd6AbTuDunsw' LIMIT 1
(0.1ms) BEGIN
SQL (0.4ms) INSERT INTO "symptom_sets" ("created_at", "updated_at", "user_id") VALUES ($1, $2, $3)
RETURNING "id" [["created_at", Tue, 05 Feb 2013 21:12:07 UTC +00:00], ["updated_at", Tue, 05 Feb 20
13 21:12:07 UTC +00:00], ["user_id", 1]]
(1.1ms) COMMIT
I'd try changing:
#symptom_set = current_user.symptom_sets.build(params[:symptom_sets])
to:
#symptom_set = current_user.symptom_sets.new(params[:symptom_sets])
I don't know if build would work there.
And also checking the params on the terminal log if it is called symptom_sets and if it's sending the parameters of nested form attributes.
EDIT:
I Really think your param's name would be symptom_set in singular. check that.

Resources