Locale does not switch while iterating in Rails - ruby-on-rails-3

I have extended RefineryCMS blog/admin/posts controller with Export action, which export post to xml and save it to file. I need export all translated versions of post. When I click export it saves all files, but all files have same locale.
Is it anything wrong with my code:
def generate_xml_by_locales
translated_locales.each do |l|
::I18n.locale = l
file = File.new("blog_#{l}.xml", "wb")
xml = Builder::XmlMarkup.new :target => file
xml.instruct!
xml.blog do
xml.title post.title
xml.description "Sixteenth installment of development diary"
xml.language l.to_s
xml.author "Dan"
xml.date post.created_at
xml.category "diary"
xml.text post.body
end
file.close
end
end
Thanks for help.

I did one modification, which work just fine. Instead of changing locale via I18n.locale I use translations.where(locale: lang).first . Don't know if it is the best solution, but it just works.
Refactored code:
def generate_xml_by_locales
translated_locales.each do |lang|
generate_xml(translations.where(locale: lang).first, lang)
end
end
def generate_xml post, lang
file = File.new("blog_#{lang}.xml", "wb")
xml = Builder::XmlMarkup.new :target => file
xml.instruct!
xml.blog do
xml.title post.title
xml.description "Sixteenth installment of development diary"
xml.language lang.to_s
xml.author "Dan"
xml.date post.created_at
xml.category "diary"
xml.text post.body
end
file.close
end

Related

including rails object in meta tags keywords

