Ruby: CSV to YAML - ruby-on-rails

I have the following csv example:
en.activerecord.models.admin_user.one;Guide
en.activerecord.models.admin_user.other;Guides
en.simple_captcha.placeholder;Type here
Is there a ruby gem or method to turn it into a Yaml file:
en:
activerecord:
models:
admin_user:
one: Guide
other: Guides
simple_captcha:
placeholder: Type here
I'm still trying (using tree data model) but no results.
Any idea?

require 'yaml'
hash = {}
file = "en.activerecord.models.admin_user.one;Guide
en.activerecord.models.admin_user.other;Guides
en.simple_captcha.placeholder;Type here"
file.split("\n").each { |line| hash.deep_merge!(line.split(/\.|;/).reverse.inject() { |m,v| {v => m} }) }
puts YAML.dump(hash)
---
en:
activerecord:
models:
admin_user:
one: Guide
other: Guides
simple_captcha:
placeholder: Type here

Related

Ruby on Rails i18n activerecord custom messages

I have a ruby on rails application. I have spanish and english support in my application. However, I get a translation missing exception in case spanish mode.
I have the following model:
class Company < ApplicationRecord
validates :name, length: { in: 5..15, message: :bad_name }
end
en.yml
en:
activerecord:
errors:
models:
company:
attributes:
name:
bad_name: 'message in english'
sp.yml
sp:
activerecord:
errors:
models:
company:
attributes:
name:
bad_name: 'message in spanish'
Just in case the error when I open the application in english. I get the "message in english" message and that's ok.
On the other hand, when I open and test it in spanish, I get the following error.
ActiveRecord::RecordInvalid:
translation missing: sp.activerecord.errors.messages.record_invalid
I can't see what I'm missing,
Any suggestions,
Thanks.
Are other translations work in this file?
Try to rename sp.yml to es.yml, because this is the iso-code for "espanol".
Also try to include a message for activerecord.errors.messages.record_invalid in your spansih file. will this be displayed?
Actually, to use Spanish within your locale you would need to set I18n.locale = :es. I think you mixed up your locales. The correct language file should be named es.yml and look like:
es:
activerecord:
errors:
models:
company:
attributes:
name:
bad_name: 'message in spanish'

How to load yaml with ruby 2.1

