Posts Rating - Rails - ruby-on-rails

I am implementing rating system in rails for posts.
On viewing a post one can rate the post by clicking radio button.
Below is the code. Consider only the post and rating don't consider tags, topics..
And there is no user in my concept one can rate whenever he needed and it should be added with existing rating of the post.
But, When I am doing this in log it shows the following:
Server log:
Started PATCH "/posts/34" for 127.0.0.1 at 2015-12-08 18:36:55 +0530
Processing by PostsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"l3aae99V424OyKVt5ULmqX2Mcs7DY2GYBskbLyhqqNENDn24ldCDAt4gNcgjESlFR6eaP0vcvrcoOerGE9lH5A==", "post"=>{"rating_ids"=>["5"]}, "commit"=>"Rate", "id"=>"34"}
Post Load (0.0ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" = ? LIMIT 1 [["id", 34]]
CACHE (0.0ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" = ? LIMIT 1 [["id", "34"]]
(0.0ms) begin transaction
SQL (4.0ms) INSERT INTO "ratings" ("star", "post_id", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["star", 5], ["post_id", 34], ["created_at", "2015-12-08 13:06:55.626133"], ["updated_at", "2015-12-08 13:06:55.626133"]]
(216.0ms) commit transaction
(0.0ms) begin transaction
Rating Load (1.0ms) SELECT "ratings".* FROM "ratings" WHERE "ratings"."id" = ? LIMIT 1 [["id", 5]]
Rating Load (0.0ms) SELECT "ratings".* FROM "ratings" WHERE "ratings"."post_id" = ? [["post_id", 34]]
SQL (2.0ms) UPDATE "ratings" SET "post_id" = NULL WHERE "ratings"."post_id" = ? AND "ratings"."id" IN (4, 25) [["post_id", 34]]
SQL (3.0ms) UPDATE "ratings" SET "post_id" = ?, "updated_at" = ? WHERE "ratings"."id" = ? [["post_id", 34], ["updated_at", "2015-12-08 13:06:55.878147"], ["id", 5]]
(170.0ms) commit transaction
Redirected to http://localhost:3000/topics/9
Completed 302 Found in 489ms (ActiveRecord: 397.0ms)
where it changes the post.id to NULL
SQL (2.0ms) UPDATE "ratings" SET "post_id" = NULL WHERE "ratings"."post_id" = ? AND "ratings"."id" IN (4, 25) [["post_id", 34]]
I don't know how this happens and how to overcome this So, Please help.
It changes the Rating database as below:
1st column: id, 2nd column: star, 3rd column: post_id
1,1,NULL
2,2,NULL
3,3,NULL
4,4,NULL
5,5,34
6,4,NULL
7,1,NULL
8,1,NULL
9,5,NULL
10,1,NULL
11,5,NULL
12,1,NULL
13,4,NULL
14,3,NULL
15,4,NULL
16,4,NULL
17,4,NULL
18,2,NULL
19,1,NULL
20,5,NULL
21,3,NULL
Post model:
class Post < ActiveRecord::Base
belongs_to :topic
has_many :comments
has_and_belongs_to_many :tags
has_many :ratings
end
Rating model:
class Rating < ActiveRecord::Base
belongs_to :post
end
Post show.html.erb
<p id="notice"><%= notice %></p>
<p>
<strong>Name:</strong>
<%= #posts.name %> (
<%= #posts.topic.name %> )
</p>
<p>
<strong>Email:</strong>
<%= #posts.email %>
</p>
<p>
<strong>Message:</strong>
<%= #posts.message %>
</p>
<strong>Tags:</strong>
<% #posts.tags.each do |tag| %>
<div>
<%= tag.name %> <br>
</div>
<% end %>
<br>
<strong>Rating:</strong>
<%= #posts.ratings.group(:star).count %>
<%= form_for #posts do |f| %>
<% (1..5).each do |rating| %>
<%= radio_button_tag "post[rating_ids][]", rating %>
<%= rating %>
<% end %>
<%= f.submit('Rate') %>
<% end %>
<%= link_to 'Comments', post_comments_path(#posts) %>
<%= link_to 'Edit', edit_post_path(#posts) %> |
<%= link_to 'Back', topic_posts_url(#posts.topic) %>
Post controller:
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
# GET /posts
# GET /posts.json
def index
if params[:topic_id].to_i > 0
#topic = Topic.find(params[:topic_id])
#posts = #topic.posts.paginate(page: params[:page], per_page: 10)
else
#posts = Post.eager_load(:topic).paginate(page: params[:page], per_page: 10)
end
end
# GET /posts/1
# GET /posts/1.json
def show
#posts = Post.find(params[:id])
#tags = #posts.tags
#comment = Comment.new(:post => #posts)
end
# GET /posts/new
def new
#topic = Topic.find(params[:topic_id])
#posts = #topic.posts.new
end
# GET /posts/1/edit
def edit
#posts = Post.find(params[:id])
#tags = #posts.tags
end
# POST /posts
# POST /posts.json
def create
#topic = Topic.find(params[:topic_id])
#posts = #topic.posts.build(post_params)
respond_to do |format|
if #posts.save
format.html { redirect_to topic_url(#posts.topic_id), notice: 'Post was successfully created.' }
format.json { render :show, status: :created, location: #posts }
else
format.html { render :new }
format.json { render json: #posts.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /posts/1
# PATCH/PUT /posts/1.json
def update
#posts = Post.find(params[:id])
#tags = #posts.tags
respond_to do |format|
#posts.ratings.create(:star => params[:post][:rating_ids][0].to_i)
if #posts.update(post_params)
format.html { redirect_to topic_url(#posts.topic_id), notice: 'Post was successfully updated.' }
format.json { render :show, status: :ok, location: #posts }
else
format.html { render :edit }
format.json { render json: #posts.errors, status: :unprocessable_entity }
end
end
end
# DELETE /posts/1
# DELETE /posts/1.json
def destroy
#posts.destroy
respond_to do |format|
format.html { redirect_to topic_url(#posts.topic_id), notice: 'Post was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_post
#posts = Post.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def post_params
params.require(:post).permit(:name, :email, :message, :topic_id, {tag_ids:[]}, rating_ids:[])
end
end
I am new to rails and I need to implement this without using any gem..
Please help how it changes the post_id to NULL which I denoted in server log..

This is because after you created a Rating manually then goes #posts.update(rating_ids:[5]), which states that this post only should have rating with id 5, not 5 stars
Plus are you sure want your unauthenticated users to have access to post editing?

Since you save the rating before updating the post change your post_params to:
def post_params
params.require(:post).permit(:name, :email, :message, :topic_id, {tag_ids:[]})
end
As you are saving the rating from the params directly.
However you should consider changing your structure to use something like nested attributes which will automatically save/update ratings.

Related

Rails 5 - has_many through and nested attributes forms

I have two models Request and TableLocation with both having a has_many through relationship joined by RequestLocation table.
I am trying to create a nested form and the table_location data is not being saved to the database.
As you can see the table_locations"=>["1"] parameter is being passed to the create action but not being saved.
Appreciate any help.
Console Output
Started POST "/requests" for 127.0.0.1 at 2017-06-07 10:35:26 -0400
Processing by RequestsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"mHV/xbmdfHmCAsi16KXlW+0bWVSkEo9SRVchdyPpL60o3m3SuKEt4nuUT4PJNEyCsWq3Nj4IWiCMlDbhiPewdA==", "request"=>{"concierge_name"=>"Alex", "concierge_number"=>"954-123-4567", "concierge_email"=>"alex#email.com", "client_name"=>"Adam", "client_number"=>"954-765-4321", "client_email"=>"adam#email.com", "hotel_employee"=>"0", "concierge_service"=>"0", "vip_promoter"=>"0", "arriving_with_client"=>"1", "client_alone"=>"0", "males"=>"", "females"=>"1", "table_minimum"=>"1000", "arrival_time(1i)"=>"2017", "arrival_time(2i)"=>"6", "arrival_time(3i)"=>"7", "arrival_time(4i)"=>"14", "arrival_time(5i)"=>"35", "table_locations"=>["1"], "comments"=>""}, "commit"=>"Submit"}
(0.1ms) BEGIN
SQL (0.4ms) INSERT INTO "requests" ("concierge_name", "concierge_number", "concierge_email", "client_name", "client_number", "client_email", "arriving_with_client", "people", "females", "table_minimum", "arrival_time", "comments", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14) RETURNING "id" [["concierge_name", "Alex"], ["concierge_number", "954-123-4567"], ["concierge_email", "alex#email.com"], ["client_name", "Adam"], ["client_number", "954-765-4321"], ["client_email", "adam#email.com"], ["arriving_with_client", "t"], ["people", 1], ["females", 1], ["table_minimum", 1000], ["arrival_time", "2017-06-07 14:35:00"], ["comments", ""], ["created_at", "2017-06-07 14:35:26.658718"], ["updated_at", "2017-06-07 14:35:26.658718"]]
(0.3ms) COMMIT
Redirected to http://localhost:3000/thanks
Completed 302 Found in 8ms (ActiveRecord: 0.8ms)
app/models/request.rb
class Request < ApplicationRecord
has_many :request_locations
has_many :table_locations, through: :request_locations
end
app/models/table_locations.rb
class TableLocation < ApplicationRecord
has_many :request_locations
has_many :requests, through: :request_locations
end
app/models/request_location.rb
class RequestLocation < ApplicationRecord
belongs_to :request
belongs_to :table_location
end
app/controllers/requests_controller.rb
class RequestsController < ApplicationController
before_action :set_request, only: [:show,
:edit,
:update,
:destroy]
before_action :authenticate_admin!, except: [:index,
:new,
:create]
def index
redirect_to root_path unless admin_signed_in?
#requests = Request.search(params[:term], params[:filter], params[:page])
end
def show
end
def new
#request = Request.new
end
def edit
end
def create
#request = Request.new(request_params)
#request.people = (#request.males || 0) + (#request.females || 0)
respond_to do |format|
if #request.save
format.html { redirect_to thanks_path, notice: 'Request was successfully created.' }
format.json { render :show, status: :created, location: #request }
else
format.html { render :new }
format.json { render json: #request.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #request.update(request_params)
format.html { redirect_to #request, notice: 'Request was successfully updated.' }
format.json { render :show, status: :ok, location: #request }
else
format.html { render :edit }
format.json { render json: #request.errors, status: :unprocessable_entity }
end
end
end
def destroy
#request.destroy
respond_to do |format|
format.html { redirect_to requests_url, notice: 'Request was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_request
#request = Request.find(params[:id])
end
def request_params
params.require(:request).permit(:concierge_name,
:concierge_number,
:concierge_email,
:client_name,
:client_number,
:client_email,
:hotel_employee,
:concierge_service,
:vip_promoter,
:arriving_with_client,
:client_alone,
:people,
:males,
:females,
:table_minimum,
:arrival_time,
:comments,
table_locations: [:id]
)
end
end
app/views/requests/_form.html.erb
...
<% TableLocation.all.each do |t| %>
<%= check_box_tag "request[table_locations][]", t.id, #request.table_locations.include?(t.id) %>
<%= t.location %>
<br />
<% end %>
...
Explanations:
Your request_params permits table_locations: [:id], but this only permits the following format:
Parameters: {"utf8"=>"✓", ... "request"=>{"table_locations"=>{"id"=>"1"}, "comments"=>""}, "commit"=>"Submit"}
but yours is showing to be:
Parameters: {"utf8"=>"✓", ... "request"=>{"table_locations"=>["1"], "comments"=>""}, "commit"=>"Submit"}
therefore, try this: puts request_params inside the create method, and you'll notice that it doesn't have table_locations values (even though you thought it's there, but it's not), because it is not "properly" whitelisted in your strong params request_params.
To be able to associate multiple TableLocations objects to a newly built Request object, the format should be something like below
request = Request.new(table_location_ids: [1,2,3,4,5])
but from your implementation, you're doing it like this (which won't work):
request = Request.new(table_locations: [1,2,3,4,5])
# => this will raise an error:
# ActiveRecord::AssociationTypeMismatch: TableLocation expected, got Fixnum
# however yours didn't raise an error, because it was not whitelisted in the request_params in the first place
Solution:
requests_controller.rb
def request_params
params.require(:request).permit(..., table_location_ids: [])
end
_form.html.erb
<% TableLocation.all.each do |t| %>
<%= check_box_tag "request[table_location_ids][]", t.id %>
<%= t.location %>
<br />
<% end %>
Recommendation:
just in case you don't know yet that you can do the following in this way, I'll be refactoring your code to look something like this:
requests_controller.rb
def create
#table_locations = TableLocation.all
end
_form.html.erb
<%= form_for #request do |f| %>
<% #table_locations.each do |table_location| %>
<%= f.check_box :table_location_ids, multiple: true, table_location.id %>
<% end %>
<% end %>

Form using collection_select, edit action works entirely but create does not

I am using following form and controller. If I create a new notification everything gets saved except the campus_id.
It seems to give the wrong campus parameter although I select a different one from the dropdown. If I edit the same entry afterwards then it does get saved? What is going on and how do I fix it?
The same form is used for the edit and create actions. (it is a partial)
It might be worth noting that I use shallow routes for the campus (has_many) and notifications(belongs_to).
routes.rb
shallow do
resources :campus do
resources :notifications
end
end
Form:
<%= form_for [#campus,#notification] do |f| %>
<% if #notification.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#notification.errors.count, "error") %> prohibited this notification from being saved:</h2>
<ul>
<% #notification.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :post %><br>
<%= f.text_area :post %>
</div>
<div class="field">
<%= f.label :campus %><br>
<%= f.collection_select(:campus_id, Campus.all.order('name ASC'), :id, :name, prompt: true) %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
This is the controller:
class NotificationsController < ApplicationController
before_action :set_notification, only: [:show, :edit, :update, :destroy]
before_action :set_campus, only: [:index, :new, :create]
def index
#notifications = #campus.notification
end
def show
end
def new
#notification = #campus.notification.new
end
def edit
end
def create
#notification = #campus.notification.new(notification_params)
respond_to do |format|
if #notification.save
format.html { redirect_to #notification, notice: 'Notification was successfully created.' }
format.json { render action: 'show', status: :created, location: #notification }
else
format.html { render action: 'new' }
format.json { render json: #notification.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #notification.update(notification_params)
format.html { redirect_to #notification, notice: 'Notification was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #notification.errors, status: :unprocessable_entity }
end
end
end
def destroy
#notification.destroy
respond_to do |format|
format.html { redirect_to campu_notifications_url(1) }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_notification
#notification = Notification.find(params[:id])
end
def set_campus
#campus = Campus.find(params[:campu_id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def notification_params
params.require(:notification).permit(:post, :campus_id)
end
end
If I look at the log I see the wrong parameter is comitted.
Started POST "/campus/1/notifications" for 84.193.153.106 at
2014-09-29 18:29:33 +0000 Started POST "/campus/1/notifications" for
84.193.153.106 at 2014-09-29 18:29:33 +0000 Processing by NotificationsController#create as HTML Processing by
NotificationsController#create as HTML Parameters: {"utf8"=>"_",
"authenticity_token"=>"oNSlEFeukwEj2hIAT89wFdIYwjHO5c8lzBlCqMyk31Y=",
"notification"=>{"post"=>"sdqfdsfd", "campus_id"=>"3"},
"commit"=>"Create Notification", "campu_id"=>"1"} Parameters:
{"utf8"=>"_",
"authenticity_token"=>"oNSlEFeukwEj2hIAT89wFdIYwjHO5c8lzBlCqMyk31Y=",
"notification"=>{"post"=>"sdqfdsfd", "campus_id"=>"3"},
"commit"=>"Create Notification", "campu_id"=>"1"} Campus Load
(0.4ms) SELECT "campus".* FROM "campus" WHERE "campus"."id" = $1
LIMIT 1 [["id", "1"]] Campus Load (0.4ms) SELECT "campus".* FROM
"campus" WHERE "campus"."id" = $1 LIMIT 1 [["id", "1"]] (0.1ms)
BEGIN (0.1ms) BEGIN SQL (28.6ms) INSERT INTO "notifications"
("campus_id", "created_at", "post", "updated_at") VALUES ($1, $2, $3,
$4) RETURNING "id" [["campus_id", 1], ["created_at", Mon, 29 Sep 2014
18:29:34 UTC +00:00], ["post", "sdqfdsfd"], ["updated_at", Mon, 29 Sep
2014 18:29:34 UTC +00:00]] SQL (28.6ms) INSERT INTO "notifications"
("campus_id", "created_at", "post", "updated_at") VALUES ($1, $2, $3,
$4) RETURNING "id" [["campus_id", 1], ["created_at", Mon, 29 Sep 2014
18:29:34 UTC +00:00], ["post", "sdqfdsfd"], ["updated_at", Mon, 29 Sep
2014 18:29:34 UTC +00:00]] (3.5ms) COMMIT (3.5ms) COMMIT
Might want to change your new and create actions like this:
def new
#notification = #campus.notifications.build
end
def create
#notification = #campus.notifications.build(notification_params)
respond_to do |format|
if #notification.save
format.html { redirect_to #notification, notice: 'Notification was successfully created.' }
format.json { render action: 'show', status: :created, location: #notification }
else
format.html { render action: 'new' }
format.json { render json: #notification.errors, status: :unprocessable_entity }
end
end
end
campus.build_notification will instantiate a notification that belongs_to campus. Using new would require you to pass notification[campus_id] as part of your params.

Nested Attribute Image Uploads Not Updating (Rails 4/ Carrierwave)

I'm using this example to create multiple image uploads using Carrierwave Rails 4 multiple image or file upload using carrierwave. For some reason if I edit the Post and try to upload a different image it doesn't update.
listings_controller.rb
class ListingsController < ApplicationController
before_action :set_listing, only: [:show, :edit, :update, :destroy]
before_filter :authenticate_user!, :except => [:show, :index]
def index
#listings = Listing.order('created_at DESC')
respond_to do |format|
format.html
format.json { render json: #listings }
end
end
def show
#image_attachments = #listing.image_attachments.all
end
def new
#listing = Listing.new
#listing.user = current_user
#image_attachment = #listing.image_attachments.build
end
def edit
end
def create
#listing = Listing.new(listing_params)
#listing.created_at = Time.now
#listing.user = current_user
respond_to do |format|
if #listing.save
params[:image_attachments]['image'].each do |a|
#image_attachment = #listing.image_attachments.create!(:image => a, :listing_id => #listing.id)
end
format.html { redirect_to #listing, notice: 'Post was successfully created.' }
else
format.html { render action: 'new' }
format.json { render json: #listing.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #listing.update(listing_params)
flash[:notice] = 'Deal was successfully updated.'
format.html { redirect_to #listing }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #listing.errors, status: :unprocessable_entity }
end
end
end
def destroy
#listing.destroy
respond_to do |format|
format.html { redirect_to listings_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_listing
#listing = Listing.friendly.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def listing_params
params.require(:listing).permit(:condition, :listing_title, :nickname, :listing_size, :listing_price, :user_id, image_attachments_attributes: [:id, :listing_id, :image])
end
end
listing form
<%= form_for(#listing, :html => { :class => 'form', :multipart => true }) do |f| %>
<% if #listing.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#listing.errors.count, "error") %> prohibited this listing from being saved:</h2>
<ul>
<% #listing.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.fields_for :image_attachments do |p| %>
<div>
<%= p.label :image %>
<%= p.file_field :image, :multiple => true, name: "image_attachments[image][]", :class => 'upload' %>
</div>
<% end %>
<div class="actions">
<%= f.submit 'Submit', :class => 'submitButton' %>
</div>
<% end %>
listing.rb
has_many :image_attachments
accepts_nested_attributes_for :image_attachments
Any help? Thanks.
UPDATE
This is the log ouput when I try to update the image field. "about.png" is the new image I'm trying to upload.
Started PATCH "/listings/nike-air-max-90" for 127.0.0.1 at 2014-07-16 11:40:14 -0400
Processing by ListingsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"LU1ADy5JqfuX9CMDtcG/dmGgu9nuvplDQrVixfICsS4=", "listing"=>{"listing_title"=>"Nike Air Max 90", "nickname"=>"", "listing_size"=>"9.5", "listing_price"=>"160", "image_attachments_attributes"=>{"0"=>{"id"=>"1"}}}, "image_attachments"=>{"image"=>[#<ActionDispatch::Http::UploadedFile:0x00000109506810 #tempfile=#<Tempfile:/var/folders/vk/x5f3g8n147z_j39_mzkbfq600000gp/T/RackMultipart20140716-1370-63vlgx>, #original_filename="about.png", #content_type="image/png", #headers="Content-Disposition: form-data; name=\"image_attachments[image][]\"; filename=\"about.png\"\r\nContent-Type: image/png\r\n">]}, "commit"=>"Submit", "id"=>"nike-air-max-90"}
[1m[35mListing Load (0.2ms)[0m SELECT "listings".* FROM "listings" WHERE "listings"."slug" = 'nike-air-max-90' ORDER BY "listings"."id" ASC LIMIT 1
[1m[36mUser Load (0.2ms)[0m [1mSELECT "users".* FROM "users" WHERE "users"."id" = 1 ORDER BY "users"."id" ASC LIMIT 1[0m
[1m[35m (0.1ms)[0m begin transaction
[1m[36mImageAttachment Load (0.1ms)[0m [1mSELECT "image_attachments".* FROM "image_attachments" WHERE "image_attachments"."listing_id" = ? AND "image_attachments"."id" IN (1)[0m [["listing_id", 2]]
[1m[35m (0.1ms)[0m commit transaction
Redirected to http://localhost:3000/listings/nike-air-max-90
Completed 302 Found in 5ms (ActiveRecord: 0.6ms)
Option 1 (Replace all existing attachments with new uploaded ones
In your update action, you are NOT doing what you are doing in create action. Which is this:
params[:image_attachments]['image'].each do |a|
#image_attachment = #listing.image_attachments.create!(:image => a, :listing_id => #listing.id)
end
You can't expect Rails to do this for you magically because this is not a typical use of accepts_nested_attributes feature. In fact, in your current code, you are not using this feature at all.
If you want to make it work with your current code, you will have to delete all existing image_attachments and create the new ones in the update action, like this:
def update
respond_to do |format|
if #listing.update(listing_params)
if params[:image_attachments] && params[:image_attachments]['image']
# delete existing image_attachments
#listing.image_attachments.delete_all
# create new ones from incoming params
params[:image_attachments]['image'].each do |a|
#image_attachment = #listing.image_attachments.create!(:image => a, :listing_id => #listing.id)
end
end
flash[:notice] = 'Deal was successfully updated.'
format.html { redirect_to #listing }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #listing.errors, status: :unprocessable_entity }
end
end
end
This will replace all existing images with new ones, if you upload new ones.
Option 2 (Edit them individually)
If you want to be able to update existing attachments, you will have to modify the edit form to allow updating attachment records individually. Or do it via proper use of accepts_nested_attributes feature. Cocoon is one great gem help you incorporate nested attributes in your forms easily.

Ruby Adding To Database

I am new in Ruby and I have to finish my school project. I have problem because we make one project in 14 people, everyone has his own part. I have to create new appointment but someone used this before and I cannot use this again (I want to add this simple from form). Please help me because I am stuck now, I don't want change someone's code. I render _form51.html.erb from new51.html.erb. Maybe I can use any simple redirect to create51?;> But I don't know how ;(
EDITED:
NOW SOLVED BUT why app create always empty appointment?
Routes.rb:
ZOZ::Application.routes.draw do
resources :refferals do
collection do
get 'new51'
end
member do
get 'show'
end
end
resources :appointments do
collection do
get 'search' #17
get 'search_result' #17
get 'to_confirm' #17
get 'search_not' #57
get 'search_result_not' #57
get 'add_or_edit_not' #57
get 'searchdate'
get 'searchd'
get 'move'
get 'new51'
post :create51
end
member do
put :confirm #17
put :update_not #57
get 'show51'
end
end
resources :clinics do
collection do
get 'index51'
end
member do
get 'show51s'
end
end
resources :doctors do
collection do
get 'index51a'
get 'index51'
get 'search54'
get 'search_result54'
get 'show_harmonogram'
end
member do
get 'show51s'
get 'show51ss'
end
end
resources :patients do
collection do
get 'select51'
get 'index51'
end
member do
get 'show51s'
get 'show51ss'
end
end
get "welcome/index2"
get "welcome/index"
get 'appointments/create'
get 'appointments/move' => 'appointments#move'
post 'appointments/move' => 'appointments#doctors_list'
get 'appointments/move/:id' => 'appointments#doctor_appointments', as: :doctor_appointments
get 'appointments/change_appointment/:id' => 'appointments#change_appointment', as: :change_appointment
get 'appointments/change_doctor_and_appointment/:id' => 'appointments#change_doctor_and_appointment', as: :change_doctor_and_appointment
get 'appointments/success' => 'appointments#success'
# The priority is based upon order of creation:
# first created -> highest priority.
# Sample of regular route:
# match 'products/:id' => 'catalog#view'
# Keep in mind you can assign values other than :controller and :action
# Sample of named route:
# match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase
# This route can be invoked with purchase_url(:id => product.id)
# Sample resource route (maps HTTP verbs to controller actions automatically):
# Sample resource route with options:
# resources :products do
# member do
# get 'short'
# post 'toggle'
# end
#
# collection do
# get 'sold'
# end
# end
# Sample resource route with sub-resources:
# resources :products do
# resources :comments, :sales
# resource :seller
# end
# Sample resource route with more complex sub-resources
# resources :products do
# resources :comments
# resources :sales do
# get 'recent', :on => :collection
# end
# end
# Sample resource route within a namespace:
# namespace :admin do
# # Directs /admin/products/* to Admin::ProductsController
# # (app/controllers/admin/products_controller.rb)
# resources :products
# end
# You can have the root of your site routed with "root"
# just remember to delete public/index.html.
root :to => 'welcome#index'
# See how all your routes lay out with "rake routes"
# This is a legacy wild controller route that's not recommended for RESTful applications.
# Note: This route will make all actions in every controller accessible via GET requests.
# match ':controller(/:action(/:id))(.:format)'
end
_form51.html.erb:
<%= form_for(#appointment) do |f| %>
<% if #appointment.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#appointment.errors.count, "error") %> prohibited this appointment from being saved:</h2>
<ul>
<% #appointment.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :data_godzina_wizyty %><br />
<%=
options = { start_year: 2.year.from_now.year,
end_year: 2013,
include_blank: true,
default: nil }
f.datetime_select :data_godzina_wizyty, options
%>
<!--<input type="text" data-behaviour='datepicker' :data_wizyty > -->
</div>
<div class="field">
<%= f.hidden_field :doctor_id, :value => Doctor.find(session[:current_doctor_id2]).id %>
</div>
<div class="field">
<%= f.hidden_field :patient_id, :value => Patient.find(session[:current_patient_id]).id %>
</div>
<div class="actions">
<%= submit_tag "Utworz wizyte" %>
</div>
<% end %>
New51.html.erb:
<div id="container">
<center>
<h1>Nowa wizyta:</h1>
<p>Sprawdz poprawnosc ponizszych danych a nastepnie uzupelnij formularz.</p>
<h3>Dane lekarza:</h3>
<p>
<strong>Imię lekarza:</strong>
<%= Doctor.find(session[:current_doctor_id2]).imie_lekarza %>
</p>
<p>
<strong>Nazwisko lekarza:</strong>
<%= Doctor.find(session[:current_doctor_id2]).nazwisko_lekarza %>
</p>
<p>
<strong>Specjalizacja lekarza:</strong>
<%= Doctor.find(session[:current_doctor_id2]).specjalizacja %>
</p>
<h3>Dane pacjenta:</h3>
<p>
<strong>Imie:</strong>
<%= Patient.find(session[:current_patient_id]).imie %>
</p>
<p>
<strong>Nazwisko:</strong>
<%= Patient.find(session[:current_patient_id]).nazwisko %>
</p>
<p>
<strong>Pesel:</strong>
<%= Patient.find(session[:current_patient_id]).pesel %>
</p>
<%= render 'form51' %>
<%= link_to 'Wybierz innego lekarza', index51_doctors_path %>
</br>
</center>
</div>
Appointments_Controller:
class AppointmentsController < ApplicationController
before_filter :load_appointment, only: [:show, :update, :edit, :destroy]
before_filter :load_wizard, only: [:new, :edit, :create]
def searchd
end
def move
end
def doctors_list
#doctors = Doctor.where("imie_lekarza like ? or nazwisko_lekarza LIKE ? or specjalizacja LIKE ?", "%#{params[:search]}%", "%#{params[:search]}%", "%#{params[:search]}%")
end
def doctor_appointments
#doctor = Doctor.find(params[:id])
#appointments = #doctor.appointments
end
def change_appointment
#appointment = Appointment.find(params[:id])
end
def change_doctor_and_appointment
#doctors = Doctor.all
#appointment = Appointment.find(params[:id])
end
def success
#notice = flash[:notice]
end
def searchdate
d = params[:date]
data = Date.new(d["(1i)"].to_i, d["(2i)"].to_i, d["(3i)"].to_i)
#appointments = Appointment.scoped
#appointments = #appointments.where(:data_godzina_wizyty => data.beginning_of_day..data.end_of_day)
end
def search_not
end
def search_result_not
#pacjent
#patients = Patient.scoped
#patients = #patients.where(pesel: params[:pesel])
d = params[:date]
if d["(1i)"] != "" and d["(2i)"]. != "" and d["(3i)"] != ""
data = Date.new(d["(1i)"].to_i, d["(2i)"].to_i, d["(3i)"].to_i)
#appointments = #patients.first.appointments.where(:data_godzina_wizyty => data.beginning_of_day..data.end_of_day)
else
#appointments = #patients.first.appointments
end
end
def add_or_edit_not
session['last_search_not'] = request.env["HTTP_REFERER"]
#appointment = Appointment.find(params[:id])
#patient = Patient.find(#appointment.patient_id)
if #appointment.doctor_id != nil
#doctor = Doctor.find(#appointment.doctor_id)
end
if #appointment.refferal_id != nil
#refferal = Refferal.find(#appointment.refferal_id)
end
end
def update_not
#appointment = Appointment.find(params[:id])
#appointment.notatka = params[:notatka]
if #appointment.save
redirect_to session[:last_search_not], notice: 'Notatka zostala zapisana.'
else
redirect_to :back, notice: 'Niestety wystapil blad. Prosze sprubowac pozniej'
end
end
def search
end
def new51
#appointment = Appointment.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #appointment }
end
end
def create51
#appointment = Appointment.new(params[:patient])
respond_to do |format|
if #appointment.save
format.html { redirect_to #appointment, notice: 'Szczegoy wizyty pomyslnie zmodyfikowane!' }
format.json { render json: #appointment, status: :created, location: #appointment }
else
format.html { render action: "new" }
format.json { render json: #appointment.errors, status: :unprocessable_entity }
end
end
end
def search_result
d = params[:date]
data = Date.new(d["(1i)"].to_i, d["(2i)"].to_i, d["(3i)"].to_i)
#szukanie pacjenta
#patients = Patient.scoped
#patients = #patients.where(pesel: params[:pesel])
if params[:imie] != ""
#patients = #patients.where(imie: params[:imie])
end
if params[:nazwisko] != ""
#patients = #patients.where(nazwisko: params[:nazwisko])
end
#szukanie doctora
opcja = 0
#doctors = Doctor.scoped
if params[:imie_lekarza] != ""
#doctors = #doctors.where(imie_lekarza: params[:imie_lekarza])
opcja = 1
end
if params[:nazwisko_lekarza] != ""
#doctors = #doctors.where(nazwisko_lekarza: params[:nazwisko_lekarza])
opcja = 1
end
#zlaczenie
#patient_appo = #patients.first.appointments.where(:data_godzina_wizyty => data.beginning_of_day..data.end_of_day, potwierdzona: false)
if opcja == 1
#doctors_appo = #doctors.first.appointments.where(:data_godzina_wizyty => data.beginning_of_day..data.end_of_day, potwierdzona: false)
#appointments = #patient_appo & #doctors_appo
else
#appointments = #patient_appo
end
end
def to_confirm
session['last_search'] = request.env["HTTP_REFERER"]
#appointment = Appointment.find(params[:id])
#patient = Patient.find(#appointment.patient_id)
if #appointment.doctor_id != nil
#doctor = Doctor.find(#appointment.doctor_id)
end
if #appointment.refferal_id != nil
#refferal = Refferal.find(#appointment.refferal_id)
end
end
def confirm
#appointment = Appointment.find(params[:id])
#appointment.potwierdzona = true
if #appointment.save
#redirect_to :back, notice: 'Rejestracja zostala pomyslnie potwierdzona.'
redirect_to session[:last_search], notice: 'Rejestracja zostala pomyslnie potwierdzona.'
else
redirect_to :back, notice: 'Niestety wystapil blad. Prosze sprubowac pozniej'
end
end
def index
#appointments = Appointment.all
end
def show
end
def new
#appointment = #wizard.object
#clinics = Clinic.all
#doctors = Doctor.all
end
public
def findDoctorViaClinic( clinic )
return( (Clinic.find( clinic )).doctors.uniq )
end
helper_method :findDoctorViaClinic
def findScheduleViaDoctor(d)
s = Schedule.includes(:doctors_workplace).where(doctors_workplace_id: (DoctorsWorkplace.includes(:doctor).where(doctor_id: d)) ).where(taken: 0)
return s
end
helper_method :findScheduleViaDoctor
def edit
end
def create
#appointment = #wizard.object
if #wizard.save
s = ( Schedule.find( #appointment.schedule.id ) )
s.taken = true
s.save
redirect_to #appointment, notice: "Appointment saved!"
else
render :new
end
end
def update
# if #wizard.save
# redirect_to #appointment, notice: 'Appointment was successfully updated.'
# else
# render action: 'edit'
# end
#appointment = Appointment.find(params[:id])
#old_appointment = #appointment.dup
respond_to do |format|
if #appointment.update_attributes(params[:appointment])
DefaultMailer.move_appointment(#appointment, #old_appointment).deliver
format.html { redirect_to appointments_success_path, notice: 'Pomyslnie zmieniono termin.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #appointment.errors, status: :unprocessable_entity }
end
end
end
def destroy
#appointment.destroy
redirect_to appointments_url
end
private
def load_appointment
#appointment = Appointment.find(params[:id])
end
def load_wizard
#wizard = ModelWizard.new(#appointment || Appointment, session, params)
if self.action_name.in? %w[new edit]
#wizard.start
elsif self.action_name.in? %w[create update]
#wizard.process
end
end
end
Logs:
Started POST "/appointments/create51" for 127.0.0.1 at 2014-06-22 08:22:53 +0200
Processing by AppointmentsController#create51 as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"kMxnErrH13opSkUPbg9hRM0Sy5JVwDCAbGRDNP5BSfc=", "appointment"=>{"data_godzina_wizyty(1i)"=>"2015", "data_godzina_wizyty(2i)"=>"1", "data_godzina_wizyty(3i)"=>"17", "data_godzina_wizyty(4i)"=>"16", "data_godzina_wizyty(5i)"=>"15", "doctor_id"=>"1", "patient_id"=>"1"}, "commit"=>"Utworz wizyte"}
[1m[35m (0.0ms)[0m begin transaction
[1m[36mSQL (2.0ms)[0m [1mINSERT INTO "appointments" ("clinic_id", "created_at", "data_godzina_wizyty", "data_wizyty", "doctor_id", "godzina_wizyty", "notatka", "objawy_choroby", "patient_id", "potwierdzona", "refferal_id", "schedule_id", "updated_at", "wymaga_Potwierdzenia") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)[0m [["clinic_id", nil], ["created_at", Sun, 22 Jun 2014 06:22:53 UTC +00:00], ["data_godzina_wizyty", nil], ["data_wizyty", nil], ["doctor_id", nil], ["godzina_wizyty", nil], ["notatka", nil], ["objawy_choroby", nil], ["patient_id", nil], ["potwierdzona", nil], ["refferal_id", nil], ["schedule_id", nil], ["updated_at", Sun, 22 Jun 2014 06:22:53 UTC +00:00], ["wymaga_Potwierdzenia", nil]]
[1m[35m (13.0ms)[0m commit transaction
Redirected to http://localhost:3000/appointments/30
Completed 302 Found in 23.0ms (ActiveRecord: 15.0ms)
Started GET "/appointments/new51" for 127.0.0.1 at 2014-06-22 08:22:42 +0200
Processing by AppointmentsController#new51 as HTML
[1m[35mDoctor Load (1.0ms)[0m SELECT "doctors".* FROM "doctors" WHERE "doctors"."id" = ? LIMIT 1 [["id", 1]]
[1m[36mCACHE (0.0ms)[0m [1mSELECT "doctors".* FROM "doctors" WHERE "doctors"."id" = ? LIMIT 1[0m [["id", 1]]
[1m[35mCACHE (0.0ms)[0m SELECT "doctors".* FROM "doctors" WHERE "doctors"."id" = ? LIMIT 1 [["id", 1]]
[1m[36mPatient Load (0.0ms)[0m [1mSELECT "patients".* FROM "patients" WHERE "patients"."id" = ? LIMIT 1[0m [["id", 1]]
[1m[35mCACHE (0.0ms)[0m SELECT "patients".* FROM "patients" WHERE "patients"."id" = ? LIMIT 1 [["id", 1]]
[1m[36mCACHE (0.0ms)[0m [1mSELECT "patients".* FROM "patients" WHERE "patients"."id" = ? LIMIT 1[0m [["id", 1]]
[1m[35mCACHE (0.0ms)[0m SELECT "doctors".* FROM "doctors" WHERE "doctors"."id" = ? LIMIT 1 [["id", 1]]
[1m[36mCACHE (0.0ms)[0m [1mSELECT "patients".* FROM "patients" WHERE "patients"."id" = ? LIMIT 1[0m [["id", 1]]
Rendered appointments/_form51.html.erb (13.0ms)
Rendered appointments/new51.html.erb within layouts/application (22.0ms)
Rendered welcome/_form.html.erb (1.0ms)
Completed 200 OK in 103.0ms (Views: 100.9ms | ActiveRecord: 1.0ms)
Started GET "/appointments/30" for 127.0.0.1 at 2014-06-22 08:22:53 +0200
Processing by AppointmentsController#show as HTML
Parameters: {"id"=>"30"}
[1m[36mAppointment Load (0.0ms)[0m [1mSELECT "appointments".* FROM "appointments" WHERE "appointments"."id" = ? LIMIT 1[0m [["id", "30"]]
Rendered appointments/show.html.erb within layouts/application (2.0ms)
Rendered welcome/_form.html.erb (1.0ms)
Completed 200 OK in 80.0ms (Views: 77.0ms | ActiveRecord: 0.0ms)
Routes
Wow your routes are really WET
You really need to read up on resourceful routing - every route you have in your routes file really needs to be associated to a particular controller (apart from root to and other wildcards)
Whoever wrote your routes file has laden it with massive numbers of specific actions. Frankly, it's a mess and I would highly recommend you go through & remove any custom actions you've got in there.
Resourceful routing is described in the Rails docs as thus:
Bottom line is you shouldn't be creating routes for specific records; you need to create a system to handle the different processes your application will have
--
Form
If you're not seeing any object created in your db, there could be a number of problems. The biggest, though, is your use of an #instance variable in your partial.
To the best of my knowledge, partials don't carry #instance variables through to their render process. You have to pass local variables:
#new.html.erb
<%= render "form51", locals: { appointment: #appointment } %>
#_form51.html.erb
<%= form_for appointment do |f| %>
...
<% end %>
--
Being honest, there's so much to fix with this, it will be best if you ask for help in the comments here - so I can pinpoint exactly what needs to be fixed
You problem comes from the url you use on your form.
You should try like this on your _form51.html.erb:
form_for #appointment, :url => url_for(:action => "create51") do |f|
If you do rake routes | grep 'create51' you'll have the rails path. Then you can also do like this:
form_for #appointment, :url => create51_path do |f|
(here I suppose the command gave you create51 as path).

ActionController::UrlGenerationError in Comments#show

I use polymorphic associations with comments. When I try to add 'edit' and also 'destroy' in show template, I get the error in the title (just edit for now). How do I add both links to show?
comments_controller.rb
class CommentsController < ApplicationController
....
before_action :signed_in_user, only: [:new, :edit]
before_filter :load_commentable
def index
#commentable = load_commentable
#comments = #commentable.comments
end
def show
end
def edit
#commentable = load_commentable
end
def new
#commentable = load_commentable
#comment = #commentable.comments.new
end
def create
#comment = #commentable.comments.new(comment_params)
#comment.user = current_user
if #comment.save
redirect_to #comment, notice: "Created."
else
render :new
end
end
def update
#comment = #commentable.comments.build(comment_params)
#comment.user = current_user
respond_to do |format|
if #comment.update(comment_params)
format.html { redirect_to #comment, notice: 'It was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
private
def load_commentable
resource, id = request.path.split('/')[1, 2]
#commentable = resource.singularize.classify.constantize.find(id)
end
....
end
show.html.erb template
<%= link_to "Edit", [:edit, #commentable, :comment] %>
form
<%= form_for [#commentable, #comment] do |f| %>
....
full trace
log
Processing by CommentsController#show as HTML
Parameters: {"post_id"=>"1", "id"=>"2"}
Comment Load (0.3ms) SELECT "comments".* FROM "comments" WHERE
"comments"."id" = ? LIMIT 1 [["id", "2"]]
Post Load (0.2ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" =
? LIMIT 1 [["id", "1"]]
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" =
? ORDER BY "users"."id" ASC LIMIT 1 [["id", 2]]
(0.2ms) SELECT COUNT(*) FROM "comments" WHERE "comments"."user_id" =
? [["user_id", 2]] CACHE (0.0ms) SELECT COUNT(*) FROM "comments"
WHERE "comments"."user_id" = ? [["user_id", 2]]
Rendered comments/show.html.erb within layouts/application (10.7ms)
Completed 500 Internal Server Error in 19ms
ActionView::Template::Error (No route matches {:action=>"edit",
:controller=>"comments", :post_id=>#, :id=>nil,
:format=>nil} missing required keys: [:id]):
25: <div class="thumbsdown"><%= link_to image_tag('othericons/thumbiconDown.PNG', height: '20', width: '20'),
"#" %>
26: <%= link_to image_tag('othericons/flagicon.PNG', height: '20', width: '18'), "#"
%>
27:
28: <%= link_to "Edit", [:edit, #commentable, :comment] %> 29:
30:
31: app/views/comments/show.html.erb:28:in
`_app_views_comments_show_html_erb___2937579164590753686_69833853514120'
Rendered /home/action/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-4.0.0/lib/action_dispatch/middleware/templates/rescues/_trace.erb
(1.6ms) Rendered
/home/action/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-4.0.0/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb
(1.2ms) Rendered
/home/action/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-4.0.0/lib/action_dispatch/middleware/templates/rescues/template_error.erb
within rescues/layout (19.1ms)
routes:
resources :posts do
resources :comments
end
Change the Edit Link as below:
<%= link_to "Edit", edit_post_comment_path(#commentable, #comment) %>
You have setup Post and Comment as nested routes, so you need to pass objects of Post as well as Comment to the edit path.
EDIT
For Polymorphic association, you could use it as below:
<%= link_to "Edit", [:edit, #commentable, #comment] %>

Resources