I'd like to include a rails object in my keywords as well as straight text but the code is clearly not the right way to do it...how can I do this?
set_meta_tags :keywords => %w[keyword1 keyword2 #{params[:hospital]}]
You might want to have a look at two plug-ins for including rails object in meta tags:
Meta Magic: https://github.com/lassebunk/metamagic
Head Liner: https://github.com/mokolabs/headliner
Edit: For Meta tag gem
What I usually do is write a meta helper that I simply stick in my ApplicationHelper, that looks like this:
def meta(field = nil, list = [])
field = field.to_s
#meta ||= {
'robots' => ['all'],
'copyright' => ['My Copyright'],
'content-language' => ['en'],
'title' => [],
'keywords' => []
}
if field.present?
#meta[field] ||= []
case list.class
when Array then
#meta[field] += list
when String then
#meta[field] += [list]
else
#meta[field] += [list]
end
case field
when 'description' then
content = truncate(strip_tags(h(#meta[field].join(', '))), :length => 255)
else
content = #meta[field].join(', ')
end
return raw(%(<meta #{att}="#{h(field)}" content="#{h(content)}"/>))
else
tags = ''
#meta.each do |field, list|
tags += meta(field)+"\n"
end
return tags.rstrip
end
end
You can simply set meta tags in your views, by adding a call to meta() in it. So in an articles/show.html.erb you might add this to the top of your view:
<% meta(:title, #article.title) %>
And in your layouts, you add it without any parameters, so it'll spit out the meta tags.
<%= meta %>
Or have it output an individual tag:
<%= meta(:title) %>
I bet you there's more elegant solutions, though.
But if you were looking for something already implemented in Rails you're out of luck.
Thanks.
Try this in your view as it worked for me (using meta-tags gem):
<% keywords [[#modelname.keyword1], [#modelname.keyword2]] %>
and you cad additional keywords in text format by adding them within the ruby in the following format ['keyword3']

What is the correct way to render_to_string in wicked pdf?

This is what the documentation of wicked pdf specifies:
WickedPdf.new.pdf_from_string(
render_to_string(:pdf => "pdf_file.pdf", :template => 'templates/pdf.html.erb', :layout => 'pdfs/layout_pdf'),
:footer => {:content => render_to_string({:template => 'templates/pdf_footer.html.erb', :layout => 'pdfs/layout_pdf'})}
)
What i get is ActionView::MissingTemplate
Even though i have pdf.html.erb in directory. I use a gen_pdf method in the application controller and an equivalent pdf.html.erb in the views/application folder. What am i missing.
Don't Use template.
I ran into the same problem as you. You have to render your PDF quite differently when you're doing it in a Controller action as opposed to a Mailer or something else.
First off, using template won't work. There's some other nuances but here is my implementation you can build off of:
notification_mailer.rb
def export
header_html = render_to_string( partial: 'exports/header.pdf.erb',
locals: { report_title: 'Emissions Export' } )
body_html = render_to_string( partial: "exports/show.pdf.erb" )
footer_html = render_to_string( partial: 'exports/footer.pdf.erb' )
#pdf = WickedPdf.new.pdf_from_string( body_html,
orientation: 'Landscape',
margin: { bottom: 20, top: 30 },
header: { content: header_html },
footer: { content: footer_html } )
# Attach to email as attachment.
attachments["Export.pdf"] = #pdf
# Send email. Attachment assigned above will automatically be included.
mail( { subject: 'Export PDF', to: 'elon#musk.com' } )
end
If you are using wicked_pdf and try to generate pdf outside of controller (i.e. in a cron job) you can do it this way (raild 4.1 +):
# app/renderers/pdf_renderer.rb
class PdfRenderer < ActionController::Metal
include ActionView::ViewPaths
include AbstractController::Rendering
include AbstractController::Helpers
include ActionController::Helpers
include ActionView::Rendering
include ActionView::Layouts
include ActionController::Rendering
include ActionController::Renderers
include ActionController::Renderers::All
append_view_path "app/views"
View = Struct.new(:layout, :template, :locals)
def render_pdf(view)
wicked = WickedPdf.new
pdf_string = render_to_string(template: view.template, layout: view.layout, locals: view.locals)
# Make a PDF in memory
pdf_file = wicked.pdf_from_string(pdf_string, pdf: "pdf_name",
page_size: 'A4',
wkhtmltopdf: ENV['WKHTMLTOPDF_EXECUTABLE_PATH'],
margin: { top: '0.5in', bottom: '1in', left: '0.5in', right: '0.5in'}
)
# Write it to tempfile
tempfile = Tempfile.new(['document', '.pdf'], Rails.root.join('tmp'))
tempfile.binmode
tempfile.write pdf_file
tempfile.close
tempfile
end
end
and call this method:
renderer = PdfRenderer.new
pdf_view = PdfRenderer::View.new.tap do |v|
v.template = "postal/#{template_file}.pdf.erb"
v.layout = 'layouts/layout.pdf.erb'
v.locals = {:user=> #user, :other_stuff => #details}
end
temp_pdf = renderer.render_pdf pdf_view
now you can use temp_pdf.path to do whatever you want with this file (i.e. send email)
you can read more about this way here: http://blog.arkency.com/2014/03/pdf-in-rails-without-controllers/
You can have something like this inside your mailer:
class ReportMailer < ActionMailer::Base
default :from => DEFAULT_FROM
def report_pdf(user, bookings)
#bookings = booking
#user = user
mail(:subject => 'Overtime', :to => user.email) do |format|
format.text # renders overtime_pdf.text.erb for body of email
format.pdf do
attachments['monthly_report.pdf'] = WickedPdf.new.pdf_from_string(
render_to_string(:pdf => 'monthly_report', :template =>
'hospital_bookings/index.pdf.erb', :layouts => 'pdf.html')
)
end
end
end
end
Hope this helps. Also if you want further help it would be ideal to post some of your code so that others can gain better understanding on what you have done and what your trying to achieve.
In case this helps someone else out: I had to generate a pdf via wicked_pdf from a job. This strategy worked for me from within the perform(*args) action of the job. WickedPDF appears to be intended to work from a controller context, so we just harness the power of controllers via ApplicationController.render:
generatedPdf = WickedPdf.new.pdf_from_string(
ApplicationController.render(
template: "path/to/your/view/template.pdf.erb",
layout: "layouts/your_wicked_pdf_layout.html.erb",
locals: {some_var: #first_var, some_other_var: #second_var}
)
)
save_path = Rails.root.join('public','your_saved_file.pdf')
File.open(save_path, 'wb') do |file|
file << generatedPdf
end

feed single .jpg file true carrierwave?

Would it be possible to feed a single.jpg true carrierwave?
Using jpegcam Im generating a temp.jpg and would like to feed this in carrierwave
so it gets stored in the photos table and generate the thumbnails based on the /uploaders/photo_uploader.rb
Any way to feed a single jpg to carrierwave?
def upload
File.open(upload_path, 'w:ASCII-8BIT') do |f|
f.write request.raw_post
end
render :text => "ok"
end
private
def upload_path # is used in upload and create
file_name = ("webcam_1.jpg")
File.join(::Rails.root.to_s, 'public', 'uploads', file_name)
Photo.create(:file => File.open("#{Rails.root}/public/uploads/#{file_name}"))
end
If I understand your question correctly, you just want to create a Photo from a file? Assuming your Photo class has an 'image' field that Carrierwave is using, that would be this:
Photo.create(:image => File.open("#{Rails.root}/public/uploads/#{file_name}"))

Rails 3/3.1 and I18n: Validation hits when switching between languages

The database is seeded with values in english language and format, e.g., :hourlyrate => 20.90. On first start (language is english by default), the input form displays the content of the field correctly. I can modify and save, no problem.
If I switch to german, the number is displayed correctly as 20,90. If I edit anything on this form, I can not save again, as the validation catches the number as not being valid.
My question is, do I have to perform corrections in my controller before saving, or did I miss some built-in function of Rails?
Relevant parts of the code
Helper:
def my_number_with_precision(value)
if value
# value
number_with_precision(value, :precision => 2)
end
end
Validation:
validates :hourlyrate, :numericality => { :greater_or_equal_than => 0, :message => " is an invalid number or below zero" }
Form:
<div class="input">
<%= f.text_field :hourlyrate, :value => my_number_with_precision(f.object.hourlyrate) %>
</div>
Gemfile
gem 'rails-i18n'
I came up with one of the following solutions - language specific code:
def parse_i18n(value)
if I18n.locale = 'de'
value.gsub(',', '.')
else
value
end
end
def parse_i18n(value)
value.gsub(I18n.t("number.currency.format.unit"),'').
gsub(I18n.t("number.currency.format.delimiter"), '').
gsub(I18n.t("number.currency.format.separator"), '.')
end

Rails3: Prefix to all url_for URLS

I add i18n to my webpage (different content for different languages). My URLs look loke this:
http://host.tld/de/news/15
http://host.tld/en/news/15
...
All my URLs in the application are set by the link_to/url_for method like this
url_for("/news/#{news.id}/#{urlify(news.title)}")
url_for("/news/#{#news.section}")
...
My routing looks like this:
scope "/:language/", :language => /de|en/ do
match "news/:news_id(/:title)" => "news#show_entry", :constraints => { :news_id => /[0-9]+/ }
...
end
I add this to my ApplicationController:
def default_url_options(options={})
{:language => I18n.locale}
end
Now I want to add the language prefix to ALL the URLs without change all the url_for()-calls. Is there a solution (parameter/config-option or something) to add this prefix? It should work with relative paths, too.
If you are looking not to change all the url for calls you could add a method in the application_helper.rb file to override the existing methods to add in the language
def url_for(options={})
if options[:language]
'/options[:language]' + super
else
super
end
end
def link_tolink_to(*args, &block)
options = args[1] || {}
if options[:language]
'/options[:language]' + super
else
super
end
end