Following this How-to:
https://github.com/carrierwaveuploader/carrierwave/wiki/How-to:-Add-more-files-and-remove-single-file-when-using-default-multiple-file-uploads-feature
class ImagesController < ApplicationController
before_action :set_gallery
def create
add_more_images(images_params[:images])
flash[:error] = "Failed uploading images" unless #gallery.save
redirect_to :back
end
def destroy
remove_image_at_index(params[:id].to_i)
flash[:error] = "Failed deleting image" unless #gallery.save
redirect_to :back
end
private
def set_gallery
#gallery = Gallery.find(params[:gallery_id])
end
def add_more_images(new_images)
images = #gallery.images
images += new_images
#gallery.images = images
end
def remove_image_at_index(index)
remain_images = #gallery.images # copy the array
deleted_image = remain_images.delete_at(index) # delete the target image
deleted_image.try(:remove!) # delete image from S3
#gallery.images = remain_images # re-assign back
end
def images_params
params.require(:gallery).permit({images: []}) # allow nested params as array
end
end
I seem to not be able to correctly remove the very last file. In my printed file list it keeps on standing there. Oddly enough with 0kb.
Then when I load up new files this one does go away.
I had the same problem and I found that you have to call 'remove_images!' if this was the last one. In 'remove_image_at_index' function add:
#gallery.remove_images! if remain_images.empty?
Regards
Related
In ruby I have created a class and array, to read the contents from a text file then output them.
class Album
attr_accessor :artist, :title, :genre, :tracks
end
album = Album.new(album_title, album_artist, album_genre, tracks)
-> tracks is an array of multiple lines read from the text file using a while loop. Context below, a_file/music_file File.new("album.txt", "r")
class Track
attr_accessor :name, :location
def read_track(a_file)
track_title = a_file.gets()
track_location = a_file.gets()
track = Track.new(track_title, track_location)
end
def read_tracks(music_file)
tracks = Array.new()
count = music_file.gets().to_i()
track = music_file
index = 0
while (index < count)
track = read_track(music_file)
tracks << track
index += 1
end
return tracks
end
end
after album = Album.new(album_title, album_artist, album_genre, tracks), I passed the album to a different procedure print_tracks(album), and in print_tracks(album), I have puts album.tracks.
But instead of printing out several lines of track names and track locations, I get something that looks like this:
#<Track:0x000055c028027b08>
#<Track:0x000055c0280277c0>
#<Track:0x000055c028027630>
How do I print out the actual words on the file?
What you are getting in return are instances of your Track class. Each of those instances has access to attributes like name and location as specified under the class definition in attr_accessor. You can change your last statement (return tracks) (take note that return here is not needed since its the last statement in the method, the last thing will be returned by default in ruby).
Try this instead of return tracks
tracks.map{ |track| {track_name: track.name, track_location: track.location} }
This was you will end up with array of hashes with keys of track_name and track_location each containing a value of one track. I am not sure what kind of format you want to return, but this is a rather simple, yet flexible. The most simplistic way would be array of array, which you can get using:
racks.map{ |track| [track.name, track.location] }
You're observing the default behavior defined in Object#to_s and Object#inspect.
Ruby uses the to_s method to convert objects to strings and the inspect method to obtain string representations of objects suitable for debugging. By default, to_s and inspect are more or less the same thing. The only difference is inspect will also show the instance variables.
You can and should override these methods in your Track class. For example:
class Track
def to_s
"#{self.class.name} #{name} # {location}"
end
def inspect
"#<#{to_s}>"
end
end
track.to_s
puts track
# Track: name # /music/name.flac
track.inspect
p track
# #<Track: name # /music/name.flac>
I'm new with Python but i'm a Powershell user so maybe what i'm trying to do is not possible the same way in Python
In Python 3 to learn i'm trying to make a list of the files in a directory and store it into a indexstore variable.
To do that this is what i done :
i created 2 objects Index and Indexstore
class Index(object):
def __init__(self, filepath, size):
self.filepath = filepath
self.size = size
and
class IndexStore(object):
def __init__(self, filepath, size):
self.filepath = filepath
self.size = size
after that i get my filelist from a location on my HDD
listOfFile = os.listdir(SourcePath)
With with list i'm starting a loop where i get the fullpath and the size of the file ( Like ForEach ) in 2 variables fullPath and fileSize
fullPath = os.path.join(SourcePath, entry)
fileSize: int = os.path.getsize(fullPath)
With the values i set the Index Object
setattr(Index, 'filepath', fullPath)
setattr(Index, 'size', fileSize)
And it's working with
pprint(vars(Index))
i have the result
mappingproxy({'dict': <attribute 'dict' of 'Index' objects>,
'doc': None,
'init': <function Index.init at 0x00000271B9C7E940>,
'module': 'main',
'repr': <property object at 0x00000271B9F30590>,
'weakref': <attribute 'weakref' of 'Index' objects>,
'filepath': 'D:\AmigaForever\AmigaOS3.9.ISO',
'size': 28862259})
After that is my problem ! In Powershell if i want to add a object2 to my objectlist1 i just do Objectlist1 += object2 and the work is done but in Python 3.x i tried many things on forums without success best way seems to be :
IndexStore = []
IndexStore.append(Index(fullPath, fileSize))
But the variable Indexstore stay Empty and if i try to print it
print(IndexStore)
pprint(vars(IndexStore))
the run console say :
print(IndexStore)
TypeError: 'tuple' object is not callable
Can you help me please ? Do i'm checking the value of my Indexstore well ?
Or my error is how i'm appending the values ?
I want in a second loop use again the values of the Object array to continue my code.
With the goal of 'Using Python 3 to make a list of the files in a directory and store it into a indexstore variable'.
The first problem I see is that you create a class Indexstore but later completely obviate the class when you assign the variable Indexstore = [].
so given you have a valid list of files from:
listOfFile = os.listdir(SourcePath)
This is an approach that will work:
First build an IndexItem class:
class IndexItem:
def __init__(self, filepath, size):
self.filepath = filepath
self.size = size
def __repr__(self):
# Returns a string representation of the IindexItem
return f"({self.filepath}, {self.size})"
This class has an intialization method which serves to preserve the instantiation values passed during initialization and a repr method which is used to convert the index values into readable text.
Next we create the IndexStore Class as follows:
class IndexStore:
def __init__(self):
self._index = []
def append(self, o: object):
# Append an entry onto the index
self._index.append(o)
def __repr__(self):
# Returns a string representation of self._index
return ', '.join(list(str(x) for x in self._index))
This class includes an instantiation which creates a list to hold the indexItems passed to it, and append method to add IndexItems to the IndexStore and finally a repr to create a readable string of the values.
Finally, we implement the basic functionality required to build the IndexStore as follows:
listOfFile = os.listdir(sourcePath)
index = IndexStore()
for f in listOfFile[:5]:
# For each entry f in listOfFile
fullpath = os.path.join(sourcePath, f)
# add an instantiation of IndexItem to IndexStore
index.append(IndexItem(fullpath, int(os.path.getsize(fullpath))))
print(index)
A simpler and more direct approach to this problem makes use of inherent Python bult-in data structures and capabilities is as follows:
IndexStore = []
listOfFile = os.listdir(sourcePath)
for f in listOfFile[:5]:
# For each entry f in listOfFile
fullpath = os.path.join(sourcePath, f)
# add an instantiation of IndexItem to IndexStore
IndexStore.append((fullpath, int(os.path.getsize(fullpath)))
print(IndexStore)
In this approach, the class definitions are eliminated, and the IndexStore contains a list of tuples with each tuple containing the fullpath to the file and it's size
I'm trying to make my result something like:
proxies_dict = {
'http':'http://178.141.249.246:8081',
'http':'http://103.12.198.54:8080',
'http':'http://23.97.173.57:80',
}
I have tried doing
proxies_dict = {}
with open('proxies.txt', 'r') as proxy_file:
for proxy in proxy_file:
proxies_dict['http'] = 'http://' + proxy.rstrip()
print(proxies_dict)
But this will only add the last line of proxy, not the whole thing. How can I make it add every proxy in a my .txt file?
Something like this could get ya going!
proxy text file looks like this:
178.141.249.246:8081
103.12.198.54:8080
23.97.173.57:80
proxies_list = []
with open('proxies.txt', 'r+') as proxy_file:
# read txt file
proxies = proxy_file.readlines()
for proxy in proxies:
# initialize dict in loop
proxies_dict = {}
# add proxy to dict
proxies_dict['http'] = 'http://' + proxy.rstrip()
# append dict to list
proxies_list.append(proxies_dict)
print(proxies_dict)
[{'http': 'http://178.141.249.246:8081'},
{'http': 'http://103.12.198.54:8080'},
{'http': 'http://23.97.173.57:80'}]
Basically you have to read the file first and then when you add the item to the dictionary you append it to the list which will hold each of your proxies. I did it this way so you could keep the 'http' key for each of your proxies.
EDIT
If you need them all in one dictionary it would look something link this, per David's answer:
with open(file, 'r+') as f:
# read file
content = f.readlines()
# this is an extra step for if you want to
# strip the newlines from each item, else
# links = content
# will work as well
links = [row.strip() for row in content]
# initialize dict
tmp = {}
# create http key and and links list
tmp['http'] = links
# print result
print(tmp)
{'http': ['178.141.249.246:8081', '103.12.198.54:8080', '23.97.173.57:80']}
I have a little GUI Program that should only get some inputs to use these inputs for a method call.
Therefore I have several tk.Entry objects. Now my method that I want to execute needs a file from my hard disk. I want to scrape it with ElementTree. (I think the file needs to be in the same directory as my .py file? If not please tell me how to use a file from another path). My Idea was to copy that file into the current filepath and then only use a simple call to get access to this file.
But when I want to copy this file it is getting copied after I close the program and that should not happen. It should instantly copy the file so I can work with it.
Is there a way to refresh my files or do you have another idea?
Thank you and here is my code:
from Modules import copy_file
import tkinter as tk
class MainApplication(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
for Frame in (StartPage, SuccessPage):
page_name = Frame.__name__
frame = Frame(parent=container, controller=self)
self.frames[page_name] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame("StartPage")
# method to show frames
def show_frame(self, page_name):
frame = self.frames[page_name] #getting our frame from our frames list
frame.tkraise() #raise it up to the front
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
# Open File Button
self.button_open_file = ttk.Button(self, text = "Open File", command = self.get_file_directory).grid(row=5, column=0, sticky="WE")
def get_file_directory(self):
filename = filedialog.askopenfilename(initialdir = "/",title = "Select file",filetypes = (("all files","*.*"),("jpeg files","*.jpg")))
copy_file(filename)
class SuccessPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
# Open File Button
self.label = tk.Label(self, text = "Lab").grid(row=0 column=0, sticky="WE")
if __name__ == '__main__':
application = MainApplication().mainloop()
----------------------------------------------------------------------------------------------
Modules.py
from shutil import copy
def copy_file(src):
destination_path = os.path.dirname(os.path.realpath(__file__))
copy(src, destination_path)
I am pretty new to programming and need some help/feedback on my code.
My goal is to scrape my data, which is working fine, and then display that data to my user in a numbered list. I am simply having difficulty displaying this data. I do not get any errors back my program simply skips my method altogether. Thanks in advance for any help/feedback!
class BestPlaces::Places
attr_accessor :name, :population, :places
##places = []
def self.list_places
# puts "this is inside list places"
self.scrape_places
end
def self.scrape_places
doc = Nokogiri::HTML(open("https://nomadlist.com/best-cities-to-live"))
places = doc.search("div.text h2.itemName").text
rank = doc.search("div.rank").text
places.collect{|e| e.text.strip}
puts "you are now in title"
##places << self.scrape_places
puts "#{rank}. #{places}"
end
end
end
CLI Page:
class BestPlaces::CLI
def list_places
puts "Welcome to the best places on Earth!"
puts #places = BestPlaces::Places.list_places
end
def call
list_places
menu
goodbye
end
end
There are a few things that could be addressed in this code, but let's first see a reworking:
require 'nokogiri'
require 'open-uri'
module BestPlaces
class Places
attr_accessor :name, :population, :places
def initialize
#places = []
end
def scrape_places
doc = Nokogiri::HTML(open("https://nomadlist.com/best-cities-to-live"))
places = doc.search("div.text h2.itemName")
ranks = doc.search("div.rank")
places.each{|e| #places << e.text.strip}
puts "you are now in title"
#places.each do |place|
i = #places.index(place)
puts "#{ranks[i].text}. #{place}"
end
end
end
class CLI
def list_places
puts "Welcome to the best places on Earth!"
BestPlaces::Places.scrape_places
end
def call
list_places
menu
goodbye
end
end
end
You have what looks to be an incomplete Module/Class setup. One can call the above like so:
bp = BestPlaces::Places.new
bp.scrape_places
The ##places variable was unnecessary, we can use #places instead to hold values that need to be accessed within the Places class. Also, nokogiri returns a string object when using the .text method on search results, which means you cannot iterate over them like an array. I hope this helps.