I'm trying to make a frontend mini admin system to reorder the product images stored as an array by Carrierwave multiple upload.
Frontend is working fine.
In my view, I have:
<%= form_for product, url: product_path(product.id), method: :patch do |form| %>
<div class="field">
<%= form.label :images %>
<div class="image-sortable">
<% product.images.each do |image| %>
<div class="image">
<%= hidden_field :product, :images, multiple: true, value: image.cache_name || image.identifier %>
<%= image_tag(image.url, height: 50) %>
<button type="button" class="remove-image">Quitar</button>
</div>
<% end %>
</div>
</div>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
Params are being passed correctly
Processing by ProductsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"X0UIytX4V56npfBIrl/fkaUiIgP4BDiJOGpB8tCdAZMeP7kvDXV1z0wsGge4Kch1TJG9Gzhpbtt5hOpQXbMH/Q==", "product"=>{"images"=>["6919-000-6.jpg", "6919-000-2.jpg", "6919-000-3.jpg", "6919-000-4.jpg", "6919-000-5.jpg"]}, "commit"=>"Update Product", "id"=>"1169"}
In the product update, the order of images are not stored, and I'm getting null values appended.
Product Update (0.9ms) UPDATE "products" SET "images" = $1, "updated_at" = $2 WHERE "products"."id" = $3 [["images", "[\"6919-000-2.jpg\",\"6919-000-3.jpg\",\"6919-000-4.jpg\",\"6919-000-5.jpg\",\"6919-000-6.jpg\",null,null,null,null,null]"], ["updated_at", "2023-01-26 21:08:11.373942"], ["id", 1169]]
In my controller, I have the standard update method:
def update
respond_to do |format|
if #product.update(product_params)
format.html { redirect_to #product }
format.json { render :show, status: :ok, location: #product }
else
format.html { render :edit }
format.json { render json: #product.errors, status: :unprocessable_entity }
end
end
end
Related
I have a two forms inside my edit action, one is to update an item inside the item.rb model(which works fine)... and the other one is to create an image in a attachment.rb model. The problem is that it creates a row inside the db images with null values and does not save the actually image along with the correct values.
items_contoller.rb
def edit
#attachment = Attachment.new
end
this is the form for the image create:
<%= form_for #attachment, url: create_attachment_path(#attachment), :html => {:id => "form", :multipart => true }, method: :post do |form| %>
<% if #attachment.errors.any? %>
<div class="centerList">
<div id="error_explanation">
<h2><%= pluralize(item.errors.count, "error") %> <%= t 'store_item_edit_4' %></h2>
<% #attachment.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</div>
</div>
<% end %>
<%= hidden_field_tag :item_id, value: #item.id %>
<div class="form-group">
<div class="text-center">
<label class="btn btn-primary"><%= t 'store_item_edit_5' %><span style="display:none;">
<%= form.file_field :image, multiple: true, id: "uploads" %></span></label>
<%= form.submit '', :style => "display: none;" %>
<% end %>
this is the route:
post "attachments/create"=> "attachments#create", :as => :create_attachment
attachments_controller.rb
def create
#attachment = Attachment.new(attachment_params)
respond_to do |format|
if #attachment.save
format.html { redirect_back fallback_location: root_path, notice: 'Image was successfully uploaded.' }
format.json { render :show, status: :created, location: #attachment }
else
format.html { render :new }
format.json { render json: #attachment.errors, status: :unprocessable_entity }
end
end
end
def attachment_params
params.require(:attachment).permit(:item_id, :account_id, :image)
end
and this is what I get inside the console... at some point as you can see I get a Unpermitted parameter: :image:
started POST "/attachments/create" for 127.0.0.1 at 2018-03-14 17:20:23 +0200
Processing by AttachmentsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"6kgGVoUf2tlM2YdxZis6xavw//zC4azttYi4FFshgw4swiFUIOfb58hCtZxf0If2ihOXz3SCETQSnci6l1IFIA==", "item_id"=>"{:value=>44}", "attachment"=>{"image"=>[#<ActionDispatch::Http::UploadedFile:0x007fc6e4acfb18 #tempfile=#<Tempfile:/var/folders/hq/pr4rt14n7s31v3f6292wtjm00000gn/T/RackMultipart20180314-4193-1jrij48.jpg>, #original_filename="image1.jpg", #content_type="image/jpeg", #headers="Content-Disposition: form-data; name=\"attachment[image][]\"; filename=\"image1.jpg\"\r\nContent-Type: image/jpeg\r\n">]}}
Store Load (0.5ms) SELECT "stores".* FROM "stores" WHERE "stores"."id" = $1 ORDER BY "stores"."id" ASC LIMIT $2 [["id", 1], ["LIMIT", 1]]
Unpermitted parameter: :image
(0.2ms) BEGIN
SQL (0.4ms) INSERT INTO "attachments" ("created_at", "updated_at") VALUES ($1, $2) RETURNING "id" [["created_at", "2018-03-14 15:20:23.368574"], ["updated_at", "2018-03-14 15:20:23.368574"]]
(1.2ms) COMMIT
Redirected to https://localhost:3000/store/items/edit/44
Completed 302 Found in 8ms (ActiveRecord: 2.3ms)
Any ideas how to fix this:
You should add:
def attachment_params
params.require(:attachment).permit(:item_id, :account_id, image: {})
end
I am suffering, because I don't get why my form doesn't write data into my database. If I submit the form I get a new line in the database, which only contains "id", "created at" and "updated at". All other parameters are not submitted. In the log file I get a "unpermitted parameters" message. Where can I change this?
I would be very happy for help. Thanks a lot!
Here is the view to the "new institute" page, which contains the form.
<% provide(:title, 'Institut erstellen') %>
<div class="small_jumbotron jumbotron">
<h1>Institut erstellen</h1>
<div class="row">
<div class="Links">
<%= form_for(#institute) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<br>
<%= f.label :Institutsname %>
<%= f.text_field :name, class: 'form-control' %>
<%= f.label :Professorenanzahl %>
<%= f.number_field :professors, class: 'form-control' %>
<%= f.label "Anzahl wissenschaftlicher Mitarbeiter" %>
<%= f.number_field :employees, class: 'form-control' %>
<%= f.label "Anzahl an Masterarbeiten" %>
<%= f.number_field :master_theses, class: 'form-control' %>
<%= f.label "Anzahl Lehrveranstaltungen" %>
<%= f.number_field :classes, class: 'form-control' %>
<%= f.label "Minimale Bachelorarbeitenzuordnung" %>
<%= f.number_field :min_workload, class: 'form-control' %>
<%= f.label "Überkapazitätsbereitschaft" %>
<%= f.number_field :overload, class: 'form-control' %>
<%= f.label "Aversion gegen Überkapazitäten" %>
<%= f.number_field :overload_aversion, class: 'form-control' %>
<%= f.label "Kapazität" %>
<%= f.number_field :capacity, class: 'form-control' %>
<br>
<%= f.submit "Erstelle das Institut", class: "btn btn-primary" %>
<% end %>
</div>
</div>
</div>
Here is the institutes controller
class InstitutesController < ApplicationController
before_action :set_institute, only: [:show, :edit, :update, :destroy]
# GET /institutes
# GET /institutes.json
def index
#institutes = Institute.all
end
# GET /institutes/1
# GET /institutes/1.json
def show
end
# GET /institutes/new
def new
#institute = Institute.new
end
# GET /institutes/1/edit
def edit
end
# POST /institutes
# POST /institutes.json
def create
#institute = Institute.new(institute_params)
respond_to do |format|
if #institute.save
format.html { redirect_to #institute, notice: 'Das Institut wurde erstellt.'}
format.json { render :show, status: :created, location: #institute }
else
format.html { render :new }
format.json { render json: #institute.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /institutes/1
# PATCH/PUT /institutes/1.json
def update
respond_to do |format|
if #institute.update(institute_params)
format.html { redirect_to #institute, notice: 'Die Institutsdaten wurden aktualisiert.' }
format.json { render :show, status: :ok, location: #institute }
else
format.html { render :edit }
format.json { render json: #institute.errors, status: :unprocessable_entity }
end
end
end
# DELETE /institutes/1
# DELETE /institutes/1.json
def destroy
#institute.destroy
respond_to do |format|
format.html { redirect_to institutes_url, notice: 'Das Institut wurde gelöscht.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_institute
#institute = Institute.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def institute_params
params.permit(:name, :professors, :employees, :master_theses, :classes, :min_workload, :overload, :overload_aversion, :capacity)
end
end
And now a snippet of the log file
Started POST "/institutes" for 127.0.0.1 at 2018-02-18 16:15:02 +0100
Processing by InstitutesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"ufyuHL2iXZpQg1ZmfG1pleuY7aL3JIl+eGn36UJeibML8U5R1sOgw8jd6geBB60XchttET2T3I1SndFgGsR2uA==", "institute"=>{"name"=>"wsd", "professors"=>"", "employees"=>"4", "master_theses"=>"", "classes"=>"", "min_workload"=>"", "overload"=>"", "overload_aversion"=>"", "capacity"=>""}, "commit"=>"Erstelle das Institut"}
Unpermitted parameters: :utf8, :authenticity_token, :institute, :commit
[1m[35m (0.5ms)[0m [1m[36mbegin transaction[0m
[1m[35mSQL (0.6ms)[0m [1m[32mINSERT INTO "institutes" ("created_at", "updated_at") VALUES (?, ?)[0m [["created_at", "2018-02-18 15:15:02.619018"], ["updated_at", "2018-02-18 15:15:02.619018"]]
[1m[35m (17.0ms)[0m [1m[36mcommit transaction[0m
Redirected to http://localhost:3000/institutes/12
Completed 302 Found in 30ms (ActiveRecord: 18.1ms)
You're not using strong_params correctly. Should be like this:
def institute_params
params.require(:institute).permit(:name, :professors, ...)
# ^^^^^^^^^^^^^^^^^^^^
end
i'm making a form to upload multiple images with carrierwave. Save array to db work fine but i want to save 1 array element as 1 record, to make it easier to manage later.
I tried to do as below but it return nilClass err.
All picture use the same description, name is image file name
Anyone has done this kind of stuff before :'(
views/_form
<%= form_for [:admin, #picture], :html => {multipart: true, :class => 'form-horizontal'} do |f| %>
<div class="box-body">
<div class="form-group">
<%= f.label :link, :class => 'col-sm-2 control-label' %>
<div class="col-sm-10">
<%= f.file_field :link, multiple: true, :class => 'form-control', :id => 'imgInp' %>
</div>
</div>
<div class="form-group">
<%= f.label :description, :class => 'control-label col-sm-2' %>
<div class="col-sm-10">
<%= f.text_area :description, :class => 'form-control' %>
</div>
</div>
</div>
<!-- /.box-body -->
<div class="box-footer">
<%= link_to admin_pictures_path do %>
<button class="btn btn-default">Back</button>
<% end %>
<%= f.submit nil, :class => 'btn btn-info pull-right' %>
</div>
<!-- /.box-footer --> <% end %>
controller
def create
if params[:link]
params[:link].each { |image|
#picture = Picture.new(name: image.file.filename, description: params[:description], link: image)
#picture.save
}
end
end
respond_to do |format|
if #picture.save
format.html { redirect_to admin_pictures_path, notice: ' picture was successfully created.' }
format.json { render :show, status: :created, location: #picture }
else
format.html { render :new }
format.json { render json: #picture.errors, status: :unprocessable_entity }
end
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_picture
#picture = Picture.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def picture_params
params.require(:picture).permit(:name, :description, :link)
end
end
param[:link] console
Parameters: {"utf8"=>"✓",
"authenticity_token"=>"2KMy3lPMnf3MqLLHpJAH+Ei40nja+KAJGsx2twyP5L05A95b7rLsZHEFoUSu+CMJQunQ4yUq6kmppdK6I7NQkw==",
"picture"=>{"album_id"=>"3", "team_id"=>"", "link"=>[#<ActionDispatch::Http::UploadedFile:0x007f9095ea1c08 #tempfile=#<Tempfile:/tmp/RackMultipart20160331-6776-1h8i98y.jpg>,
#original_filename="images.jpg", #content_type="image/jpeg",
#headers="Content-Disposition: form-data; name=\"picture[link][]\";
filename=\"images.jpg\"\r\nContent-Type: image/jpeg\r\n">, #<ActionDispatch::Http::UploadedFile:0x007f9095ea1be0 #tempfile=#<Tempfile:/tmp/RackMultipart20160331-6776-y6d6ug.jpg>, #original_filename="images (1).jpg", #content_type="image/jpeg",
#headers="Content-Disposition: form-data; name=\"picture[link][]\";
filename=\"images (1).jpg\"\r\nContent-Type: image/jpeg\r\n">, #<ActionDispatch::Http::UploadedFile:0x007f9095ea1bb8 #tempfile=#<Tempfile:/tmp/RackMultipart20160331-6776-hizrku.jpg>,
#original_filename="lulu.jpg", #content_type="image/jpeg", #headers="Content-Disposition: form-data; name=\"picture[link][]\";
filename=\"lulu.jpg\"\r\nContent-Type: image/jpeg\r\n">],
"description"=>"abc"}, "commit"=>"Create Picture"}
User Load (0.4ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 ORDER BY `users`.`id` ASC LIMIT 1
params:
Completed 500 Internal Server Error in 3ms (ActiveRecord: 0.4ms)
This will solve your issue :
def create
if params[:picture][:link]
params[:picture][:link].each { |image|
#picture = Picture.new(:name => image.original_filename,:description => params[:description])
#picture.store!(image.tempfile)
#picture.save
}
end
end
respond_to do |format|
if #picture.save
format.html { redirect_to admin_pictures_path, notice: ' picture was successfully created.' }
format.json { render :show, status: :created, location: #picture }
else
format.html { render :new }
format.json { render json: #picture.errors, status: :unprocessable_entity }
end
end
end
Try
...
#picture = Picture.new(picture_params)
respond_to do |format|
if #picture.save...
so that #picture.save will not result to nil
My problem is after I create a new record with ajax I get a NOMETHODERROR and I must reload the page to see the new record.
The Error I get in terminal.
Rendered time_entries/_time_entry.html.erb (3.4ms) Rendered
time_entries/create.js.erb (4.9ms) Completed 500 Internal Server Error
in 41ms (ActiveRecord: 4.4ms)
NoMethodError - undefined method `each' for nil:NilClass:
app/views/time_entries/_time_entry.html.erb:1:in '_app_views_time_entries__time_entry_html_erb___4086905375499854267_70174828432680'
What I do wrong?
time_entries_controller.erb
class TimeEntriesController < ApplicationController
...
respond_to :html, :js
def index
#time_entries = current_user.time_entries.all.order("date DESC")
#time_entries_days = #time_entries.group_by{ |t| t.date.beginning_of_day }
respond_with(#time_entry)
end
def create
#time_entry = TimeEntry.new(timeentry_params)
#time_entry.user_id = current_user.id
respond_to do |format|
if #time_entry.save
format.html { redirect_to #time_entry, notice: 'Arbeitszeit wurde eingetragen' }
format.json { render :show, status: :created, location: #time_entry }
format.js
else
format.html { render :new }
format.json { render json: #time_entry.errors, status: :unprocessable_entity }
format.js
end
end
end
...
_time_entry.html.erb
the partial
<% #time_entries_days.each do |day, time_entries| %>
<% if day.today? %>
<div class="column-12 list-group">Today, <%= l day, format: :dm %></div>
<% else %>
<div class="column-12 list-group"><%= l day, format: :dm %></div>
<% end %>
<ul class="lists">
<% time_entries.each do |time_entry| %>
<li class="list-item" id="time_entry_<%= time_entry.id %>">
<div class="list-item__content">
<h3 class="list-item__title">
<%= link_to time_entry.category.name, time_entry %>
<span><%= l time_entry.start_time, format: :hm %></span> - <span><%= l time_entry.end_time, format: :hm %></span>
</h3>
<p><%= time_entry.note %></p>
</div>
<span class="list-item__label"><%= time_entry.hours %>h</span>
</li>
<% end %>
</ul>
<% end %>
index.html.erb
<% if can? :create, TimeEntry %>
<%= link_to 'Add new Time Entry', new_time_entry_path, remote: true, class: 'btn btn-primary', :data => { :'popup-open' => 'popup-1' } %>
<% end %>
...
<div class="row" id="container_time_entries">
<%= render "time_entry" %>
</div>
create.js.erb for testing
I don't get an alert after I create a new time entry.
alert("HALLO");
create.js.erb normal
$('.modal-bg').hide();
$('.popup').fadeOut(350);
$('#container_time_entries').html("<%= j(render 'time_entry') %>");
You do not set the variable #time_entries_days in your create method, but you need it in your _time_entry.html.erb .
Set it and you should be good to go.
Two of the action of My registration controller is new and create.
def new
#regist = Regist.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #regist }
end
end
def create
#regist = Regist.new(regist_params)
respond_to do |format|
if #regist.save
format.html { redirect_to #regist, notice: 'Regist was successfully created.' }
format.json { render json: #regist, status: :created, location: #regist }
else
format.html { render action: "new" }
format.json { render json: #regist.errors, status: :unprocessable_entity }
end
end
end
And the new form contain following code.
<%= form_for(#regist) do |f| %>
<% if #regist.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#regist.errors.count, "error") %> prohibited this regist from being saved:</h2>
<ul>
<% #regist.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.collection_select :student_id, Student.all, :id, :name %><br />
</div>
<div class="field">
<%= f.collection_select :semester_id, Semester.all, :id, :name %><br />
</div>
<div class="field">
<% for subject in Subject.find(:all) %>
<%= check_box_tag "regist[subject_ids][]", subject.id %>
<%= subject.name %><br>
<% end %>
</div>
<div class="field">
<%= f.label :date_of_birth %><br />
<%= f.text_field :date_of_birth %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Now, when someone click on submit button I want to make ajax call using remote true if there are validation errors and show the errors without reloading the page. And if there are no validation errors I want the user to be redirected to show page. How can I do this?
First of all you should add a remote: true to your existing form to allow remote action.
TODO this just add on the first line of your form the remote: true,
<%= form_for(#regist, remote: true) do |f| %>
the rest leave it as it is. Then you need to make your controller to respond to remote calls, therefore you need to alter the responds_to block of create action:
respond_to do |format|
if #regist.save
format.html { redirect_to #regist, notice: 'Regist was successfully created.' }
format.json { render json: #regist, status: :created, location: #regist }
format.js { render js: "window.location.href='"+regists_path+"'"}
else
format.html { render action: "new" }
format.json { render json: #regist.errors, status: :unprocessable_entity }
format.js
end
end
The last step you have to do is to add a file to your app/views/regists/ directory
where you should add a create.js.erb file:
<% if #regist.errors.any? %>
$('#new_regist').effect('highlight', { color: '#FF0000'}, 1000); // for highlighting
// or add here whatever jquery response you want to have to your views.
<% end %>
You will get your validation errors displayed like before above the form.
You have to add the redirect to your controller to the desirable action of your choice. I have added for you a window.location.href as a response to the regists_path.