Convert array of string to an array of images - ruby-on-rails

This is a follow on from my previous question here. What I want to do now is convert the column type for projects to hold an array of images.
I've built the ability for a user to upload an image to Rails but want them to be able to upload an array of images for a project; I'm not quite sure as to how to go about it.
I've thought about creating a migration that converts the column type of images from an array of strings to an array of images:
def up
change_column :projects, :images, ?
end
def down
change_column :projects, :images, ?
end
but I don't know how to use the image as a type.
An example of what returns from a GET for the images looks like this:
[
{
"id": 10,
"name": "doot.png",
"featured_image": {
"url": "http://localhost:3000/rails/active_storage/blobs/redirect/3joi32jo23nfkjsnjksefsdnansdf--daf5e3e6b3772510ada4077c2172b117e81f8f85/doot.png"
}
}
]
Pointing me in the right direction would be appreciated - thanks!

Related

How to update json column in Rails?

I have a json column in my Categories table and I want to update each category record with a translation from a json file. I have built the json file so that it contains a categories array and each category has a name and a translation, like so:
{
"categories": [
{
"name": "starter",
"message": "Abs/Анти блокираща система (система против боксуване)"
},
{
"name": "alternator",
"message": "Алтернатор"
}
...
]
}
I want every category record to be updated with the language key as well as the translation from the file, like so:
{ bg: 'translation from file' }
I have this code
file = File.read('app/services/translations/files/bg.json')
data = JSON.parse(file)
language = File.basename(file, '.json')
Translations::CategoriesMigrator.call(file: data, language: language)
module Translations
class CategoriesMigrator < Service
def initialize(category_repo: Category)
#category_repo = category_repo
end
def call(file:, language:)
file['categories'].each do |category|
found_category = #category_repo.find_by(name: category['name'])
found_category.translated_categories[language] = category['message']
found_category.save
end
end
end
end
Right now I end up having all categories in a single category record. What am I doing wrong?
Update
My db migration looks like this:
class AddTranslatedCategoriesToCategories < ActiveRecord::Migration[5.1]
def change
add_column :categories, :translated_categories, :jsonb, null: false, default: {}
add_index :categories, :translated_categories, using: :gin
end
end
JSON/JSONB is a good choice when you have data that does not fit in the relational model. In most other cases its an anti-pattern since it makes it much harder to query the data and provides no data integrity or normalization.
This case is definitely the later since the underlaying structure is not dynamic. To keep track of translations we just need to know the subject, the language and the translation.
class Category
has_many :category_translations
end
# rails g model category_translation category:belongs_to locale:string text:string
class CategoryTranslation
belongs_to :category
end
You can add a compound index on category_id and locale to enforce uniqueness.
See:
https://www.2ndquadrant.com/en/blog/postgresql-anti-patterns-unnecessary-jsonhstore-dynamic-columns/

How to store string as array in database column using Ruby on Rails

This question is asked many times on SO. The main problem is nothing got fits into my situation.
Case is, I am not able to store typed content as array in database column.
text_field whose code is:
= text_field_tag 'product[keywords][]', #product.keywords, class: 'tab-input
product_keywords'
In controller strong parameters are:
params.require(:product).permit(:id, :name, :keywords => [])
Jquery code that is not not removing value upon deletion when typed wrong value but it add commas after each element as I want to take commas seperated value in one column.
$(document).on 'keyup', '.product_keywords', ->
keyword = #value.replace(/(\w)[\s,]+(\w?)/g, '$1, $2')
if keyword != #value
#value = keyword
return
model code:
serialize :keywords, Array
migration code:
class AddKeywordsToProducts < ActiveRecord::Migration[5.1]
def change
add_column :products, :keywords, :text
end
end
So, if someone writes, abc and hit space a comma is added in the end. after three typed words it will look like:
abc, dbx, she
now I want to store it as array in column but its not storing properly.
it stores as:
["abc, dbx, she"]
Also please can anybody tell me the best cases to handle these cases?
Plus best practices to deal with such cases using ruby so I will learn it for future?
You probably want a custom serializer as shown here. So instead of:
serialize :keywords, Array
You might do somewhat like:
serialize :keywords, KeywordSerializer
And somewhere in helpers:
class KeywordSerializer
def self.dump(what)
what.join(", ")
end
def self.load(what)
what.split(/\s*,\s*/)
end
end
Passing array elements using single form tag is not possible to pass as a array and passing array as a string, you need to process it near white-listing your params,
permitted_params = params.require(:product).permit(:id, :name, :keywords => [])
permitted_params[:keywords] = permitted_params[:keywords][0].split(/\s*,\s*/)

