diff --git a/CHANGELOG b/CHANGELOG
index 577201a9c..3c9f74a37 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -16,7 +16,9 @@
* Changed date/time inputs to default to nil instead of Time.now when the object has no value (due to deprecation warning, #240)
* Changed the behaviour of associations with a :class_name option to be more consistent with what Rails expects
* Fixed issues with Ruby 1.9.1 and Haml
+* Fixed inputs_for_nested_attributes only appending to the output buffer
* Add the :disabled option to check_boxes input
+* Changed I18n handling in spec tests to use I18n.backend.reload! instead of assigning nil
0.9.8
diff --git a/README.textile b/README.textile
index a620af903..5057ce70b 100644
--- a/README.textile
+++ b/README.textile
@@ -337,7 +337,7 @@ Formtastic supports localized *labels*, *hints*, *legends*, *actions* using the
title: "Choose a good title for you post."
body: "Write something inspiring here."
actions:
- create: "Create my {{model}}"
+ create: "Create my %{model}"
update: "Save changes"
dummie: "Launch!"
@@ -354,7 +354,7 @@ Formtastic supports localized *labels*, *hints*, *legends*, *actions* using the
<%= form.input :section %> # => :label => I18n.t('activerecord.attributes.user.section') or 'Section'
<% end %>
<% form.buttons do %>
- <%= form.commit_button %> # => "Create my {{model}}"
+ <%= form.commit_button %> # => "Create my %{model}"
<% end %>
<% end %>
diff --git a/generators/formtastic/templates/formtastic.rb b/generators/formtastic/templates/formtastic.rb
index ee76ff638..bb710efcc 100644
--- a/generators/formtastic/templates/formtastic.rb
+++ b/generators/formtastic/templates/formtastic.rb
@@ -28,7 +28,7 @@
# Formtastic::SemanticFormBuilder.inline_errors = :sentence
# Set the method to call on label text to transform or format it for human-friendly
-# reading when formtastic is user without object. Defaults to :humanize.
+# reading when formtastic is used without object. Defaults to :humanize.
# Formtastic::SemanticFormBuilder.label_str_method = :humanize
# Set the array of methods to try calling on parent objects in :select and :radio inputs
diff --git a/lib/formtastic.rb b/lib/formtastic.rb
index 6ea708296..7319eedcb 100644
--- a/lib/formtastic.rb
+++ b/lib/formtastic.rb
@@ -1606,9 +1606,9 @@ def humanized_attribute_name(method) #:nodoc:
#
# Lookup priority:
#
- # 'formtastic.{{type}}.{{model}}.{{action}}.{{attribute}}'
- # 'formtastic.{{type}}.{{model}}.{{attribute}}'
- # 'formtastic.{{type}}.{{attribute}}'
+ # 'formtastic.%{type}.%{model}.%{action}.%{attribute}'
+ # 'formtastic.%{type}.%{model}.%{attribute}'
+ # 'formtastic.%{type}.%{attribute}'
#
# Example:
#
@@ -1627,15 +1627,16 @@ def localized_string(key, value, type, options = {}) #:nodoc:
use_i18n = value.nil? ? @@i18n_lookups_by_default : (value != false)
if use_i18n
- model_name = self.model_name.underscore
+ model_name, nested_model_name = normalize_model_name(self.model_name.underscore)
action_name = template.params[:action].to_s rescue ''
attribute_name = key.to_s
defaults = ::Formtastic::I18n::SCOPES.collect do |i18n_scope|
i18n_path = i18n_scope.dup
- i18n_path.gsub!('{{action}}', action_name)
- i18n_path.gsub!('{{model}}', model_name)
- i18n_path.gsub!('{{attribute}}', attribute_name)
+ i18n_path.gsub!('%{action}', action_name)
+ i18n_path.gsub!('%{model}', model_name)
+ i18n_path.gsub!('%{nested_model}', nested_model_name) unless nested_model_name.nil?
+ i18n_path.gsub!('%{attribute}', attribute_name)
i18n_path.gsub!('..', '.')
i18n_path.to_sym
end
@@ -1652,6 +1653,14 @@ def model_name
@object.present? ? @object.class.name : @object_name.to_s.classify
end
+ def normalize_model_name(name)
+ if name =~ /(.+)\[(.+)\]/
+ [$1, $2]
+ else
+ [name]
+ end
+ end
+
def send_or_call(duck, object)
if duck.is_a?(Proc)
duck.call(object)
diff --git a/lib/formtastic/i18n.rb b/lib/formtastic/i18n.rb
index 97b05e4c2..5d917fdfb 100644
--- a/lib/formtastic/i18n.rb
+++ b/lib/formtastic/i18n.rb
@@ -6,13 +6,16 @@ module I18n
:required => 'required',
:yes => 'Yes',
:no => 'No',
- :create => 'Create {{model}}',
- :update => 'Update {{model}}'
+ :create => 'Create %{model}',
+ :update => 'Update %{model}'
}.freeze
SCOPES = [
- '{{model}}.{{action}}.{{attribute}}',
- '{{model}}.{{attribute}}',
- '{{attribute}}'
+ '%{model}.%{nested_model}.%{action}.%{attribute}',
+ '%{model}.%{action}.%{attribute}',
+ '%{model}.%{nested_model}.%{attribute}',
+ '%{model}.%{attribute}',
+ '%{nested_model}.%{attribute}',
+ '%{attribute}'
]
class << self
diff --git a/spec/commit_button_spec.rb b/spec/commit_button_spec.rb
index 18f4289e5..efe24cb9d 100644
--- a/spec/commit_button_spec.rb
+++ b/spec/commit_button_spec.rb
@@ -147,7 +147,7 @@
describe 'when no explicit label is provided' do
describe 'when no I18n-localized label is provided' do
before do
- ::I18n.backend.store_translations :en, :formtastic => {:submit => 'Submit {{model}}'}
+ ::I18n.backend.store_translations :en, :formtastic => {:submit => 'Submit %{model}'}
end
after do
@@ -183,7 +183,7 @@
:formtastic => {
:actions => {
:post => {
- :submit => 'Custom Submit {{model}}'
+ :submit => 'Custom Submit %{model}'
}
}
}
@@ -225,7 +225,7 @@
describe 'when no explicit label is provided' do
describe 'when no I18n-localized label is provided' do
before do
- ::I18n.backend.store_translations :en, :formtastic => {:create => 'Create {{model}}'}
+ ::I18n.backend.store_translations :en, :formtastic => {:create => 'Create %{model}'}
end
after do
@@ -261,7 +261,7 @@
:formtastic => {
:actions => {
:post => {
- :create => 'Custom Create {{model}}'
+ :create => 'Custom Create %{model}'
}
}
}
@@ -303,7 +303,7 @@
describe 'when no explicit label is provided' do
describe 'when no I18n-localized label is provided' do
before do
- ::I18n.backend.store_translations :en, :formtastic => {:update => 'Save {{model}}'}
+ ::I18n.backend.store_translations :en, :formtastic => {:update => 'Save %{model}'}
end
after do
@@ -340,7 +340,7 @@
:formtastic => {
:actions => {
:post => {
- :update => 'Custom Save {{model}}'
+ :update => 'Custom Save %{model}'
}
}
}
diff --git a/spec/i18n_spec.rb b/spec/i18n_spec.rb
index ee6f4a6ae..a19be951a 100644
--- a/spec/i18n_spec.rb
+++ b/spec/i18n_spec.rb
@@ -26,11 +26,11 @@
@formtastic_strings = {
:yes => 'Default Yes',
:no => 'Default No',
- :create => 'Default Create {{model}}',
- :update => 'Default Update {{model}}',
+ :create => 'Default Create %{model}',
+ :update => 'Default Update %{model}',
:custom_scope => {
:duck => 'Duck',
- :duck_pond => '{{ducks}} ducks in a pond'
+ :duck_pond => '%{ducks} ducks in a pond'
}
}
::I18n.backend.store_translations :en, :formtastic => @formtastic_strings
@@ -71,7 +71,7 @@
it "should use default strings" do
(::Formtastic::I18n::DEFAULT_VALUES.keys).each do |key|
- ::Formtastic::I18n.t(key, :model => '{{model}}').should == ::Formtastic::I18n::DEFAULT_VALUES[key]
+ ::Formtastic::I18n.t(key, :model => '%{model}').should == ::Formtastic::I18n::DEFAULT_VALUES[key]
end
end
@@ -89,7 +89,8 @@
:labels => {
:title => "Hello world!",
:post => {:title => "Hello post!"},
- :project => {:title => "Hello project!"}
+ :project => {:title => "Hello project!", :task => {:name => "Hello task name!"}},
+ :line_item => {:name => "Hello line item name!"}
}
}
::Formtastic::SemanticFormBuilder.i18n_lookups_by_default = true
@@ -123,6 +124,25 @@
output_buffer.should have_tag("form label", /Hello project!/)
end
+ it 'should be able to translate nested objects with nested translations' do
+ semantic_form_for(:project, :url => 'http://test.host') do |builder|
+ builder.semantic_fields_for(:task) do |f|
+ concat(f.input(:name))
+ end
+ end
+ output_buffer.should have_tag("form label", /Hello task name!/)
+ end
+
+ it 'should be able to translated nested objects with top level translations' do
+ semantic_form_for(:order, :url => 'http://test.host') do |builder|
+ builder.semantic_fields_for(:line_item) do |f|
+ concat(f.input(:name))
+ end
+ end
+ output_buffer.should have_tag("form label", /Hello line item name!/)
+ end
+
+
# TODO: Add spec for namespaced models?
end
diff --git a/spec/inputs/country_input_spec.rb b/spec/inputs/country_input_spec.rb
index 514e1cc00..67570b32d 100644
--- a/spec/inputs/country_input_spec.rb
+++ b/spec/inputs/country_input_spec.rb
@@ -56,8 +56,8 @@
it "should be passed down to the country_select helper when provided" do
priority_countries = ["Foo", "Bah"]
semantic_form_for(@new_post) do |builder|
- builder.stub!(:country_select).and_return("")
- builder.should_receive(:country_select).with(:country, priority_countries, {}, {}).and_return("")
+ builder.stub!(:country_select).and_return(Formtastic::Util.html_safe(""))
+ builder.should_receive(:country_select).with(:country, priority_countries, {}, {}).and_return(Formtastic::Util.html_safe(""))
concat(builder.input(:country, :as => :country, :priority_countries => priority_countries))
end
@@ -69,8 +69,8 @@
priority_countries.should_not be_nil
semantic_form_for(@new_post) do |builder|
- builder.stub!(:country_select).and_return("")
- builder.should_receive(:country_select).with(:country, priority_countries, {}, {}).and_return("")
+ builder.stub!(:country_select).and_return(Formtastic::Util.html_safe(""))
+ builder.should_receive(:country_select).with(:country, priority_countries, {}, {}).and_return(Formtastic::Util.html_safe(""))
concat(builder.input(:country, :as => :country))
end
@@ -84,7 +84,7 @@
before do
@form = semantic_form_for(@new_post) do |builder|
- builder.stub!(:country_select).and_return("")
+ builder.stub!(:country_select).and_return(Formtastic::Util.html_safe(""))
concat(builder.input(:country))
end
end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 14f9cd0c4..27951146c 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -1,8 +1,8 @@
# coding: utf-8
require 'rubygems'
-gem 'activesupport', '>= 2.3.5'
-gem 'actionpack', '>= 2.3.5'
+gem 'activesupport', '>=2.3.7'
+gem 'actionpack', '>=2.3.7'
require 'active_support'
require 'action_pack'
require 'action_view'
@@ -37,6 +37,7 @@
end
require File.expand_path(File.join(File.dirname(__FILE__), '../lib/formtastic'))
+require File.expand_path(File.join(File.dirname(__FILE__), '../lib/formtastic/util'))
require File.expand_path(File.join(File.dirname(__FILE__), '../lib/formtastic/layout_helper'))
module ActionView