I am having a slight issue with a rails app I am working on. I am utilizing Carrierwave, Nested_form, Simple_form, and Jquery-file-upload gems.
The majority of everything is working fine, with the exception of the data.
I have two models, a Project Model and an Attachments Model.
When the Project form is submitted, all the files upload as they should, a record in the attachments model is created as it should (one per file). But as for the projects model, a record is created for each file as well.
I can't seem to figure out (on a single form, with single submit) how to get only one record for the project and multiple records for the attachments.
Any help would be appreciated, I've outlined my code below. I'd like to avoid a two step process if possible, but if someone could point me in the right direction that would help.
Project Model
class Project < ActiveRecord::Base
has_many :attachments, :dependent => :destroy
accepts_nested_attributes_for :attachments, :allow_destroy => true
def generate_token
self.token = loop do
random_token = SecureRandom.urlsafe_base64
break random_token unless Project.where(token: random_token).exists?
end
end
end
Attachment Model
class Attachment < ActiveRecord::Base
belongs_to :project, :polymorphic => true
include Rails.application.routes.url_helpers
mount_uploader :file, AttachmentUploader
def to_jq_upload
{
"name" => read_attribute(file),
"url" => file.url,
"size" => file.size,
"delete_url" => attachment_path(:id => id),
"delete_type" => "DELETE"
}
end
end
Projects Controller
class ProjectsController < ApplicationController
def index
#projects = Project.all
respond_to do |format|
format.html
format.json { render json: #projects }
end
end
def new
#project = Project.new
#project.token = #project.generate_token
#attachments = #project.attachments.build
end
def create
#project = Project.new(project_params)
respond_to do |format|
if #project.save
format.html { redirect_to projects_url, notice: 'Project was successfully created.' }
format.json { render json: #project, status: :created, location: #project }
else
format.html {}
format.json {}
end
end
end
def destroy
#project = Project.find(params[:id])
#project.destroy
respond_to do |format|
format.html { redirect_to projects_url }
format.json { head :no_content }
end
end
private
def project_params
params.require(:project).permit(:name, :token, :number_of_pages, :number_of_copies, :flat_page_size, :trim_page_size, :purchase_order_number, :preferred_delivery_date, :delivery_method, :delivery_instructions, :project_instructions, attachments_attributes: [:id, :attachment, :name, :filename, :file, :project_token, :branch])
end
end
Attachments Controller
class AttachmentsController < ApplicationController
before_filter :the_project
def index
#attachments = Attachment.where("project_id = ?", the_project)
render :json => #attachments.collect { |p| p.to_jq_upload }.to_json
end
def create
#project = Project.find(params[:project_id])
#attachment = Attachment.new(attachment_params)
if #attachment.save
respond_to do |format|
format.html { render :json => [#attachment.to_jq_upload].to_json, :content_type => 'text/html', :layout => false }
format.json { render :json => {files: [#attachment.to_jq_upload]}.to_json }
end
else
render :json => [{ :error => "custom_failure "}], :status => 304
end
end
def destroy
#attachment = Attachment.find(params[:id])
#attachment.destroy
render :json => true
end
private
def the_project
#project = Project.find(params["project_id"])
end
end
New Project Form (app/views/projects/new.html.erb)
<h2>New Project</h2>
<br />
<%= simple_nested_form_for #project, :defaults => { :wrapper_html => {:class => 'form-group'}, :input_html => { :class => 'form-control' } }, :html => { :multipart => true, :id => "fileupload", :class => 'horizontal-form', :role => "form" } do |f| %>
<div class="row">
<div class="col-lg-12">
<%= f.input :name, :label => "Project Name / Description", :class => 'col-lg-12' %>
<%= f.hidden_field :token %>
</div>
</div>
<div class="row">
<div class="col-lg-6">
<%= f.input :number_of_pages %>
<%= f.input :flat_page_size %>
<%= f.input :purchase_order_number %>
</div>
<div class="col-lg-6">
<%= f.input :number_of_copies %>
<%= f.input :trim_page_size, :label => 'Finished Size <em><small>(If Different from Flat Page Size)</small></em>' %>
<%= f.input :preferred_delivery_date, :as => :text %>
</div>
</div>
<div class="row">
<div class="col-lg-6">
<%= f.input :delivery_method %>
</div>
<div class="col-lg-6">
<%= f.input :project_instructions %>
</div>
</div>
<div class="row">
<div class="col-lg-6">
<select id="branches">
<option>Calgary Downtown</option>
<option>Calgary South</option>
<option>Edmonton</option>
<option>Kelowna</option>
</select>
</div>
</div>
<br />
<div class="row fileupload-buttonbar">
<div class="col-lg-7">
<%= fields_for :attachments do |a| %>
<span class="btn btn-success fileinput-button">
<i class="glyphicon glyphicon-plus"></i>
<span>Add files...</span>
<%= a.file_field :file, :name => 'project[attachments_attributes][0][file]', :multiple => true %>
</span>
<button type="submit" class="btn btn-primary start">
<i class="glyphicon glyphicon-upload"></i>
<span>Start Upload</span>
</button>
<button type="reset" class="btn btn-warning cancel">
<i class="glyphicon glyphicon-ban-circle"></i>
<span>Cancel Upload</span>
</button>
<button type="button" class="btn btn-danger delete">
<i class="glyphicon glyphicon-trash"></i>
<span>Delete Upload</span>
</button>
<%= a.hidden_field :branch, :value => "Calgary Downtown" %>
<%= a.hidden_field :project_token, :value => #project.token %>
<% end %>
</div>
<div class="col-lg-5">
<div class="progress progress-success progress-striped active fade">
<div class="bar" style="width:0%"></div>
</div>
</div>
</div>
<div class="row fileupload-loading"></div>
<div class="row">
<table class="table table-striped">
<tbody class="files" data-toggle="modal-gallery" data-target="#modal-gallery">
</tbody>
</table>
</div>
<% end %>
<script>
var fileUploadErrors = {
maxFileSize: 'File is too big',
minFileSize: 'File is too small',
acceptFileTypes: 'Filetype not allowed',
maxNumberOfFiles: 'Max number of files exceeded',
uploadedBytes: 'Uploaded bytes exceed file size',
emptyResult: 'Empty file upload result'
};
</script>
<!-- The template to display files available for upload -->
<script id="template-upload" type="text/x-tmpl">
{% for (var i=0, file; file=o.files[i]; i++) { %}
<tr class="template-upload fade">
<td class="preview"><span class="fade"></span></td>
<td class="name"><span>{%=file.name%}</span></td>
<td class="size"><span>{%=o.formatFileSize(file.size)%}</span></td>
{% if (file.error) { %}
<td class="error" colspan="2"><span class="label label-important">{%=locale.fileupload.error%}</span> {%=locale.fileupload.errors[file.error] || file.error%}</td>
{% } else if (o.files.valid && !i) { %}
<td>
<div class="progress progress-success progress-striped active"><div class="bar" style="width:0%;"></div></div>
</td>
<td class="start">{% if (!o.options.autoUpload) { %}
<button class="btn btn-primary">
<i class="icon-upload icon-white"></i>
<span>{%=locale.fileupload.start%}</span>
</button>
{% } %}</td>
{% } else { %}
<td colspan="2"></td>
{% } %}
<td class="cancel">{% if (!i) { %}
<button class="btn btn-warning">
<i class="icon-ban-circle icon-white"></i>
<span>{%=locale.fileupload.cancel%}</span>
</button>
{% } %}</td>
</tr>
{% } %}
</script>
<!-- The template to display files available for download -->
<script id="template-download" type="text/x-tmpl">
{% for (var i=0, file; file=o.files[i]; i++) { %}
<tr class="template-download fade">
{% if (file.error) { %}
<td></td>
<td class="name"><span>{%=file.name%}</span></td>
<td class="size"><span>{%=o.formatFileSize(file.size)%}</span></td>
<td class="error" colspan="2"><span class="label label-important">{%=locale.fileupload.error%}</span> {%=locale.fileupload.errors[file.error] || file.error%}</td>
{% } else { %}
<td class="preview">{% if (file.thumbnail_url) { %}
<img src="{%=file.thumbnail_url%}">
{% } %}</td>
<td class="name">
{%=file.name%}
</td>
<td class="size"><span>{%=o.formatFileSize(file.size)%}</span></td>
<td colspan="2"></td>
{% } %}
<td class="delete">
<button class="btn btn-danger" data-type="{%=file.delete_type%}" data-url="{%=file.delete_url%}">
<i class="icon-trash icon-white"></i>
<span>{%=locale.fileupload.destroy%}</span>
</button>
<input type="checkbox" name="delete" value="1">
</td>
</tr>
{% } %}
</script>
<script type="text/javascript" charset="utf-8">
$(function () {
var num_added = 0;
var added = 0;
var all_data = {};
$('#branches').change(function() {
var test = $("option:selected",this).text();
$('#project_attachments_attributes_0_branch').val(test);
});
// Initialize the jQuery File Upload widget:
$('#fileupload').fileupload({
sequentialUploads: true,
});
});
</script>
I'm working on more or less that exact same issue (mine involves stock_items - not projects, but anyways...)
One issue is the #fileupload.fileupload which initializes the entire form - and that will post your project, which you will not want to
I've not solved that one yet - but somehow 'we' have to make the parent form not POST
I believe you need to include the index of the 'parent' instance in the input, in this case, Project. So:
<%= a.file_field :file, :name => 'project[*index*][attachments_attributes][0][file]', :multiple => true %>
Related
I'm trying to do an edit object in Ruby on Rails using a modal form, when I try to do the link_to edit_plane_path(plane) in planes.html.erb I get the following error:
undefined local variable or method `plane' for #<#:0xd580e98>
Did you mean? #plane
plane_url
#planes
However, trying any of those doesn't really change the fact that I still get an error on the page and I can't even load it.
planes.html.erb
<table>
<thead>
<tr>
<th>Image</th>
<th>Operating agency</th>
<th>Date</th>
<th>Call sign</th>
<th>Country</th>
<th>Info</th>
<th>Action</th>
</tr>
<thead>
<tbody>
<% #planes.each do |p| %>
<tr class="gradeC">
<td>
<%= image_tag(p.image, size: "150x150")%></td>
<td class="w-25"><%= p.provider%>
</td>
<td><%= p.brand%></td>
<td class="center"><%= p.year%></td>
<td class="center"><%= p.call_sign%></td>
<td><%= p.country%></td>
<td><%= p.info%></td>
<td class="text-right">
<div class="btn-group">
<%= link_to 'Edit', edit_plane_path(plane), remote: true, :class =>'btn white btn btn-xs' %>
<button class="btn-white btn btn-xs">Delete</button>
</div>
</td>
</tr>
</tbody>
<% end %>
</table>
_form.html.erb
<!-- FORM EDIT -->
<div id="edit-plane" class="modal fade" aria-hidden="true">
<div class="modal-dialog modal-md">
<div class="modal-content">
<div class="modal-body">
<div class="row">
<div class="col-sm-12"><h3 class="m-t-none m-b">Edit plane</h3>
</div>
</div>
<%= form_for #plane, url: planes_path, remote: true do |f| %>
<div class="form-group row">
<div class="col-sm-6">
<label>Brand</label>
<%= f.text_field :brand, class:"form-control"%>
</div>
<div class="col-sm-5">
<label>Model</label>
<%= f.text_field :model, class:"form-control"%>
</div>
</div>
<div class="form-group row">
<div class="col-sm-5">
<label>Year</label>
<%= select_tag :hyear, options_for_select(["2015","2016","2017","2018","2019"], "2019"), class:"select2_demo_1 form-control" %>
<%= f.hidden_field :year %>
</div>
<div class="col-sm-6">
<label>Country</label>
<%= select_tag :hcountry, nil, class:"select2_demo_1 form-control" %>
<%= f.hidden_field :country %>
</div>
<script language="javascript">
populateCountries("hcountry");
</script>
</div>
<div class="form-group row">
<div class="col-sm-6">
<label>Provider</label>
<%= select_tag :hprovider, options_for_select([ "Test", "Test2"], "Test"), class:"select2_demo_1 form-control"%></select>
<%= f.hidden_field :provider %>
</div>
<div class="col-sm-5">
<label>Tactical call sign</label>
<%= f.text_field :call_sign, class:"form-control"%>
</div>
</div>
<div class="form-group row">
<div class="col-sm-6">
<label>Extra info</label>
<%= f.text_area :info %>
</div>
<div class="col-sm-5">
<label>Image</label>
<%= f.file_field :image %>
</div>
</div>
<!-- SUBMIT -->
<button class="btn btn-primary btn-lg float-right ml-2" id="cancelbtn">Cancel</button>
<%= f.submit "Submit", id:"edpla", class: 'btn btn-primary btn-lg float-right'%>
</div>
<% end %>
</div>
</div>
</div>
</div>
</div>
</div>
edit.js.erb
// Add the dialog title
$('#edit-plane h3').html("<i class=' glyphicon glyphicon-pencil'></i> Edit Plane");
// Render the edit form
$('.modal-body').html('<%= j render("form") %>');
// Show the dynamic dialog
$('#edit-plane').modal("show");
// Set focus to the first element
$('#edit-plane').on('shown.bs.modal', function () {
$('.first_input').focus()
})
update.js.erb
$('#edit-plane').modal('toggle');
$('#customer_<%= #plane.id %>').replaceWith('<%= j render (#plane) %>')
planes_controller.rb
class PlanesController < ApplicationController
def planes
#plane = Plane.new
#planes = Plane.all
end
def create
#plane = Plane.new(plane_params)
if #plane.save
flash[:success] = "Plane successfully added"
redirect_to :planes => 'post', :action => 'planes'
else
flash[:error] = "Something went wrong"
render 'planes'
end
end
def edit
#plane = Plane.find(params[:id])
end
def update
respond_to do |format|
if #plane.update(plane_params)
format.json { head :no_content }
format.js
else
format.json { render json: #customer.errors.full_messages, status: :unprocessable_entity }
end
end
end
private
def plane_params
params.require(:plane).permit(:brand, :model, :provider, :call_sign, :user, :country, :image, :info, :year)
end
end
My goal is to edit a plane in the table through a modal form, but I can't even show the page at the moment.
Here:
<% #planes.each do |p| %>
...you are passing each plane as p. Therefore, try:
<%= link_to 'Edit', edit_plane_path(p), remote: true, class: 'btn white btn btn-xs' %>
I have hit a brick wall. I've been hacking at this problem for so long now, I'm not even sure how I got to where I am. All I can say is, I've tried all of the below without success:
How to add bootstrap modal with link_to so the link content open in modal ?
How to show twitter bootstrap modal via JS request in rails?
rails link_to :remote
http://apidock.com/rails/ActionView/Helpers/PrototypeHelper/link_to_remote
How do I render "new", "edit" and "delete" views within Bootstrap modals on the "index" view rather than linking to separate pages for each?
Here is my code as it stands now. For now, lets ignore "edit" and "delete" and just focus on "new". When I click the "New" button, a modal with the string "<%= j render "items/new" %>" appears (instead of the form that that ruby statement should render). What am I doing wrong?:
items_controller.rb:
class ItemsController < ApplicationController
def index
#items = Item.all
end
def new
respond_to do |format|
format.js {}
end
end
def create
#item = Item.new(item_params)
if #item.save
flash[:notice] = "'#{#item.name}' saved!"
redirect_to items_path
else
flash[:notice] = "Something went wrong :("
render "index"
end
end
def edit
#item = Item.find(params[:id])
respond_to do |format|
format.js {}
end
end
def update
#item = Item.find(item_params[:id])
if #item.update_attributes(item_params)
flash[:notice] = "Successfully updated #{#item.name}."
redirect_to items_path
else
flash[:notice] = "Oops"
# render "edit"
end
end
private
def item_params
params.require(:item).permit(:name, :bid, :uuid)
end
end
items/index.html.erb
<div class="row">
<div class="col-xs-12">
<%= link_to "New", new_item_path, remote: true, class: "btn btn-success pull-right new", data: { toggle: "modal", target: "#newModal" } %>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<table class="table table-hover items">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>UUID</th>
<th colspan="2">Links</th>
</tr>
</thead>
<tbody>
<% #items.each do |item| %>
<tr>
<td><%= item.id %></td>
<td><%= item.name %>
<!-- edit/remove icons -->
<span class="edit-remove">
<%= link_to edit_item_path(item.id), remote: true, data: { toggle: "modal", target: "#editModal" } do %>
<span class="glyphicon glyphicon-pencil text-muted"></span>
<% end %>
<a href="#">
<span class="glyphicon glyphicon-remove text-muted"></span>
</a>
</span>
</td>
<td><%= item.uuid %></td>
<td><%= link_to "XXX", "http://xxx" %></td>
<td><%= link_to "XXXX", "http://xxx", target: "_blank" %></td>
</tr>
<% end %>
</tbody>
</table>
</div>
</div>
<!-- newModal skeleton -->
<div class="modal fade" id="newModal">
<div class="modal-dialog">
<div class="modal-content">
</div>
</div>
</div>
<!-- editModal skeleton -->
<div class="modal fade" id="editModal">
<div class="modal-dialog">
<div class="modal-content">
</div>
</div>
</div>
<!-- deleteModal skeleton -->
<div class="modal fade" id="deleteModal">
<div class="modal-dialog">
<div class="modal-content">
</div>
</div>
</div>
items/new.html.erb
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span>×</span></button>
<h4 class="modal-title">New Item</h4>
</div>
<div class="modal-body">
<%= form_for :item, url: { action: "create" } do |f| %>
<div class="form-group">
<%= f.label :name, "Name" %>
<%= f.text_field :name, { class: "form-control" } %>
</div>
<div class="form-group">
<%= f.label :bid, "BID" %>
<%= f.text_field :bid, { class: "form-control" } %>
</div>
<div class="form-group">
<%= f.label :uuid, "UUID" %>
<%= f.text_field :uuid, { class: "form-control" } %>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<%= submit_tag "Save", class: "btn btn-primary" %>
<% end %>
</div>
javascripts/items.js
$(document).on("page:change", function() {
$("#newModal .modal-content").html('<%= j render "items/new" %>');
});
In the case of new for instance, you want to render a javascript file. For this, you'll need to create items/new.js.erb.
Also, remove ", data: { toggle: "modal", target: "#newModal" }" from your link, we will do that in the javascript.
# new.js.erb
$("#newModal .modal-content").html('<%= j render "items/form" %>');
$("#newModal").modal(); // Or whatever the Bootstrap function is to render the modal
# items/_form.html.slim
# Here you'll put your form
You cannot use "render" on views directly, you should render partials and not views (this is why I asked you to put your form into a partial).
I threw this together and it puts a big '3' in my document 3 seconds after loading it:
<script>
setTimeout(function() {
$("#holder").html("<%= j render(:file => 'things/test.html.erb') %>");
}, 3000);
</script>
<div id="holder></div>
app/views/things/test.html.erb:
<h1><%= 1 + 2 %></h1>
That should get you going.
So far I've been able to make a modal that will 'create' a facility from the index page when user clicks the 'add new facility' button. Now my problem is trying to do the same thing except I want the user to be able to edit their facility using a modal from the index page as well. At this point when I click my 'edit' button on the webpage it opens a modal, but it is still the 'create facility' modal and not the 'edit modal'. Here's code:
views\facilities\index.html.erb
<h1>Facilities</h1>
<table class="table table-striped">
<thead>
<tr>
<th>Name</th>
<th>Abbr.</th>
<th>Status</th>
<th>Message</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<% #facilities.each do |facility| %>
<tr>
<td><%= facility.name %></td>
<td><%= facility.abbr %></td>
<td><%= facility.status %></td>
<td><%= truncate(facility.message, :length => 60, :seperator => ' ') %></td>
<td><%= link_to '<button class="btn btn-primary btn-edit" data-toggle="modal" data-target="#myModal2">Edit</button>'.html_safe, edit_facility_path(facility) %></td>
<td><%= link_to '<button class="btn btn-danger btn-edit">Destroy</button>'.html_safe, facility, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<div class="center" style="margin-top: 30px; margin-bottom: 80px;">
<!-- Future Modal Button -->
<%= link_to '<button class="center btn btn-success btn-fac" data-toggle="modal" data-target="#myModal1">Add New Facility</button>'.html_safe, new_facility_path %>
<!--<%= link_to '<button class="center btn btn-success btn-fac">Add New Facility</button>'.html_safe, new_facility_path %> -->
</div>
<!-- Create Modal -->
<div class="modal fade" id="myModal1" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id="myModalLabel">Add New Facility</h4>
</div>
<div class="modal-body">
<div class="small-container">
<%= simple_form_for(#facility) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :name %>
<%= f.input :abbr %>
<%= f.input :status, collection: ["Open", "Close", "Custom"], selected: ["Open"] %>
<%= f.input :message %>
</div>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
<!-- Edit Modal -->
<div class="modal fade" id="myModal2" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id="myModalLabel">Modal title</h4>
</div>
<div class="modal-body">
<div class="small-container">
<%= simple_form_for(#facility) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :name %>
<%= f.input :abbr %>
<%= f.input :status, collection: ["Open", "Close", "Custom"], selected: ["Open"] %>
<%= f.input :message %>
</div>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
Here's controllers\facilities_controller.rb
class FacilitiesController < ApplicationController
before_action :set_facility, only: [:show, :edit, :update, :destroy]
# GET /facilities
# GET /facilities.json
def index
#facility = Facility.new
#facilities = current_user.facilities.all
end
# GET /facilities/1
# GET /facilities/1.json
def show
#facility = current_user.facilities.find(params[:id]) rescue redirect_to(facilities_path)
end
# GET /facilities/new
def new
#facility = Facility.new
end
# GET /facilities/1/edit
def edit
#facility = current_user.facilities.find(params[:id]) rescue redirect_to(facilities_path)
end
# POST /facilities
# POST /facilities.json
def create
#facility = current_user.facilities.new(facility_params)
respond_to do |format|
if #facility.save
format.html { redirect_to facilities_path, notice: 'Facility was successfully created.' }
format.json { render action: 'show', status: :created, location: #facility }
else
format.html { render action: 'new' }
format.json { render json: #facility.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /facilities/1
# PATCH/PUT /facilities/1.json
def update
respond_to do |format|
if #facility.update(facility_params)
format.html { redirect_to #facility, notice: 'Facility was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #facility.errors, status: :unprocessable_entity }
end
end
end
# DELETE /facilities/1
# DELETE /facilities/1.json
def destroy
#facility.destroy
respond_to do |format|
format.html { redirect_to facilities_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_facility
#facility = Facility.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def facility_params
params.require(:facility).permit(:name, :abbr, :status, :message)
end
end
Let me know if more information is needed, thanks.
I want to create tasks by using ajax with loader.
Here is my View -
<%= form_for(#task, :remote => "true") do |f| %>
<center><h3>Organize Your Tasks</h3></center>
<table class="table table-bordered table-condensed table-striped">
<tr>
<td>
<%= f.select :taskcategory, options_for_select(["Money/Career", "Relationship", "Safety", "Health Care", "God", "Hobbies", "Society"]), {}, {:multiple => false} %>
</td>
<td style="width:120px;">
<%= f.text_field :taskname, :placeholder => "Task Name" %>
</td>
<td>
<%= f.select :importance, options_for_select(["Highly Important", "Important", "Less Important"]), {}, {:multiple => false} %></center>
</td>
<td style="width:120px;">
<%= f.text_field :startdate , :id => "from", :placeholder => "Start Date", :value => "#{Date.today.strftime("%d/%m/%Y") }" %>
</td>
<td style="width:120px;">
<%= f.text_field :targetdate , :id => "to", :placeholder => "End Date", :disabled => "ture"%>
</td>
<td>
<%= f.submit "Create", class: "btn"%>
</td>
</tr>
</table>
<% end %>
And here is my controller -
def create
#task= current_user.tasks.build(params[:task])
respond_to do |format|
if #task.save
flash[:success] = "Task created!"
format.html {redirect_to root_url }
format.js { redirect_to}
else
format.html { render 'static_pages/index'}
end
end
end
Here I write a code to show all tasks
<div class="tabbable" style="margin-left:-50px" >
<ul class="nav nav-tabs span10" id="myTab" style="margin-left:50px">
<li class="active">All Tasks(<%= current_user.tasks.where(:status => 'active').count %>)</li>
<li >Dreams(<%= current_user.tasks.where(:importance => 'Highly Important', :status => 'active').count %>)</li>
<li ><a href="#tab3" >Today's Tasks(<%= current_user.tasks.where(:targetdate => Date.today.to_s, :status => 'active').count %>)</a></li>
<li ><a href="#tab4" >Imp Tasks(<%= current_user.tasks.where(:importance => 'Important', :status => 'active').count %>)</a></li>
<li id="fat-menu" class="dropdown aa">
Others
<ul class="dropdown-menu">
<li><a href="#tab5" >Postpone(<%= current_user.tasks.where(:status => 'postpone').count %>)</a></li>
<li><a href="#tab6" >Satisfied(<%= current_user.tasks.where(:status => 'satisfied').count%>)</a></li>
<li><a href="#tab7" >Unsatisfied(<%= current_user.tasks.where(:status => 'unsatisfied').count%>)</a></li>
<li><a href="#tab8" >Closed(<%= current_user.tasks.where(:status => 'closed').count%>)</a></li>
</ul>
</li>
</ul>
<div class="tab-content span10" >
<div class="tab-pane active" id="tab1">
<%= render 'shared/feed' %>
</div>
<div class="tab-pane" id="tab2">
<%= render 'shared/feed_dream' %>
</div>
<div class="tab-pane" id="tab3">
<%= render 'shared/feed_urgent' %>
</div>
<div class="tab-pane" id="tab4">
<%= render 'shared/feed_important' %>
</div>
<div class="tab-pane" id="tab5">
<%= render 'shared/feed_postpone' %>
</div>
<div class="tab-pane" id="tab6">
<%= render 'shared/feed_satisfied' %>
</div>
<div class="tab-pane" id="tab7">
<%= render 'shared/feed_unsatisfied' %>
</div>
<div class="tab-pane" id="tab8">
<%= render 'shared/feed_closed' %>
</div>
</div>
Here is my create.js.ejb ---
page.replace_html('index' , redirect_to root_url)
When i submit my task then it creates in database but page is not updated. When i again refresh the page then task is showing. I know the problem in create.js.ejb file. How can i show update tasks in my table??
First of all make sure that you have included jquery and jquery_ujs into your application.js file.
Its a bad habit to redirect from the view. Make it format.js { redirect_to root_url}
And use *.js.erb template instead of rjs template.
In create.js.erb you might do something like this
$("#some_div").append("some HTML content that is related to created record")
Hope this helps
page.replace_html('index' , redirect_to root_url) // this is invalid
"page.replace_html" no longer works in rails 3
In create.js.erb
alert("record created");
// or update div with id some_div_id
$("#some_div_id").html("<%= escape_javascript(render :partial => 'some_partial') %>");
He
I have two models in my rails application (Post, Picture) that are associated as follows:
#Post model
has_many :pictures, :dependent => :destroy
accepts_nested_attributes_for :pictures, :allow_destroy => true
#Picture model
belongs_to :post
In my post edit view I have two forms, so I can edit the post content as well as add pictures to the post. I use the jquery file upload plugin together with carrierwave to handle the upload process. This looks quite similar to this setup here http://tinyurl.com/aun7bl5
When I go to the post edit view the jquery file upload always shows me all pictures, because it uses the index action of the picture controller which fetches all images and renders them to json so jquery file upload can handle them. The index action looks like this.
def index
#pictures = Picture.all
render :json => #pictures.collect { |p| p.to_jq_upload }.to_json
end
The post param (:id) is available to the post controller when I edit a post. I can see it with the logger. But it is not available to the index action which is nested inside of the post edit form.
Now my question is, how I can provide the index action in the post controller with the id of the post I like to edit so that I can do there something like this to filter the pictures it gets:
def index
#pictures = Picture.where(:post_id => params[:id])
render :json => #pictures.collect { |p| p.to_jq_upload }.to_json
end
EDIT:
#Post#edit view
<div class=post-well>
<div class="page-header">
<h1>Reisebericht editieren</h2>
</div>
<%= simple_form_for #post do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :title, :label => "Titel", :input_html => { :class => 'new-post-inputfields' } %>
<%= f.input :body, :label => "Artikel", :input_html => { :class => 'new-post-inputfields' } %>
<%= f.hidden_field :picture_ids, :input_html => { :id => 'post_picture_ids' } %>
<%= f.button :submit, :label => "Speichern" %>
</div>
<% end %>
<h4>Bilder verwalten</h4>
<%= simple_form_for Picture.new, :html => { :multipart => true, :id => "fileupload" } do |f| %>
<!-- The fileupload-buttonbar contains buttons to add/delete files and start/cancel the upload -->
<div class="row fileupload-buttonbar">
<div class="span7">
<!-- The fileinput-button span is used to style the file input field as button -->
<span class="btn btn-success fileinput-button">
<i class="icon-plus icon-white"></i>
<span>Hinzufügen</span>
<%= f.file_field :path, multiple: true, name: "picture[path]" %>
</span>
<button type="submit" class="btn btn-primary start">
<i class="icon-upload icon-white"></i>
<span>Upload</span>
</button>
<button type="reset" class="btn btn-warning cancel">
<i class="icon-ban-circle icon-white"></i>
<span>Abbrechen</span>
</button>
<button type="button" class="btn btn-danger delete">
<i class="icon-trash icon-white"></i>
<span>Delete</span>
</button>
<input type="checkbox" class="toggle">
</div>
<div class="span5">
<!-- The global progress bar -->
<div class="progress progress-success progress-striped active fade">
<div class="bar" style="width:0%;"></div>
</div>
</div>
</div>
<!-- The loading indicator is shown during image processing -->
<div class="fileupload-loading"></div>
<br>
<!-- The table listing the files available for upload/download -->
<table class="table table-striped"><tbody class="files" data-toggle="modal-gallery" data-target="#modal-gallery"></tbody>
</table>
<% end %>
</div>
<script>
var fileUploadErrors = {
maxFileSize: 'File is too big',
minFileSize: 'File is too small',
acceptFileTypes: 'Filetype not allowed',
maxNumberOfFiles: 'Max number of files exceeded',
uploadedBytes: 'Uploaded bytes exceed file size',
emptyResult: 'Empty file upload result'
};
</script>
<!-- The template to display files available for upload -->
<script id="template-upload" type="text/x-tmpl">
{% for (var i=0, file; file=o.files[i]; i++) { %}
<tr class="template-upload fade">
<td class="preview"><span class="fade"></span></td>
<td class="name"><span>{%=file.name%}</span></td>
<td class="size"><span>{%=o.formatFileSize(file.size)%}</span></td>
{% if (file.error) { %}
<td class="error" colspan="2"><span class="label label-important">{%=locale.fileupload.error%}</span> {%=locale.fileupload.errors[file.error] || file.error%}</td>
{% } else if (o.files.valid && !i) { %}
<td>
<div class="progress progress-success progress-striped active"><div class="bar" style="width:0%;"></div></div>
</td>
<td class="start">{% if (!o.options.autoUpload) { %}
<button class="btn btn-primary">
<i class="icon-upload icon-white"></i>
<span>{%=locale.fileupload.start%}</span>
</button>
{% } %}</td>
{% } else { %}
<td colspan="2"></td>
{% } %}
<td class="cancel">{% if (!i) { %}
<button class="btn btn-warning">
<i class="icon-ban-circle icon-white"></i>
<span>{%=locale.fileupload.cancel%}</span>
</button>
{% } %}</td>
</tr>
{% } %}
</script>
<!-- The template to display files available for download -->
<script id="template-download" type="text/x-tmpl">
{% for (var i=0, file; file=o.files[i]; i++) { %}
<tr class="template-download fade">
{% if (file.error) { %}
<td></td>
<td class="name"><span>{%=file.name%}</span></td>
<td class="size"><span>{%=o.formatFileSize(file.size)%}</span></td>
<td class="error" colspan="2"><span class="label label-important">{%=locale.fileupload.error%}</span> {%=locale.fileupload.errors[file.error] || file.error%}</td>
{% } else { %}
<td class="preview">{% if (file.thumbnail_url) { %}
<img src="{%=file.thumbnail_url%}">
{% } %}</td>
<td class="name">
{%=file.name%}
</td>
<td class="size"><span>{%=o.formatFileSize(file.size)%}</span></td>
<td colspan="2"></td>
{% } %}
<td class="delete">
<button class="btn btn-danger" data-type="{%=file.delete_type%}" data-url="{%=file.delete_url%}">
<i class="icon-trash icon-white"></i>
<span>{%=locale.fileupload.destroy%}</span>
</button>
<input type="checkbox" name="delete" value="1">
</td>
</tr>
{% } %}
</script>
And the javascript:
$(function () {
// Initialize the jQuery File Upload widget:
$('#fileupload').fileupload({
completed: function(e, data) {
console.log(data.result[0].picture_id);
$("#post_picture_ids").val(function(i,val) {
return val + (val ? ', ' : '') + data.result[0].picture_id;
});
}
});
// Load existing files:
$.getJSON($('#fileupload').prop('action'), function (files) {
var fu = $('#fileupload').data('fileupload'),
template;
fu._adjustMaxNumberOfFiles(-files.length);
template = fu._renderDownload(files)
.appendTo($('#fileupload .files'));
// Force reflow:
fu._reflow = fu._transition && template.length &&
template[0].offsetWidth;
template.addClass('in');
$('#loading').remove();
});
});
Any help with this would be appreciated.
EDIT2: For one solution see below under #SybariteManoj answer. Another solution is to use:
$.getJSON($('#fileupload').prop('action') + '/' + $('#current_post_id').val(), function (files) {
in the beginning of the get function and then add a route for the pictures controller as follows:
get 'pictures/:id', to: 'pictures#index'
The index action in the pictures controller will then filter for the id parameter in this solution and looks like this:
def index
#pictures = Picture.where(:post_id => params[:id])
render :json => #pictures.collect { |p| p.to_jq_upload }.to_json
end
I think I prefer the full solution of #SybariteManoj so there is no need for a route and the index action loks like this now.
def index
#pictures = Picture.where(:post_id => params[:post_id])
render :json => #pictures.collect { |p| p.to_jq_upload }.to_json
end
I think I got the culprit. In your javascript, $.getJSON($('#fileupload').prop('action') this is passing the value of the action attribute of the image upload form.
Try adding this line somewhere in your edit view file
<%= hidden_field_tag :current_post_id, #post.id, :id => 'current_post_id' %>
and replace this line
$.getJSON($('#fileupload').prop('action'), function (files) {
with
$.getJSON($('#fileupload').prop('action') + '?post_id=' + $('#current_post_id').val(), function (files) {
I haven't tested it but I am quite sure this should solve your issue.
Since you are editing the post, the post params[:id] is available to the post controller's update action and not to others which is the default action call after editing the form in rails.
If you want the params[:id] in the index action then you need to either redirect to the index action after update action is called or you need to put the logic of showing the selected pictures in the update action only.
You can also create a custom action method to handle the process of showing the pictures that belongs to the post.
I suppose that your Picture has a foreign_key named post_id and you can simply use this in your index action to get only pictures which belong to the Post.
Try something like this :
def index
#pictures = #post.pictures
render :json => #pictures.collect { |p| p.to_jq_upload }.to_json
end
EDIT
Since your pictures belong_to your post, you also need to modify the new and create actions so that you create a picture for your post.
One way to do that is to create a method find_post in your Picture controller, and make a before_filter callback like this :
class PicturesController < ApplicationController
before_filter :find_post, :only => [:index, :new, :create]
def find_post
#post = Post.find(params[:post_id]) unless params[:post_id].nil?
end
def new
#picture = #post.pictures.new
end
## Same thing for the create action
end
And in your view, do the same when you create you form :
<%= simple_form_for #post.pictures.new
Hope this helps.