Argument error for file uploading with rails 3.1 app - ruby-on-rails

I'm trying to set up a very basic system for uploading files to my rails 3.1 app. Before people start throwing paperclip and carrierwave links at me, let me say that this is NOT the solution that I am looking for. I have read quiet a few posts on this topic, however, all the code I saw was either depreciated in rails 3.1 or I just did not understand how people came to a solution to this problem.
Updated view/form: (haml)
%h1 File Upload
= form_for :upload,:url=>{:action => 'uploadFile'},:html => { :multipart => true } do |f|
%p
%label{:for => "upload_file"} Select File
\:
\#{f.file_field 'datafile'}
= f.submit "Upload"
Updated controller:
class UploadController < ApplicationController
def index
render :file => 'upload/uploadfile.haml'
end
def uploadFile
file_param = params[:upload][:datafile]
post = DataFile.save(file_param)
render :text => "File has been uploaded successfully"
end
end
Updated model
class DataFile < ActiveRecord::Base
def self.save(upload)
# Changed Default Destination: [__RAILS_DIR__/public/data]
name = "public/data/" + upload.original_filename
# can haz data directory?
require 'FileUtils'
FileUtils.mkdir_p(File.dirname(name))
File.open(name, "wb") { |f| f.write(upload.read) }
end
end
The Solution:
Above is the correct code I used to add simple uploading functionality to my rails 3.1 app

You are passing unnecessary argument "file" to the uploadFile method. It's an action and passing argument to it is not possible. Just remove the "file" argument.

Related

How to build Help based on Markdown in Ruby on Rails 5?

I am willing to create Help manual pages using Markdown files within my Rails application. I am already using Markdown for limited elements in some pages, but I now want to create dynamic pages using MD files. Searching around, I found some tips, but no complete HowTo.
My main issue was generating the route to various pages based on the requested MarkDown file. I propose the solution below, which fits well for documenting my application, and also allows contributors to easily enrich or translate the documentation.
Writing this question, I found the solution.
Here is what I did:
1 - I created a hierarchy of folders in public for supporting several languages. Each folder contains a help_index.md file, which contains links to other MD files:
public
help-en
help-index.md
logging.md
user-ceation.md
help-fr
help-index.md
logging.md
etc.
2 - I created a route (routes.rb) to reach these pages based on the page name:
# get '/help',
get 'help/*page_name', :controller => 'help', :action => 'help', :as => :help
3 - I created a link from the application header (application.html.erb):
<%= link_to t('Help'), help_path("help_index") %>
4 - I created a template for the help pages:
<% provide(:title, t('Help')) %>
<h1>Help pages</h1>
<p>
<%= displayHelp %>
</p>
5 - I created a controller (help_controller.rb) for displaying the page:
class HelpController < ApplicationController
def help
end
end
6 - I created a helper (application_helper.rb) for interpreting Markdown based on Redcarpet gem:
module ApplicationHelper
def markdown
markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML, :autolink => true, :space_after_headers => true)
end
def displayHelp
filename = File.join(Rails.root, 'public', "help-#{I18n.locale.to_s}", "#{params[:page_name]}.md")
begin
file = File.open(filename, "rb")
markdown.render(file.read).html_safe
rescue Errno::ENOENT
render :file => "public/404.html", :status => 404
end
end
end
And it works fine!

Rails4: How do I store images uploaded by carrierwave in private folder?

I have uploaded images with carrierwave under the public folder.
For security reason, I'm going to change the folder to under the root.
Althogh I referred to the post How to: Secure Upload and created carrierwave.rb, I don't know how to write the path uploaded by carrierwave.
How can I display images under private folder?
image_uploader.rb
class ImageUploaader < CarrierWave::Uploader::Base
storage :file
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
end
I created \config\initializers\carrierwave.rb
CarrierWave.configure do |config|
config.permissions = 0600
config.directory_permissions = 0700
config.root = Rails.root
end
I also created images_controller.rb
class ImagesController < ApplicationController
#I tried some, but doesn't work
end
I have used the following view to display images.
\views\articles\ _article.html.erb
<% article.photos.each do |photo| %>
<%= image_tag(photo.image_url(:thumb).to_s, class: :thumb) if photo.image? %>
<% end %>
It would be appreciated if you could specify the code in routes.rb, images_controller.rb and _article.html.erb.
I'm running through Rails 4 In Action and we had a similar need. In that book they had us create a folder under the app root called "files".
Then we changed the line in your uploader from:
uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}
to
files/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}
Now, in that book, files get dropped to the files directory. You then set permissions using something like CanCanCan or writing it yourself. That seems to be it. I think.
It's an old question, maybe it will help someone as it helped me.
I think you misunderstand the explanation in the reference:
Add this route:
match "/uploads/photos/:id/:basename.:extension", controller: "photo", action: "send_img", via: :get
So every URL requests like: /uploads/photos/1/best_ever_img.png will be "redirected" to send_img action in photos controller
On your action,
class Photos
mount_uploader :image, ImageUploaader
def send_img
id = params[:id]
basename = params[:basename]
extension = params[:extension]
type = params[:type]
# if you have a different environment in your dev and production, you can add each unique route
if Rails.env.development?
# The route to your project folder
# My dev server is on windows Linux shell so the route is like this, you may use other development environment so just update the route
base_url = "/mnt/c/Users/YOUR_USER_NAME/Desktop/Sites/"
else
base_url = "/home/deploy"
end
# Replace the `YOUR_PROJECT_FOLDER` with name of yours
path = "#{base_url}/YOUR_PROJECT_FOLDER/uploads/photos/image/#{id}/#{basename}.#{extension}"
send_file path, x_sendfile: true
end
In your view, load the image like this:
<%= image_tag "uploads/photos/#{photo.id}/#{File.basename(photo.image.url)}" %>

