Rails 3/3.1 and I18n: Validation hits when switching between languages - ruby-on-rails-3

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

Related

Why isn't my search method working in Ruby on Rails?

In my Ruby on Rails application, I have a cinema system and am trying to return the screen a showing is in when a user searches for the showing.
To display the search drop down I am using this code in my _application.html.erb:
<%= render( :partial => '/screen_lookup', :locals => {:showings => #showings = Showing.all, :my_path => '/screens/display_screens_by_showing' })%>
Which renders the search from the _screen_lookup.html.erb:
<%= form_tag my_path, :method=>'post', :multipart => true do %>
<%= select_tag ('showings_id'),
options_from_collection_for_select(#showings, :id, :showing_times, 0 ),
:prompt => "Showings" %>
<%= submit_tag 'Search' %>
<% end %>
And uses the display_screens_by_showing in the screens_controller:
def display_screens_by_showing
#screens = Screen.showing_search(params[:showing_id])
if #screens.empty?
# assign a warning message to the flash hash to be displayed in
# the div "feedback-top"
flash.now[:alert] = "There are no films of that genre."
# return all products, in alphabetical order
#screens = Screen.all
end
render :action => "index"
end
And this searches using the method in the screen.rb model:
def self.showing_search(showing_id)
screen = Showing.where("id = ?", showing_id).screen_id
self.where("id = ?", screen)
end
Now, the problem I am having is that because a showing belongs_to a screen, and a screen has_many showings, I need to be able to search for the showing, and store that showing's screen_id in a variable to search for the screen that showing is in with, which I have tried doing in the model:
screen = Showing.where("id = ?", showing_id).screen_id
self.where("id = ?", screen)
But the error I am getting is:
NoMethodError in ScreensController#display_screens_by_showing
undefined method `screen_id' for #<ActiveRecord::Relation []>
These are the model relationships:
showing.rb:
class Showing < ActiveRecord::Base
belongs_to :screen
end
screen.rb:
class Screen < ActiveRecord::Base
has_many :showings
end
What code will get my search working?
The problem is that where doesn't return a record, it returns a relation that can be enumerated or chained, instead you want to use find or find_by to return a single record, which is kind equivalent to where + first
screen = Showing.find(showing_id).screen_id
which is sort of like doing
screen = Showing.where(id: showing_id).first.screen_id
If you want to pass a hash you can use find_by which will be like this
screen = Showing.find_by(id: showing_id).screen_id
PS:
I'm not sure what you're doing exactly, but i think those two lines can be merged into a single query ( not sure what it should be returning, but I'm assuming a screen )
def self.showing_search(showing_id)
Showing.find(showing_id).screen
end

Rails. Validations for many locales at the same time

I have a bilingual web site with two locales: en and ru.
I want my site to have i18n. I use 'globalize3' and 'easy_globalize3_accessors' gems.
There are departments I can create and edit with standard forms.
Locales are given from URL: example.com/en/departments/ or example.com/ru/departments/
Now if I want to create a new department item, I would see such a thing:
A main form for current locale (I18n.locale).
A checkbox to add a translation on the same page.
If checkbox is active, show another form for another locale right next to the main form.
The most important thing — validations for each locale must be different. Say, for en it should pass ASCII symbols; for ru — Cyrillic ones.
My problem is number 4. I can't get my validations work with a checkbox.
The main problem is: checkbox active? If yes, show another form and run validations for it. If no, show nothing and don't run validations for that form, pass it empty.
For now, if I fill in two forms, everything works like a charm.
Ok. What I tried.
Model
class Department < ActiveRecord::Base
attr_accessible :name, :translations_attributes
translates :name, fallbacks_for_empty_translations: true
accepts_nested_attributes_for :translations
# The inline class Translation is a hack to solve
# "Can't mass-assign protected attributes: locale"
# See https://github.com/svenfuchs/globalize3/issues/128#issuecomment-11480650
class Translation
attr_accessible :locale, :name
validates :name, uniqueness: true
validates :name, format: {with: /\A[-а-яА-Я -]+\Z/}, if: ->(l) {l.locale.to_s == 'ru'}
validates :name, format: {with: /\A[-a-zA-Z -']+\Z/}, if: ->(l) {l.locale.to_s == 'en'}
end
end
Controller
def new
#department = Department.new
end
def create
#department = Department.new(params[:department])
#department.save ? (redirect_to action: :index) : (render :new)
end
View (new.haml.html) without checkbox
= form_for #department, url: {action: :create} do |f|
%h2
- f.globalize_fields_for_locale I18n.locale do |g|
= "Translation for"
= I18n.locale
= g.label t("department.form.new.label.name")
= g.text_field :name
%hr
%h2
- I18n.available_locales.each do |locale|
- next if locale == I18n.locale
%br
- f.globalize_fields_for_locale locale do |g|
= "Translation for"
= locale
= g.label t("department.form.new.label.name")
= g.text_field :name
= f.submit t("department.create.link"), class: "btn"
Help me understand what I have to do, please.

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']

datepicker jquery ui and rails 3(.1)

Hi i am using the date picker jquery ui in combination with rails 3.1. The date picker looks brilliant, only the date isn't stored in the database? Only sometimes...? So that's a difficult error.
This is my .js file:
$(function() {
$("#question_deadline").datepicker({ duration: 'fast', maxDate: '+2m', minDate: 'now', showOn: "button", buttonImage: "calendar.gif", buttonImageOnly: true });
$("#question_deadline").datepicker("option", "showAnim", "drop");
$("#question_deadline").datepicker("option", "dateFormat", "DD, d MM, yy");
});
In my controller there's just plain rails script:
def create
#question = Question.new(params[:question])
if #question.save
redirect_to questions_path, :notice => "Successfully created question."
else
setup_questions
render :index
end
end
In views file _form.html.erb i use a text_field to display the date:
<div class="field">
<%= f.label :content, "Question" %><br />
<%= f.text_field :content, :placeholder => "type your question here.." %>
<%= f.text_field :deadline %><br />
</div>
Are there people who have experience with datepiacker jquery ui and rails, the ryan bates episode, didn't solve it, i think that was written in rails 2.3?
Regards,
Thijs
First, you need to show us the view where you have the datepicker element. If it's like this:
<input type="text" name="question_deadline" id="question_deadline" />
When you submit this form, the parameters you receive in your controller (in the method "create") is called question_deadline. So in that create method you should first write:
if params[:question_deadline] != ""
params[:question][:question_deadline] = params[:question_deadline]
end
#add a else if this date field is compulsory in the database
This step is important because the create method will read stuff from params[:question][:question_deadline] not from params[:question_deadline] which is returned from the view.
Thus params[:question][:question_deadline] is empty when you do #question.save
To display the date, you also need to show us the controller "show" method that should be something like:
#question = Question.find(params[:id]) #or any sql request that returns info about a question.
Then in the view you can retrieve it simply with:
<%= #question.question_deadline%>
Maybe with more code from you controller and view I can elaborate on that.
I think, Rails/Ruby is not able to parse a date in this format:
$("#question_deadline").datepicker("option", "dateFormat", "DD, d MM, yy");
// full day name, day (w/o leading zero), full month name, 4-digit year
In your controller, you might want to add a line such as
def create/update
...
#question.deadline = DateTime.strptime(params[:question][:deadline], '%A, %d %B, %Y')
# assuming my jquery-to-ruby format-mapping is adequate ;-)
if #question.save
...
end
Beware, that this code easily breaks on malformed date strings.
If you don't want to change the format to, e.g. 'yy-mm-dd' (in Ruby-land it's '%Y-%m-%d'), you may want to populate the selected date to another HTML element using the altField option and hide the actual datepicker input field via CSS:
$("#somewhere_else").datepicker(
dateFormat: "%yy-%mm-%dd",
altField: "#question_deadline",
altFormat: "DD, d MM, yy",
...
);
<%= form_for #question do |f| %>
...
<%= text_field_tag 'somewhere_else', #question.deadline %>
<%= f.hidden_field :deadline %>
...
<% end %>
That'll work, at least for me :-)
—Dominik
The other option is to update the way ActiveSupport parses dates. This is outlined in Default Date Format in Rails (Need it to be ddmmyyyy)

Rails 3 custom validation: Highlighting offending fields

I'm writing my first custom rails validation, and would like to tag the offending class with an html "error" class if they return false - I can't quite figure out how to do it. Relevant validation code below - any help appreciated.
(If it makes a difference, I'm using jQuery)
validates_each :shop do |record, attr, value|
shopvar = record.shops.map{ |s| s.email.downcase.strip }
if shopvar.count != shopvar.uniq.count
record.errors.add(attr, 'has the same email address entered more than once')
#record.errors[attr] << "You have entered this shop in the form twice"
end
end
So in your form you'd have something like this for an input field
<%= form.text_field :title %>
Since errors is a hash you could use the "include?" method like so...
errors.include?(:title)
This tells you that there's something wrong with this field. Now all you need to do is style it.
Whack on a ternary operator asi...
<% css_class = errors.include?(:title) ? "highlight_error_class" : "no_problem_class" %>
<%= form.text_field :title, :class => css_class %>
Done.