I have a the following data in tmp.yml. My goal is to load the data to mysql database.
I have the following code to load the data from tmp.yml:
$LOAD_PATH.unshift( File.join( File.dirname(__FILE__), 'lib' ) )
require 'yaml'
require 'AacflmDirection' # Just an empty class
SITE_PATH = '/var/www/test/testme/asian_cinema/tmp.yml'
doc = YAML::load( File.open( SITE_PATH ) )
puts doc[0]['attributes']['position'] # Expect position = 1
And I got this error. It seems I cannot access it via hash.
load.rb:8:in `<main>': undefined method `[]' for #<AacflmDirection:0x000000023c9fe0> (NoMethodError)
tmp.yml
--- !ruby/object:AacflmDirection
attributes:
position: "1"
film_id: "1"
created_on: 2012-02-06 09:31:31
page_id: "2671"
director_id: "1"
id: "1"
site_id: "173"
director:
film:
page:
site:
--- !ruby/object:AacflmDirector
assets:
attributes:
slug: paul-cox
name: Paul Cox
bio_markup: ""
created_on: 2012-02-06 09:31:39
page_id: "2671"
id: "51"
bio:
site_id: "173"
directions:
draft:
films:
page:
pathprints:
settings_objects:
site:
You're unserializing objects, not hashes. doc[0] is an instance of AacflmDirection. You need to access them with whatever accessors they provide.
Try doc[0].position.
First, three hyphens --- separate multiple documents in yaml. Then the !ruby/object... followed will deserialize your file to an object, not hash.
In your original code, you only get the AacflmDirection object as your doc variable. Use YAML::load_stream to load all the objects in your yaml.
require 'AacflmDirector'
require 'AacflmDirection'
doc = YAML::load_stream( File.open( SITE_PATH ) )
By that you'll get:
=> [#<AacflmDirection:0x007fa62c1c3a48
#attributes=
{"position"=>"1",
"film_id"=>"1",
"created_on"=>2012-02-06 17:31:31 +0800
"page_id"=>"2671",
"director_id"=>"1",
"id"=>"1",
"site_id"=>"173"},
#director=nil,
#film=nil,
#page=nil,
#site=nil>,
#<AacflmDirector:0x007fa62c1bbe10
#assets=nil,
#attributes=
{"slug"=>"paul-cox",
"name"=>"Paul Cox",
"bio_markup"=>"",
"created_on"=>2012-02-06 17:31:39 +0800,
"page_id"=>"2671",
"id"=>"51",
"bio"=>nil,
"site_id"=>"173"},
#directions=nil,
#draft=nil,
#films=nil,
#page=nil,
#pathprints=nil,
#settings_objects=nil,
#site=nil>]
Then add attr_accessor :attributes in your AacflmDirection class defination. So you can get the value by:
doc[0].attributes["position"]
Use YAML::load_file(SITE_PATH) to read the file and convert it to a Ruby object.

How do I recursively flatten a YAML file into a JSON object where keys are dot separated strings?

For example if I have YAML file with
en:
questions:
new: 'New Question'
other:
recent: 'Recent'
old: 'Old'
This would end up as a json object like
{
'questions.new': 'New Question',
'questions.other.recent': 'Recent',
'questions.other.old': 'Old'
}
Since the question is about using YAML files for i18n on a Rails app, it's worth noting that the i18n gem provides a helper module I18n::Backend::Flatten that flattens translations exactly like this:
test.rb:
require 'yaml'
require 'json'
require 'i18n'
yaml = YAML.load <<YML
en:
questions:
new: 'New Question'
other:
recent: 'Recent'
old: 'Old'
YML
include I18n::Backend::Flatten
puts JSON.pretty_generate flatten_translations(nil, yaml, nil, false)
Output:
$ ruby test.rb
{
"en.questions.new": "New Question",
"en.questions.other.recent": "Recent",
"en.questions.other.old": "Old"
}
require 'yaml'
yml = %Q{
en:
questions:
new: 'New Question'
other:
recent: 'Recent'
old: 'Old'
}
yml = YAML.load(yml)
translations = {}
def process_hash(translations, current_key, hash)
hash.each do |new_key, value|
combined_key = [current_key, new_key].delete_if { |k| k.blank? }.join('.')
if value.is_a?(Hash)
process_hash(translations, combined_key, value)
else
translations[combined_key] = value
end
end
end
process_hash(translations, '', yml['en'])
p translations
#Ryan's recursive answer is the way to go, I just made it a little more Rubyish:
yml = YAML.load(yml)['en']
def flatten_hash(my_hash, parent=[])
my_hash.flat_map do |key, value|
case value
when Hash then flatten_hash( value, parent+[key] )
else [(parent+[key]).join('.'), value]
end
end
end
p flatten_hash(yml) #=> ["questions.new", "New Question", "questions.other.recent", "Recent", "questions.other.old", "Old"]
p Hash[*flatten_hash(yml)] #=> {"questions.new"=>"New Question", "questions.other.recent"=>"Recent", "questions.other.old"=>"Old"}
Then to get it into json format you just need to require 'json' and call the to_json method on the hash.

Attribute translation in Rails

So the issue I've encountered days ago still makes me unconfortable with my code. I can't get proper translation for my application: Yml looks like that:
pl:
errors: &errors
format: ! '%{attribute} %{message}'
messages:
confirmation: nie zgadza się z potwierdzeniem
activemodel:
errors:
<<: *errors
activerecord:
errors:
<<: *errors
And model looks like that:
module Account
class User < ActiveRecord::Base
attr_accessor: password_confirmation
end
end
And flash in controller declared:
flash[:errors] = #user.errors.full_messages
I tried and read activerecord documentation and stack previous questions (How to use Rails I18n.t to translate an ActiveRecord attribute?, Translated attributes in Rails error messages (Rails 2.3.2, I18N)). Yet it still doesn't work as I wanted.
password_confirmation remains "Password Confirmation", and not "Potwierdzenie hasła" as it shoul be. The screenshot might explain it better: http://i42.tinypic.com/1glz5.png
Your User model is in a namespace, thus you have to declare the namespace in your translation file also. Try the following to get the correct translation for password_confirmation:
pl:
activerecord:
attributes:
account/user:
password_confirmation: "Potwierdzenie hasła"

What does the percent sign mean in Yaml?

I noticed that in the i18n rails guide, they have the following code:
en:
activerecord:
errors:
template:
header:
one: "1 error prohibited this %{model} from being saved"
other: "%{count} errors prohibited this %{model} from being saved"
body: "There were problems with the following fields:"
What do the %{...} mean? How is this different from #{...}?
If you read the guide a little more, you'll come across the Passing variables to translations section:
You can use variables in the translation messages and pass their values from the view.
# app/views/home/index.html.erb
<%=t 'greet_username', :user => "Bill", :message => "Goodbye" %>
# config/locales/en.yml
en:
greet_username: "%{message}, %{user}!"
and the Interpolation section:
In many cases you want to abstract your translations so that variables can be interpolated into the translation. For this reason the I18n API provides an interpolation feature.
All options besides :default and :scope that are passed to #translate will be interpolated to the translation:
I18n.backend.store_translations :en, :thanks => 'Thanks %{name}!'
I18n.translate :thanks, :name => 'Jeremy'
# => 'Thanks Jeremy!'
So the %{...} stuff doesn't have anything to do with YAML, that's I18n's way of handling variable interpolation in the messages.

Resources