Don't Duplicate Entries Rails

I'm currently calling this every 3hrs, but it's storing duplicates of the same data. I've tried a few methods here on Stackoverflow but none of them seem to be actually working.
def fetch_data
response = self.class.get("/tap-2_JD7rkZupwNmg91im5G/last_ready_run/data?format=json")
#elements = response.parsed_response["link"]
# To access the image src's:
image_srcs = #elements.collect { |e| e['image'] }
image_srcs.each do |image|
self.entries.create(image: image)
end
end
Is there a way to check against each 'image' string that it collects and make sure it's not a duplicate before it inserts a new entry into the database
Thanks
Edit - Example Response
{
"link": [
{
"link": "http://www.test.com",
"image": "http://www.test.com/500x500.jpg"
}, ....
Use Rails build-in validation: validate :image, :uniqueness. (http://guides.rubyonrails.org/active_record_validations.html#uniqueness)
Note: beware that it's not 100% protection from duplicates. For more robust solution please use DB level constraints (ex. add_index :entries, :image, unique: true in migrations)

Allow an array of hashes with a dynamic hash (hstore) inside

I'm stuck with strong_parameters and this array of hashes with a dynamic hash (hstore) inside.
The structure is the following:
{ contact_sources: [
{ id: 1, filled_fields: { randomstuff: 'randomdata', dunno: 123 } },
{ id: 2, filled_fields: { blah: 'blabla', dunno: 9043 } }
] }
So, my main attempt is the following:
params.permit(contact_sources: [{:filled_fields => []}, 'id'])
Which doesn't return filled_fields. Any suggestion on how to deal with it?
Update 1:
I have the following model:
class ContactSource < ActiveRecord::Base
# Fields: id:integer, filled_fields:hstore
end
In my action, I'm submitting multiple records at once (mass update), so I have an array of contact_source, but actually they don't belong to anything, it's just a mass update.
Looks like it's not possible to do it with "plain" strong_parameters syntax. The only option you have is to actually, after filtering, re-add those values with a loop. I know it's terrible but it's the only way right now. I submitted a bug to Rails actually.

array of strings to array of objects

My model is giving me an array of strings as json, and I need an array of objects for my api to function correctly on the client side. In my model I define the json as
def as_json(options={})
super(:only => [:price, :available, :location_id, :beer_id], :methods => [:name, :brewery, :style, :label_url, :description, :id])
end
This is giving me a response
{"available":"on","beer_id":1,"created_at":"2013-05-31T16:45:09Z","description":"Good","id":1,"location_id":1,"price":"3.0","size":"16.0","updated_at":"2013-05-31T16:45:09Z"}
which is obviously missing the [ ] indicating it is an array of objects. Is there a simple way to convert this array of strings into an array of objects?
EDIT: My original response which was working fine was
[{"available":"on","beer_id":1,"created_at":"2013-05-31T16:45:09Z","description":"Good","id":1,"location_id":1,"price":"3.0","size":"16.0","updated_at":"2013-05-31T16:45:09Z"}]
My ios app is crashing because it doesn't think the current response is of type NSDictionary because it is NSString. After looking around it appears that some change I made to the rails app changed the json response. The only clue I have is the missing brackets when I look at what was working and what is now not working.
As far as I can see, your response is not an array of strings, it's just a single JSON object.
If you need to convert the object into 1-element array of objects, just enclose it into [ and ]. :)

Resources