I create user->posts->comments associations, but comments don't work right.When I commented post, comment save to data base, column user_id was recorded (ok), but column post_id is empty.
There is partial _post_list.html.erb
<% #posts.each do |post| %>
<tr>
<td><%= post.title %></td>
<td><%= post.content %></td>
<%= render 'shared/comment' %>
<%= post.user.name %>
</tr></br></br>
<% end %>
There is partial _comment.html.erb
<%= form_for(#comment) do |f| %>
<%= f.text_area :body %><br><br>
<%= f.submit "commented" %>
<% end %>
controller comments_controller
class CommentsController < ApplicationController
def new
#comment = Comment.new
end
def create
#comment = current_user.comments.build(comment_params)
if #comment.save
redirect_to root_url
else
render 'static_pages/home'
end
end
private
def comment_params
params.require(:comment).permit(:body)
end
end
UPD there is server log
Started POST "/posts/6/comments" for 127.0.0.1 at 2014-11-16 23:28:26 +0300
Processing by CommentsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"ZvyHKxSdH0a1rf79yaWmo9N/pD9/YhSQ9Ek8bdMLhOI=", "comment"=>{"body"=>"stackoverflow"}, "commit"=>"commented", "post_id"=>"6"}
User Load (4.9ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = 'b52623cb00671708536fce96c310b5d365128880' LIMIT 1
(0.2ms) begin transaction
SQL (0.6ms) INSERT INTO "comments" ("body", "created_at", "updated_at", "user_id") VALUES (?, ?, ?, ?) [["body", "stackoverflow"], ["created_at", "2014-11-16 20:28:26.544500"], ["updated_at", "2014-11-16 20:28:26.544500"], ["user_id", 5]]
(131.7ms) commit transaction
Redirected to http://localhost:3000/
Completed 302 Found in 152ms (ActiveRecord: 137.4ms)
Started GET "/" for 127.0.0.1 at 2014-11-16 23:28:26 +0300
Processing by StaticPagesController#home as HTML
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = 'b52623cb00671708536fce96c310b5d365128880' LIMIT 1
Rendered shared/_post_form.html.erb (2.4ms)
Post Load (0.4ms) SELECT "posts".* FROM "posts" ORDER BY created_at DESC
Rendered shared/_comment.html.erb (1.8ms)
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 5]]
Rendered shared/_comment.html.erb (2.8ms)
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 1]]
Rendered shared/_comment.html.erb (4.0ms)
CACHE (3.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 1]]
Rendered shared/_comment.html.erb (1.5ms)
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 1]]
Rendered shared/_comment.html.erb (2.9ms)
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 1]]
Rendered shared/_post_list.html.erb (45.3ms)
Rendered static_pages/home.html.erb within layouts/application (52.1ms)
Rendered layouts/_header.html.erb (1.2ms)
Completed 200 OK in 364ms (Views: 347.0ms | ActiveRecord: 4.5ms)
controller static_pages_controller
class StaticPagesController < ApplicationController
def index
end
def show
end
def home
#post = current_user.posts.build
if signed_in?
end
#posts = Post.all
#comment = current_user.comments.build
end
end
view home.html.erb
<%= render 'shared/post_form' %>
<%= render 'shared/post_list' %>
How fix?
sorry for my bad English
You are far from showing enough code to allow us to understand what can happen. But I feel strange that your form does not include somewhere a reference to post.id or whatever you name the identifier for post objects.
The controller will only be able to use :
input fields of the form (here text of comment)
session stored values (user id)
If the current post id is neither in form fields, not in session, the controller will not get id, it you cannot store it in database.
It looks like you are looping through all of your posts and creating a comment form on the same page for each. You may want to set your comment routes up as nested resources by wrapping it within the post resource.
# config/routes.rb
resources :posts do
resources :comments
end
Pass your #post object into the partial like so:
<%= render 'shared/comment', post: post %>
Then you should be able to create your comment form like so:
<%= form_for([post,#comment]) do |f| %>
<%= f.text_area :body %><br><br>
<%= f.submit "commented" %>
<% end %>
By including that post, you are telling the comment which post it belongs to. Don't forget to update your strong parameters in the controller if you are using them.
EDIT: Based on your update, you'll need to add :post_id to the permit at the bottom of our controller.
Related
After pressing the follow/unfollow toggle button, I receive an ActionView::MissingTemplate exception for the _follow.html.erb. I cannot seem to get past this point with the follow/unfollow button. I tried 6 different approaches and none seem to render the correct results for me. How can setup the follow/unfollow toggle button to work correctly in my index/show view??
Server Development Log
Started GET "/u/jimmydean/follow" for 127.0.0.1 at 2018-02-25 00:43:41 -0500
Processing by UsersController#follow as JS
Parameters: {"id"=>"jimmydean"}
User Load (3.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 2], ["LIMIT", 1]]
User Load (1.0ms) SELECT "users".* FROM "users" WHERE "users"."slug" = $1 LIMIT $2 [["slug", "jimmydean"], ["LIMIT", 1]]
(0.0ms) BEGIN
SQL (1.0ms) INSERT INTO "notifications" ("user_id", "actor_id", "notify_type", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["user_id", 1], ["actor_id", 2], ["notify_type", "follow"], ["created_at", "2018-02-25 05:43:42.022447"], ["updated_at", "2018-02-25 05:43:42.022447"]]
(0.0ms) COMMIT
Completed 500 Internal Server Error in 1039ms (ActiveRecord: 5.0ms)
ActionView::MissingTemplate (Missing template users/follow, application/follow with {:locale=>[:en], :formats=>[:js, :html], :variants=>[], :handlers=>[:raw, :erb, :html, :builder, :ruby, :slim, :coffee, :jbuilder]}. Searched in:
index.html.erb
<div class="col-md-4">
<div class="others-like-me-box">
<div class="others-like-me-box-header user">
<%= render partial: 'users/shared/follow', locals: {users: #users} %>
</div>
</div>
</div>
_follow.html.erb
<ul class="list-unstyled">
<% #users.each do |user| %>
<li>
<div class="media">
<%= user_avatar_dashboard(user) %>
<div class="media-body">
<h6 class="mt-0 mb-1"><%= fa_icon 'user-o' %><strong> <%= link_to user.username, user %></strong></h6>
<div class="cool-ppl-to-follow-btn-pos">
<% if current_user.id != user.id %>
<% if user.followed_by?(current_user) %>
<%= link_to 'Unfollow', unfollow_user_path(user), class: 'btn btn-outline-danger', remote: true %>
<% else %>
<%= link_to 'Follow', follow_user_path(user), class: 'btn btn-outline-success', remote: true %>
<% end %>
<% end %>
</div>
</div>
</div>
</li>
<% end %>
</ul>
users_controller.rb
def follow
#user = User.friendly.find(params[:id])
if current_user
current_user.follow(#user)
end
respond_to do |format|
format.js
end
end
def unfollow
#user = User.friendly.find(params[:id])
if current_user
current_user.stop_following(#user)
end
respond_to do |format|
format.js
end
end
def block
#user = User.friendly.find(params[:id])
if current_user
current_user.block(#user)
end
respond_to do |format|
format.js
end
end
def unblock
#user = User.friendly.find(params[:id])
if current_user
current_user.unblock(#user)
end
respond_to do |format|
format.js
end
end
routes.rb
resources :users, only: [:show, :index, :update], path: 'u' do
get 'users/:username' => 'users#show'
patch 'users/:username', to: 'users#update'
member do
get :follow
get :unfollow
get :block
get :unblock
end
end
follow.js.erb
<% if #user.followed_by?(current_user) %>
$("#user-<%= #user.id %>").html("<%= link_to 'Unfollow', unfollow_user_path(#user), remote: true %>")
<% else %>
$("#user-<%= #user.id %>").html("<%= link_to 'Follow', follow_user_path(#user), remote: true %>")
<% end %>
UPDATE
When I click the follow button, the state doesn't change, nor does the user actually follow the target user. My server log shows this below.
Started GET "/u/jimmydean/follow" for 127.0.0.1 at 2018-02-25 12:01:30 -0500
Processing by UsersController#follow as JS
Parameters: {"id"=>"jimmydean"}
User Load (1.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 2], ["LIMIT", 1]]
User Load (1.0ms) SELECT "users".* FROM "users" WHERE "users"."slug" = $1 LIMIT $2 [["slug", "jimmydean"], ["LIMIT", 1]]
(0.0ms) BEGIN
SQL (75.1ms) INSERT INTO "notifications" ("user_id", "actor_id", "notify_type", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["user_id", 1], ["actor_id", 2], ["notify_type", "follow"], ["created_at", "2018-02-25 17:01:30.780542"], ["updated_at", "2018-02-25 17:01:30.780542"]]
(151.1ms) COMMIT
Rendering users/follow.js.erb
DEPRECATION WARNING: Setting custom parent classes is deprecated and will be removed in future versions. (called from parent_class_name at C:/Ruby24-x64/lib/ruby/gems/2.4.0/bundler/gems/acts_as_follower-c5ac7b9601c4/lib/acts_as_follower/follower_lib.rb:10)
Follow Load (0.0ms) SELECT "follows".* FROM "follows" WHERE "follows"."followable_id" = $1 AND "follows"."followable_type" = $2 AND "follows"."blocked" = $3 AND "follows"."follower_id" = $4 AND "follows"."follower_type" = $5 ORDER BY "follows"."id" ASC LIMIT $6 [["followable_id", 1], ["followable_type", "User"], ["blocked", "f"], ["follower_id", 2], ["follower_type", "User"], ["LIMIT", 1]]
Rendered users/follow.js.erb (4.0ms)
Completed 200 OK in 1399ms (Views: 1102.6ms | ActiveRecord: 228.2ms)
For UsersController#follow to automatically find the unobtrusive JS partial, it should also be placed within the users folder (i.e. app/views/users/follow.js.erb).
Your code looks fine, but since your partial is in users/shared/_follow.html.erb, you might have accidentally placed the JS partial in users/shared as well.
My controller code is like these:
def edit
#user = User.find params[:id]
end
def update
#user = User.find params[:id]
if #user.update_attributes(params[:user])
flash[:notice] = "success!"
else
flash[:notice] = "fail!"
end
end
attr_accessor :username, :introduction, :first_name, :last_name
private
def user_params
params.require(:user).permit(:username, :introduction, :first_name, :last_name)
end
View:
<%= form_for #user, :url =>edit_path(#user), :method => :PUT do |f| %>
<%= f.label :username %><br>
<%= f.text_field :username %>
<br>
<%= f.label :Introduction %><br>
<%= f.text_area :introduction %>
<br>
<%= f.label :FirstName %><br>
<%= f.text_field :first_name %>
<br>
<%= f.label :LastName %><br>
<%= f.text_field :last_name %>
<br>
<%= f.submit "Save changes"%><% end %>
And the terminal is:
Started PUT "/profile/1/edit" for 127.0.0.1 at 2017-12-06 04:30:05 -0500
Processing by ProfileController#edit as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"eBvvAG892DTOFzYuFTKPCgbOuSQXB8BVOub7A8CgaPHLW2vaBFMpUGNHhgYZednfd5pqICCy1DykIarD7QYtIg==", "user"=>{"username"=>"aaa", "introduction"=>"aaaaa", "first_name"=>"a", "last_name"=>"a"}, "commit"=>"Save changes", "id"=>"1"}
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT 1 [["id", 1]]
Notification Load (0.1ms) SELECT "notifications".* FROM "notifications"
Chat Exists (0.0ms) SELECT 1 AS one FROM "chats" WHERE "chats"."sender_id" = ? LIMIT 1 [["sender_id", 1]]
Chat Exists (0.0ms) SELECT 1 AS one FROM "chats" WHERE "chats"."recip_id" = ? LIMIT 1 [["recip_id", 1]]
User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 1]]
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", "1"]]
Rendered profile/edit.html.erb within layouts/game (1.5ms)
User Load (0.2ms) SELECT "users".* FROM "users"
Completed 200 OK in 32ms (Views: 28.5ms | ActiveRecord: 0.5ms)
But database is not updating:
1|du.1#osu.edu|$2a$11$2WHUjqQHU1gtlzw3ObXgVeE7dGG1qby2tLmATeoUyMnh1cg5wXv86||||3|2017-12-06 08:43:44.469588|2017-12-06 05:32:19.252680|127.0.0.1|127.0.0.1|2017-12-05 17:04:39.689636|2017-12-06 08:43:44.470487||1970-1-1|||This guy is lazy. Without an Introduction.|
Try to use safe user_params instead of params[:user]:
if #user.update_attributes(user_params)
# ...
BTW you probably don't need attr_accessor :username, :introduction, :first_name, :last_name line in your controller.
Something is definitely askew. Look here:
Started PUT "/profile/1/edit" for 127.0.0.1 at 2017-12-06 04:30:05 -0500
You're doing a PUT to /profile/1/edit. Conventionally, you would do a GET to /profile/1/edit which would map to the edit action of your ProfileController. So, perhaps you have your routes mis-configured because I would normally expect that to throw an error. Instead (if your console output is correct), PUT "/profile/1/edit" is mapping to the edit action of your ProfileController, as you can see here:
Processing by ProfileController#edit as HTML
And, naturally, edit doesn't do any updating:
def edit
#user = User.find params[:id]
end
So, no changes to your database.
By the way, are you using Devise or something like that? As you can see, you're loading your user twice:
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT 1 [["id", 1]]
...
User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 1]]
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", "1"]]
So I wonder if, in edit,
def edit
#user = User.find params[:id]
end
#user = User.find params[:id] is even needed.
I am stumped as to why this isn't working. I have a review system, and a link to create a new review passing 2 attributes; user_id and gigid. Both id's are being generated as integers but when I save the review, the gigid saves as 'nil' rather than the integer.
View:
<%= link_to 'Click here to rate this user', new_user_review_path(:user_id => request.user.id, :gigid => request.gig.id) %>
Here both ID's are set correctly (according to server output). User_id is the user which is to be reviewed (works correctly) and gigid is a reference for post validation. (works correctly until I try and save)
_form :
<%= simple_form_for([#user, #user.reviews.build]) do |f| %>
<div id="rating-form">
<label>Rating</label>
</div>
<%= f.input :comment %>
<%= f.button :submit %>
<% end %>
Controller:
def new
if user_signed_in?
#review = current_user.reviews.new
else
redirect_to(root_url)
flash[:danger] = "You must log in to rate a user"
end
end
def create
#review = #user.reviews.new review_params
#review.reviewed_id = current_user.id
if #review.save
redirect_to user_path(#user)
else
render 'new'
end
end
private
def review_params
params.require(:review).permit(:rating, :comment, :gigid, :user_id)
end
end
Server output when clicking link:
Started GET "/users/21/reviews/new?gigid=17&locale=en" for 127.0.0.1 at 2016-01-13 18:08:26 +0100
Processing by ReviewsController#new as HTML
Parameters: {"gigid"=>"17", "locale"=>"en", "user_id"=>"21"}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 21]]
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT 1 [["id", 1]]
Rendered reviews/_form.html.erb (4.9ms)
I then add a comment and a rating and click create.
Server output when clicking create:
Started POST "/users/21/reviews?locale=en" for 127.0.0.1 at 2016-01-13 18:10:44 +0100
Processing by ReviewsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"RToZwvodvXxQp1/spEhgemO/oi+4rof8jREuLw27CcEsEBqFWGLeYne1CgH3kvWu9OzAV+bHvOk9g9nq8JMPnw==", "review"=>{"rating"=>"5", "comment"=>"sdfsdfdd"}, "commit"=>"Create Review", "locale"=>"en", "user_id"=>"21"}
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 21]]
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT 1 [["id", 1]]
(0.1ms) begin transaction
SQL (0.7ms) INSERT INTO "reviews" ("rating", "comment", "user_id", "reviewed_id", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?, ?) [["rating", 5], ["comment", "sdfsdfdd"], ["user_id", 21], ["reviewed_id", 1], ["created_at", "2016-01-13 17:10:44.675386"], ["updated_at", "2016-01-13 17:10:44.675386"]]
(93.6ms) commit transaction
I notice that 'gigid' is being completely ignored here, but EVERYTHING else saves fine.
I don't understand why one attribute saves and the other doesn't, any insight would be greatly appreciated!
Your form doesn't have anything for gigid to send it to create action. You can use hidden field in the form like below
<%= simple_form_for([#user, #user.reviews.build]) do |f| %>
<div id="rating-form">
<label>Rating</label>
</div>
<%= f.input :comment %>
<%= f.input :gigid, :as => :hidden, :input_html => { :value => params[:gigid] }
<%= f.button :submit %>
<% end %>
There is no gigid in review params. Look carefully on your params when you are performing POST: "review"=>{"rating"=>"5", "comment"=>"sdfsdfdd"}. Just review and comment. And after it you are doing:
params.require(:review).permit(:rating, :comment, :gigid, :user_id)
This is a follow-up question on Rails 4: new instance is created and saved to database but not displayed in view.
In our Rails 4 app, there are four models:
class User < ActiveRecord::Base
has_many :administrations, dependent: :destroy
has_many :calendars, through: :administrations
end
class Administration < ActiveRecord::Base
belongs_to :user
belongs_to :calendar
end
class Calendar < ActiveRecord::Base
has_many :administrations, dependent: :destroy
has_many :users, through: :administrations
end
class Post < ActiveRecord::Base
belongs_to :calendar
end
Here are the corresponding migrations:
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :first_name
t.string :last_name
t.string :email
t.integer :total_calendar_count
t.integer :owned_calendar_count
t.timestamps null: false
end
end
end
class CreateAdministrations < ActiveRecord::Migration
def change
create_table :administrations do |t|
t.references :user, index: true, foreign_key: true
t.references :calendar, index: true, foreign_key: true
t.string :role
t.timestamps null: false
end
end
end
class CreateCalendars < ActiveRecord::Migration
def change
create_table :calendars do |t|
t.string :name
t.timestamps null: false
end
end
end
class CreatePosts < ActiveRecord::Migration
def change
create_table :posts do |t|
t.references :calendar, index: true, foreign_key: true
t.date :date
t.time :time
t.string :focus
t.string :format
t.string :blog_title
t.text :long_copy
t.text :short_copy
t.string :link
t.string :hashtag
t.string :media
t.float :promotion
t.string :target
t.integer :approval
t.text :comment
t.timestamps null: false
end
end
end
We have the following form to create posts:
<h2>Create a new post</h2>
<%= form_for(#post) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<tr>
<%= f.hidden_field :calendar_id, value: #calendar.id %>
<td class="field"><%= f.date_field :date, placeholder: "When do you want to publish this post?" %></td>
<td class="field"><%= f.time_field :time, placeholder: "What time do you want to publish this post?" %></td>
<td class="field"><%= f.text_field :focus, placeholder: "What is this post about?" %></td>
<td class="field"><%= f.text_field :format, placeholder: "What type of post is this?" %></td>
<td class="field"><%= f.text_field :blog_title, placeholder: "If this post is about a blog post, what is the title of the blog post?" %></td>
<td class="field"><%= f.text_area :long_copy, placeholder: "What is the copy of the post?" %></td>
<td class="field"><%= f.text_area :short_copy, placeholder: "What is the short copy of the post (to be used on Twitter for instance)?" %></td>
<td class="field"><%= f.url_field :link, placeholder: "Which link to you want to embed in this post?" %></td>
<td class="field"><%= f.text_field :hashtag, placeholder: "Which hashtag(s) do you want to you in this post?" %></td>
<td class="field"><%= f.text_field :media, placeholder: "Which media file (image, video) do you want to include in this post?" %></td>
<td class="field"><%= f.number_field :promotion, placeholder: "What advertising budget should be allocated to this post?" %></td>
<td class="field"><%= f.text_field :target, placeholder: "Who do you want to target with this post?" %></td>
<td class="field"><%= f.select(:approval, %w['Approved' 'Needs edits' 'To be deleted'], {prompt: 'How does this post look?'}) %></td>
<td class="field"><%= f.text_area :comment, placeholder: "Any comment?" %></td>
<td><%= f.submit "Create", class: "btn btn-primary" %></td>
</tr>
<% end %>
This form is embedded into the Calendars#Show view, so that as soon as a post is created, it should appear in the corresponding calendar.
Here is our PostsController:
class PostsController < ApplicationController
def create
#post = Post.create(post_params)
if #post.save
redirect_to root_url
else
render root_url
end
end
end
Currently, whenever we submit the form, nothing happens:
All the values stay put in the form
The page is not reloaded (so, no error message appears)
No new #post is added to the database
EDIT: here are the server logs:
Started GET "/calendars/1" for ::1 at 2015-07-07 22:21:07 -0700
Processing by CalendarsController#show as HTML
Parameters: {"id"=>"1"}
Calendar Load (0.1ms) SELECT "calendars".* FROM "calendars" WHERE "calendars"."id" = ? LIMIT 1 [["id", 1]]
Post Exists (0.1ms) SELECT 1 AS one FROM "posts" WHERE "posts"."calendar_id" = ? LIMIT 1 [["calendar_id", 1]]
Post Load (0.1ms) SELECT "posts".* FROM "posts" WHERE "posts"."calendar_id" = ? [["calendar_id", 1]]
Rendered posts/_post.html.erb (0.7ms)
Rendered shared/_error_messages.html.erb (0.0ms)
Rendered shared/_post_form.html.erb (5.1ms)
Rendered calendars/show.html.erb within layouts/application (13.7ms)
Rendered layouts/_shim.html.erb (0.1ms)
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 1]]
Rendered layouts/_header.html.erb (0.9ms)
Rendered layouts/_footer.html.erb (0.4ms)
Completed 200 OK in 145ms (Views: 144.0ms | ActiveRecord: 0.4ms)
EDIT 2: here are the new server logs, after implementing what #miler350 recommended in his answer:
Started POST "/posts" for ::1 at 2015-07-08 09:09:58 -0700
Processing by PostsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"+LS+B2/KiUq09cypZSQnzwj5xHbNnkYR6EC5hfjNCwc3/NfFkbWi3FJe0Zw3Mumsdnubnip5piQHXZ00eV1W2A==", "post"=>{"calendar_id"=>"", "date"=>"2015-08-20", "time"=>"12:04", "focus"=>"Test", "format"=>"Test", "blog_title"=>"Test", "long_copy"=>"Test", "short_copy"=>"Test", "link"=>"http://www.google.com", "hashtag"=>"Test", "media"=>"Test", "promotion"=>"50", "target"=>"Test", "approval"=>"'Approved'", "comment"=>"Test"}, "commit"=>"Create"}
Unpermitted parameter: calendar_id
(0.1ms) begin transaction
SQL (0.7ms) INSERT INTO "posts" ("date", "time", "focus", "format", "blog_title", "long_copy", "short_copy", "link", "hashtag", "media", "promotion", "target", "approval", "comment", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) [["date", "2015-08-20"], ["time", "2000-01-01 12:04:00.000000"], ["focus", "Test"], ["format", "Test"], ["blog_title", "Test"], ["long_copy", "Test"], ["short_copy", "Test"], ["link", "http://www.google.com"], ["hashtag", "Test"], ["media", "Test"], ["promotion", 50.0], ["target", "Test"], ["approval", 0], ["comment", "Test"], ["created_at", "2015-07-08 16:09:58.605712"], ["updated_at", "2015-07-08 16:09:58.605712"]]
(0.6ms) commit transaction
(0.0ms) begin transaction
(0.0ms) commit transaction
Redirected to http://localhost:3000/
Completed 302 Found in 9ms (ActiveRecord: 1.5ms)
Started GET "/" for ::1 at 2015-07-08 09:09:58 -0700
Processing by StaticPagesController#home as HTML
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 1]]
Rendered static_pages/home.html.erb within layouts/static_pages (1.8ms)
Rendered layouts/_shim.html.erb (0.0ms)
Rendered layouts/_static_header.html.erb (1.0ms)
Rendered layouts/_footer.html.erb (0.3ms)
Completed 200 OK in 148ms (Views: 147.5ms | ActiveRecord: 0.1ms)
Started GET "/users/1" for ::1 at 2015-07-08 09:10:02 -0700
Processing by UsersController#show as HTML
Parameters: {"id"=>"1"}
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 1]]
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 1]]
Rendered shared/_error_messages.html.erb (0.7ms)
Rendered shared/_calendar_form.html.erb (5.0ms)
Administration Exists (0.5ms) SELECT 1 AS one FROM "administrations" WHERE "administrations"."user_id" = ? LIMIT 1 [["user_id", 1]]
Administration Load (0.5ms) SELECT "administrations".* FROM "administrations" WHERE "administrations"."user_id" = ? [["user_id", 1]]
Calendar Load (0.1ms) SELECT "calendars".* FROM "calendars" WHERE "calendars"."id" = ? LIMIT 1 [["id", 1]]
Calendar Load (0.1ms) SELECT "calendars".* FROM "calendars" WHERE "calendars"."id" = ? LIMIT 1 [["id", 2]]
Calendar Load (0.1ms) SELECT "calendars".* FROM "calendars" WHERE "calendars"."id" = ? LIMIT 1 [["id", 3]]
Calendar Load (0.1ms) SELECT "calendars".* FROM "calendars" WHERE "calendars"."id" = ? LIMIT 1 [["id", 4]]
Calendar Load (0.1ms) SELECT "calendars".* FROM "calendars" WHERE "calendars"."id" = ? LIMIT 1 [["id", 5]]
Rendered administrations/_administration.html.erb (4.1ms)
Rendered users/show.html.erb within layouts/application (32.1ms)
Rendered layouts/_shim.html.erb (0.3ms)
Rendered layouts/_header.html.erb (0.9ms)
Rendered layouts/_footer.html.erb (0.7ms)
Completed 200 OK in 150ms (Views: 135.3ms | ActiveRecord: 1.8ms)
Started GET "/calendars/1" for ::1 at 2015-07-08 09:10:04 -0700
Processing by CalendarsController#show as HTML
Parameters: {"id"=>"1"}
Calendar Load (0.1ms) SELECT "calendars".* FROM "calendars" WHERE "calendars"."id" = ? LIMIT 1 [["id", 1]]
Post Exists (0.1ms) SELECT 1 AS one FROM "posts" WHERE "posts"."calendar_id" = ? LIMIT 1 [["calendar_id", 1]]
Post Load (0.1ms) SELECT "posts".* FROM "posts" WHERE "posts"."calendar_id" = ? [["calendar_id", 1]]
Rendered posts/_post.html.erb (1.1ms)
Rendered shared/_error_messages.html.erb (0.0ms)
Rendered shared/_post_form.html.erb (5.3ms)
Rendered calendars/show.html.erb within layouts/application (13.9ms)
Rendered layouts/_shim.html.erb (0.1ms)
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 1]]
Rendered layouts/_header.html.erb (0.8ms)
Rendered layouts/_footer.html.erb (0.3ms)
Completed 200 OK in 113ms (Views: 111.2ms | ActiveRecord: 0.4ms)
EDIT 3: here are the server logs when I add :calendar_id to the permitted post_params in the PostsControllers:
Started GET "/calendars/1" for ::1 at 2015-07-08 11:07:39 -0700
Processing by CalendarsController#show as HTML
Parameters: {"id"=>"1"}
Calendar Load (0.1ms) SELECT "calendars".* FROM "calendars" WHERE "calendars"."id" = ? LIMIT 1 [["id", 1]]
Post Exists (0.2ms) SELECT 1 AS one FROM "posts" WHERE "posts"."calendar_id" = ? LIMIT 1 [["calendar_id", 1]]
Post Load (0.2ms) SELECT "posts".* FROM "posts" WHERE "posts"."calendar_id" = ? [["calendar_id", 1]]
Rendered posts/_post.html.erb (0.7ms)
Rendered shared/_error_messages.html.erb (0.0ms)
Rendered shared/_post_form.html.erb (5.2ms)
Rendered calendars/show.html.erb within layouts/application (17.9ms)
Rendered layouts/_shim.html.erb (0.0ms)
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 1]]
Rendered layouts/_header.html.erb (0.8ms)
Rendered layouts/_footer.html.erb (0.3ms)
Completed 200 OK in 160ms (Views: 147.4ms | ActiveRecord: 0.8ms)
Where could the problem be coming from: the models, the form, the controller, or somewhere else?
You have to create your post params.
class PostsController < ApplicationController
def create
#post = Post.create(post_params)
if #post.save
redirect_to root_url
else
render root_url
end
end
protected
def post_params
params.require(:post).permit(:date, :time, :focus....) #put all columns that you want to submit via form here.
end
end
What you are getting is most likely a validation error because you probably require at least one field to be submitted for your post. When rails doesn't receive this, you tell it to render not redirect so you may not notice the reload.
What I want to do is for users to select at least one image (up to 3 images) and to enter f.text_area :content in \views\shared\ _article_form.html.erb.
I added a custom validation check_for_at_least_image in \models\article.rb.
It works (error message is displayed) only in create action, but it doesn't work in update action.
How can I check no image and display error message in update action.
article has many photo.
The logs are as followings.
\log/development.log
no image when new create (error message was displayed as I expect)
Started POST "/articles" for 127.0.0.1 at 2014-09-13 10:40:49 +0900
Processing by ArticlesController#create as HTML
Parameters: {"utf8"=>"笨・, "authenticity_token"=>"xxxx=", "article"=>{"category_id"=>"1379", "photos_attributes"=>{"0"=>{"article_id"=>""}, "1"=>{"article_id"=>""}, "2"=>{"article_id"=>""}}, "content"=>"test"}, "commit"=>"逋サ骭イ縺吶k"}
[1m[35mUser Load (0.0ms)[0m SELECT "users".* FROM "users" WHERE "users"."remember_token" = 'xxxx' LIMIT 1
[1m[36m (0.0ms)[0m [1mbegin transaction[0m
[1m[35m (0.0ms)[0m rollback transaction
[1m[36mCategory Load (1.0ms)[0m [1mSELECT "categories".* FROM "categories" WHERE "categories"."id" = ? LIMIT 1[0m [["id", 1379]]
Rendered shared/_error_messages.html.erb (1.0ms)
Rendered shared/_article_form.html.erb (8.0ms)
Rendered articles/new.html.erb within layouts/application (10.0ms)
Rendered layouts/_header.html.erb (1.0ms)
Rendered layouts/_footer.html.erb (0.0ms)
Completed 200 OK in 63ms (Views: 51.0ms | ActiveRecord: 1.0ms)
delete all(three) images (no error message was displayed)
Started PATCH "/articles/40" for 127.0.0.1 at 2014-09-13 11:10:00 +0900
Processing by ArticlesController#update as HTML
Parameters: {"utf8"=>"笨・, "authenticity_token"=>"xxxx=", "article"=>{"category_id"=>"1379", "photos_attributes"=>{"0"=>{"article_id"=>"40", "_destroy"=>"1", "id"=>"132"}, "1"=>{"article_id"=>"40", "_destroy"=>"1", "id"=>"133"}, "2"=>{"article_id"=>"40", "_destroy"=>"1", "id"=>"134"}}, "content"=>"test"}, "commit"=>"譖エ譁ー縺吶k", "id"=>"40"}
[1m[35mUser Load (0.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" = 40 ORDER BY created_at DESC LIMIT 1[0m [["user_id", 1]]
[1m[35mArticle Load (1.0ms)[0m SELECT "articles".* FROM "articles" WHERE "articles"."id" = ? ORDER BY created_at DESC LIMIT 1 [["id", "40"]]
[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 (132, 133, 134) [["article_id", 40]]
[1m[36m (0.0ms)[0m [1mSELECT COUNT(*) FROM "photos" WHERE "photos"."article_id" = ?[0m [["article_id", 40]]
[1m[35mSQL (1.0ms)[0m DELETE FROM "photos" WHERE "photos"."id" = ? [["id", 132]]
[1m[36mSQL (0.0ms)[0m [1mDELETE FROM "photos" WHERE "photos"."id" = ?[0m [["id", 133]]
[1m[35mSQL (0.0ms)[0m DELETE FROM "photos" WHERE "photos"."id" = ? [["id", 134]]
[1m[36m (4.0ms)[0m [1mcommit transaction[0m
Redirected to http://localhost:3000/users/1
Completed 302 Found in 26ms (ActiveRecord: 7.0ms)
photos table
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);
\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
Just looked at your question and was thinking that may be your validations are running before the destory call on child objects and searched around a bit and found this post, looks like i was right about validations being run before destory. Just going to post pointer related to your question
The problem here is that accepts_nested_attributes_for call destroy for child objects AFTER validation of the parent object. So the user is able to delete an image. Of course, later, when the user will try to edit an article, he/she will get an error – “Select at least one image.”.
Fix:
accepts_nested_attributes_for :photos, reject_if: proc { |attributes| attributes['image'].blank? } , allow_destroy: true #as discussed in your other question you have to use proc to solve your update problem
validate :check_for_at_least_image
def check_for_at_least_image
errors.add(:image, "select...") if photos.reject(&:marked_for_destruction?).size <= 0
end