undefined method `original_filename' for String

I'm trying to implement a csv upload functionality WITHOUT using gems such as paperclip. Here's the view:
%h1 Add Users From CSV
= form_tag(:action => "upload",:multipart => true,:method => :post) do
= file_field_tag 'csv'
= submit_tag 'Upload'
And here's the controller:
def upload
csv_io = params[:csv]
File.open(Rails.root.join('public', 'uploads', csv_io.original_filename), 'wb') do |file|
file.write(csv_io.read)
end
redirect_to root_path, :notice => "Successfully uploaded csv!"
end
But I got this error message when I'm uploading a csv called data.csv
undefined method `original_filename' for "data.csv":String
I just followed the official Rails guide, but it's still getting error. Can anyone suggest some solutions?
NOTE: I just need to read data from the csv file and it does not need to be saved persistently on server.
The way you're passing the arguments to form_tag, all your arguments are getting treated as part of the first form_tag parameter url_for_options, instead of going in part to the second parameter options (see http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html#method-i-form_tag for the method definition).
Per the guide at http://guides.rubyonrails.org/form_helpers.html#uploading-files, you can use the following syntax to achieve what you want:
form_tag({:action => "upload"},:multipart => true)
You don't need to set :method because it defaults to post.

How can I add a view path to Rails's partial rendering lookup?

I'd like to have the following directory structure:
views/
app1/
users/_user.html.erb
users/index.html.erb
app2/
users/index.html.erb
shared/
users/_user.html.erb
users/index.html.erb
In my view, I'd call
# app1/users/index.html
<%= render :partial => "user" %>
# => /app1/users/_user.html.erb
# app2/users/index.html
<%= render :partial => "user" %>
# => /shared/users/_user.html.erb
So basically, how do I tell Rails to check in the /app2/users dir then the shared dir before it raises it's missing template error?
Update
I got around this (as suggested by Senthil, using File.exist?
Here's my solution - feedback and suggestions welcome
# application_helper.rb
# Checks for a partial in views/[vertical] before checking in views/shared
def partial_or_default(path_name, options={}, &block)
path_components = path_name.split("/")
file_name = path_components.pop
vertical_file_path = File.join(vertical}, path_components, file_name)
shared_file_path = File.join("shared", path_components, file_name)
full_vertical_file_path = File.join("#{Rails.root}/app/views/", "_#{vertical_file_path}.html.erb")
attempt_file_path = File.exist?(full_vertical_file_path) ? vertical_file_path : shared_file_path
render({:partial => attempt_file_path}.merge(options), &block)
end
There's already something built into rails that facilitates this type of "theming" for you. It's called prepend_view_path.
http://api.rubyonrails.org/classes/ActionView/ViewPaths/ClassMethods.html#method-i-prepend_view_path
There's also append_view_path for adding paths to the end of the lookup stack.
I have this successfully working in production:
class ApplicationController < ActionController::Base
before_filter :prepend_view_paths
def prepend_view_paths
prepend_view_path "app/views/#{current_app_code}"
end
end
Now every controller will first look in "views/app1" (or whatever your dynamic name turns out to be) for the views corresponding to the action being called.
It's also smart enough to check all the defined paths for the file you're looking for, so it rolls back to the default location if one isn't found.

ruby on rails and XML

I am trying to create a ruby on rails app to capture data from form and create a corresponding XML.I have created a dummy model class which is not extending active record
Do i have to do that .Below is the code and the error i m facing plz help
class RamOne
attr_accessor :name,:city
end
Controller
def start
#ramone = RamOne.new
end
def load_new
#ramone = RamOne.new(params[:ramone])
if #ramone.save
redirect_to :action => ‘gen_xml’
end
end
def gen_xml
#xml = Builder::XmlMarkup.new
#ramones = RamOne.find(:all)
render :layout => false
end
View captures name,city and has a submit action attached with load_new
error : wrong num of args(1 for 0 ) in load_new
what is wrong?
You can't call RamOne.new with an argument because your RamOne class does not override the initialize method. Also, #ramone.save and RamOne.find are all ActiveRecord methods, so I think you need to extend ActiveRecord::Base in your RamOne class.
Check out the Hpricot gem http://hpricot.com/ if you are doing some heavy duty XML.
Check out REST to clean up your controller. http://guides.rubyonrails.org/routing.html#restful-routing-the-rails-default
Can i get rid of the model class
and store my captured data in a normal ruby class and fetch from it to create the xml .Are there any helper methods available
similar to form_for() helper
<% form_for :ramone, #ramone, :url => { :action => "load_new" }, :html => { :method => :get } do |f| %>
can i find any other non ActiveRecordHelper methods
I dont want the Model class unnecesarily.

Resources