Cannot upload file - ruby-on-rails

I have problems to upload a file:
Here is my html:
<%= form_tag import_test_path, multipart: true do %>
<%= file_field_tag :file, :style => 'display:inline; margin-top:-10px' %>
<%= submit_tag 'Hochladen', :class => 'btn btn-sm btn-info' %>
<% end %>
First i tried to simply upload it and to handle it in my controller like this:
def import
widgets = DBF::Table.new(params[:file], nil, 'cp1252')
w = widgets.find(6)
p = Patient.new
p.vorname = w.vorname
p.name = w.name
p.geburtsdatum = w.geburt
p.save
respond_to do |format|
format.html {redirect_to :back }
end
end
But this provoced an error:
no implicit conversion of ActionDispatch::Http::UploadedFile into String
in line: DBF::Table.new(params[:file], nil, 'cp1252')
Next i tried to generate first an Tempfile:
def import
file = Tempfile.new(params[:file])
widgets = DBF::Table.new(file, nil, 'cp1252')
w = widgets.find(6)
p = Patient.new
p.vorname = w.vorname
p.name = w.name
p.geburtsdatum = w.geburt
p.save
respond_to do |format|
format.html {redirect_to :back }
end
end
But this also proved an error:
unexpected prefix_suffix: #<ActionDispatch::Http::UploadedFile:0x6793d10 #tempfile=# <Tempfile:C:/Users/EMMANU~1/AppData/Local/Temp/RackMultipart20131110-6816-ogkd3i>, #original_filename="patient.DBF", #content_type="application/octet-stream", #headers="Content-Disposition: form-data; name=\"file\"; filename=\"patient.DBF\"\r\nContent-Type: application/octet-stream\r\n">
in line: file = Tempfile.new(params[:file])
What do i wrong? Thanks and have a nice day!

Accessing params[:file] is a ActionDispatch::Http::UploadedFile which is just a wrapper for the TmpFile that is used to store the uploaded content.
You need to read from that IO like object to get the contents.

Try DBF::Table.new(params[:file].path, nil, 'cp1252')

Related

Create multiple objects on a button click in Rails

I have template_sections and sections and on a button click in my view I want
a) get all template_sections with a specific template_id, send them to the sections_controller
or
b) the section_controller method transform should get the template_sections there
and
iterate over them and create a new section object for each one of them, where I would set is_template = 0 and template_id = nil and save them.
View:
<div class="col-2 deploy-template">
<%= button_to 'Deploy Template', transform_sections_path, method: :post, *{call controller's method or send objects from here to transform method}*, remote: true, type: 'button', class: "btn btn-secondary btn-sm ml-0 mr-4" %>
</div>
Controller:
def new
#section = Section.new
if params[:is_template]
date = (Time.at(params['day'].to_i*86400-1)).strftime("%Y-%m-%d")
#section.starts_at_datetime = (date + ' ' + params['time']).in_time_zone rescue nil
else
#section.starts_at_datetime = (params['date'] + ' ' + params['time']).in_time_zone rescue nil
end
respond_to do |format|
format.js
end
end
def create
#section = Section.new(section_params)
#section.account_id = session_account_id
#section.is_template = true if params[:section][:is_template] == 'true'
#section.template_id = params[:section][:template_id]
respond_to do |format|
if #section.save
format.js
flash.now[:success] = "saved successfuly"
create_event #section, "create", "Create"
else
flash.now[:danger] = "#{#section.errors.full_messages}"
format.js { render 'layouts/notifications' }
end
end
end
def transform
template_sections.each do |template_section|
#save each template_section with is_template = 0 and template_id = nil
end
What you can do is pass your template sections to your controller through the params hash like so:
<%= button_to 'Deploy Template', method: :post, transform_sections_path(template_sections: [YOUR ARRAY VARIABLE HERE]), remote: true, type: 'button', class: "btn btn-secondary btn-sm ml-0 mr-4" %>
Your template sections should then be available through params[:template_sections] inside of your controller for you to do whatever you feel like doing, (I am assuming post: template_sections_path points to the transform action in your controller).
def transform
template_sections = params[:template_sections]
template_sections.each do |template_section|
#save each template_section with is_template = 0 and template_id = nil
end
I don't know what your TemplateSection model looks like so I will refrain from writing controller code that won't work, but hopefully once you have the data in your controller you will be able to work through it, and if not I am happy to help with a little bit more information.
As an additional note, "method: :post", and "type: button" seem redundant when using a button_to tag as those are the defaults, you can remove them unless you have a specific reason for having them.

How to fix 'Rails.ajax' error in site Console?

I have 2 different post types (news and articles). When i go to news and try to comment any news, nothing happen. In google chrome console it says:
POST /news/artifact-v-spiske-liderov-prodazh-steam-po-itogam-2018-goda/comments/ 404
rails-ujs.self-d109d8c5c0194c8ad60b8838b2661c5596b5c955987f7cd4045eb2fb90ca5343.js?body=1:7
Rails.ajax # rails-ujs.self-d109d8c5c0194c8ad60b8838b2661c5596b5c955987f7cd4045eb2fb90ca5343.js?body=1:7
Rails.handleRemote # rails-ujs.self-d109d8c5c0194c8ad60b8838b2661c5596b5c955987f7cd4045eb2fb90ca5343.js?body=1:31
(anonymous) # rails-ujs.self-d109d8c5c0194c8ad60b8838b2661c5596b5c955987f7cd4045eb2fb90ca5343.js?body=1:5
BUT! When i try comment in Articles type, all good, comments work. What is problem?
My _form.html.haml:
- if user_signed_in? && current_user.mute_to && current_user.mute_to > Time.current
%div
%strong
= "Вы не можете писать комментарии до #{current_user.mute_to.strftime("%F %R")}"
- elsif user_signed_in?
= form_with model: [commentable, Comment.new], html: { class:
local_assigns[:class], data: { target: local_assigns[:target] } } do |form|
.form-group
= form.text_area :body, placeholder: "Напишите комментарий (минимум 3 символа)", class: "form-control"
.form-group
= form.hidden_field :parent_id, value: local_assigns[:parent_id]
= form.submit 'Отправить', class: "btn"
My _comment.html.haml:
- nesting = local_assigns.fetch(:nesting, 1)
- max_nesting = local_assigns[:max_nesting]
- continue_thread = local_assigns[:continue_thread]
= tag.div id: dom_id(comment), class: "border-left pl-4 my-4" do
- if comment.deleted?
%strong [комментарий удален]
%small
= link_to time_ago_in_words(comment.created_at), url_for(comment: comment.id, anchor: dom_id(comment))
%p [комментарий удален]
- else
- comments_user = comment.user
%strong.comments_user_line
= fa_icon "user-circle", class: "mr-1"
= link_to comments_user.nickname, user_path(comments_user), class: 'user_link'
%small
= link_to time_ago_in_words(comment.created_at), polymorphic_path(comment.commentable, comment: comment.id, anchor: dom_id(comment))
= simple_format comment.body
%div.comments_block
- if user_signed_in? && current_user.mute_to && current_user.mute_to > Time.current
- else
%small
- if user_signed_in?
%btn.reply Отвеить
- else
= link_to "Отвеить", new_user_session_path
= link_to "Удалить", [comment.commentable, comment], method: :delete, data: {confirm: "Вы уверены?"} if comment.user == current_user
= render partial: "comments/form", locals: { |
commentable: comment.commentable, |
parent_id: reply_to_comment_id(comment, nesting, max_nesting), |
class: "mt-4 d-none replies_form", |
target: "reply.form" |
} |
= tag.div id: "#{dom_id(comment)}_comments" do
- if continue_thread.present? && nesting >= continue_thread && comment.comments.any?
= link_to "Открыть ветку", url_for(comment: comment.id, anchor: dom_id(comment))
- else
= render comment.comments, continue_thread: continue_thread, nesting: nesting + 1, max_nesting: local_assigns[:max_nesting]
My comments_controller.rb:
class CommentsController < ApplicationController
before_action :authenticate_user!
def create
#comment = #commentable.comments.new(comment_params)
#comment.user = current_user
if #comment.save
respond_to do |format|
format.html { redirect_to #commentable }
format.js
end
else
redirect_to #commentable, alert: "Ошибка :("
end
end
def destroy
#comment = #commentable.comments.find(params[:id])
return false unless current_user.id == #comment.user_id
#comment.destroy
redirect_to #commentable
end
private
def comment_params
params.require(:comment).permit(:body, :parent_id)
end
end
If i uncomment rails-ujs in application.js like this:
require rails-ujs
Then when i posting comment it will be say:
ActiveRecord::RecordNotFound in News::CommentsController#create
Couldn't find News with 'id'=artifact-v-spiske-liderov-prodazh-steam-po-itogam-2018-goda
Extracted source (around line #7):
6 def set_commentable
7 #commentable = News.find(params[:news_id])
8 end
9 end
How i can fix it? Thanks!
The first suggestion - comment require rails-ujs until you solve the issue. It will be easier to debug.
Then, the issue is that as a params[:news_id] you are passing news slug (artifact-v-spiske-liderov-prodazh-steam-po-itogam-2018-goda) instead of news id. One solution is to modify the code to pass news id as params[:news_id].
Another, a little big uglier solution, is to refactor set_commentable method in the News::CommentsController to something like this:
def set_commentable
#commentable = News.find_by(slug: params[:news_id])
end
However, it might break other places where set_commentable is used.

ActiveRecord::StatementInvalid in Show Controller

I've got a simple search form, in rails 4 app, that needs two params passed to be able to show relevant data.
I'm getting an 'Mysql2::Error: Unknown column 'data inputted' but the columns do exist. If I instead of '#search = Page.where(params[:one] && params[:two])' use '#search = Page.all' the data shows, but all of it shows.
Form
<%= form_tag(page_show_path, id: "search-form") do %>
<%= text_field_tag :one, params[:one], placeholder: "One" %>
<%= text_field_tag :two, params[:two], placeholder: "Two" %>
<%= submit_tag "Search", :name => nil %>
<% end %>
Model
def self.one(query)
where("one = ?", "%#{query}%")
end
def self.two(query)
where("two = ?", "%#{query}%")
end
Controller
def show
if (params[:one] && params[:two]).present?
#search = Page.where(params[:one] && params[:two])
else
redirect_to page_path, notice: "Not a valid combination"
end
end
You can Create and Use Scope.
scope :find_one_two, ->(query_one, query_two) { where("one = ? AND two = ? ", query_one, query_two) }
#search = Page.find_one_two(params[:one], params[:two])
OR
You can use.
#search = Page.where("one = ? AND two = ?", params[:one], params[:two])
def show
if (params[:one] && params[:two]).present?
#search = Page.where("one like ? AND two like ? ", "%#{params[:one]}%", "%#{params[:two]}%")
else
redirect_to page_path, notice: "Not a valid combination"
end
end
This may solve your problem.

Specific AJAX request failing in Rails 4

This one has been bugging me for a while. Hoping someone can help...
I have an ajax request as follows (this one works perfectly).
Controller:
def destroy
#property = Property.find(params[:property_id])
#property_asset = #property.property_assets.find(params[:id])
#property_asset.destroy
property = Property.find(params[:property_id])
#images = property.property_assets.asset_content_type_starts_with('image')
#videos = property.property_assets.asset_content_type_starts_with('video')
#docs = property.property_assets.asset_content_type_starts_with('application')
respond_to do |format|
format.html
format.js
flash[:notice] = "Deleted"
end
end
Destroy.js.haml:
$("#images").html("#{escape_javascript(render 'images')}");
$("#videos").html("#{escape_javascript(render 'videos')}");
$("#docs").html("#{escape_javascript(render 'docs')}");
This method, when called renders the partials on the page without needing to do refresh. Exactly what I want.
On the same page I have a file upload that calls a Create method:
def create
#property = Property.find(params[:property_id])
#property_asset = #property.property_assets.create
property = Property.find(params[:property_id])
#images = property.property_assets.asset_content_type_starts_with('image')
#videos = property.property_assets.asset_content_type_starts_with('video')
#docs = property.property_assets.asset_content_type_starts_with('application')
if #property_asset.save
if #property_asset.update(property_asset_params)
respond_to do |format|
format.html
format.js
flash[:notice] = "File added"
end
end
end
end
_create.js.haml is the same as the destroy file above but does not work with the any of the renders. So if I was to just try
$("#images").html("#{escape_javascript(render 'images')}");
The create method takes me to create.js.haml fine, I know if this because I can just enter a console.log and it spits out fine, but adding the line above and the console.log line fails and it doesnt render.
The images partial is:
- #images.each do |asset|
= form_for [#property, asset], remote: true do |f|
- if asset.id.present?
.row
.large-2.columns
%ul.clearing-thumbs{"data-clearing" => ""}
%li
%a{href: asset.asset.url}
%img{src: asset.asset(:thumb)}
.large-10.columns
.row
.large-12.columns
= f.text_field :description, :placeholder => 'Description', :id => 'test1'
.row
.large-8.columns
%p
= f.check_box :private, :id => 'private'
%label{for: "private"} Private
.large-2.columns
= f.submit 'Update', :class => 'button tiny right round', :disabled => '', :html => { :id => "update#{asset.id}" }, :remote => true
.large-2.columns
%p.right
= link_to 'Delete', [#property, asset], method: :delete, :class => 'button tiny right round alert', :remote => true
Let me know if I need to clarify anything. thanks.
Logs
This is when I just add in a simple console.log. JS console outputs fine. All ok.
(18.8ms) commit transaction
Rendered property_assets/create.js.haml (1.9ms)
Completed 200 OK in 4474ms (Views: 13.4ms | ActiveRecord: 169.5ms)
This is when I add
$("#images").html("#{escape_javascript(render 'images')}");
When the render is added log is:
Rendered property_assets/_images.html.haml (19.0ms)
Rendered property_assets/create.js.haml (23.6ms)
Completed 200 OK in 4017ms (Views: 34.7ms | ActiveRecord: 54.1ms)
The log before that is all the same, I'm adding a file into PropertyAsset using paperclip and I have papertrail tracking versions. When the render fails I need to refresh the page in order for the image to appear in the list.

Import CSV - No such file or directory

When I want to select a file via file_field, it gives me the error that my file is 'nil'. Here's the error: "No such file or directory - Book1.csv"
May I know why? Below are the codes:
controller
def import_csv
#list = List.find(params[:list_id])
#lists = List.all
respond_to do |format|
#csv_text = File.read(params[:list][:file])
#csv = CSV.parse(#csv_text, :headers => true)
#n=0
#csv.each do | row |
#user_new = User.new
#user_new.first_name = row[0]
#user_new.last_name = row[1]
#user_new.email = row[2]
#user_new.company = row[3]
#user_new.address = row[4]
#user_new.city = row[5]
#user_new.state = row[6]
#user_new.zipcode = row[7]
#user_new.country = row[8]
#user_new.notes = row[9]
#user_new.birthday = row[10]
#user_new.home_number = row[11]
#user_new.mobile_number = row[12]
#user_new.list_id = #list.id
#user_new.save
#list.subscribers += 1
#list.save
#n=#n+1
GC.start if #n%50==0
flash[:notice] = "CSV Imported Successfully, with #{#n} records"
end
format.html { redirect_to lists_url }
format.json { head :no_content }
end
end
view
<%= form_for(:list, :url => list_import_csv_path(#list), :method => :get, :html => {:multipart => true}) do |f| %>
<table>
<tr>
<td><label for="dump_file">Select a CSV File :</label></td>
<td><%= f.file_field :file %></td>
</tr>
<tr>
<td colspan='2'><%= submit_tag 'Import from CSV file' %></td>
</tr>
</table>
<% end %>
This is because you try to pass the ActionDispatch::Http::UploadedFile Object as a path instead of the real path. You do:
#csv_text = File.read(params[:list][:file])
you should do:
#csv_text = File.read(params[:list][:file].tempfile.to_path.to_s)
Also it might be a problem that you use :method => :get when you upload not so tiny files. Genereally GET and File Upload arent such a great combination.^^
6/27/2017 - Hopefully someone will benefit from this if they are in the same situation I was.
It turns out, whereas I had:
= form_tag action: :bulk_upload_submit, multipart: true do
...
= file_field_tag :file, accept: 'text/csv'
and it was sending the file params as:
"file"=>"subscribers.csv"
I needed to change the form_tag to use a path instead of an action:
= form_tag upload_subscribers_path, multipart: true do
which changed the params to:
"file"=>
#<ActionDispatch::Http::UploadedFile:0x007ffda857b5e0
#content_type="text/csv",
#headers="Content-Disposition: form-data; name=\"file\"; filename=\"subscribers.csv\"\r\nContent-Type: text/csv\r\n",
#original_filename="subscribers.csv",
#tempfile=#<File:/var/folders/_4/50fjk9z57x544klj30k0g1780000gn/T/RackMultipart20170627-33947-12xwfow.csv>>

Resources