Rails 4 - 国家 Select & 简单表格
Rails 4 - Country Select & Simple Form
我正在尝试在 Rails 4 中制作一个应用程序。我使用简单的表格作为表格,country_select gem 作为国家/地区列表。
我有一个地址模型,其中包括这个方法:
def country_name
self.country = ISO3166::Country[country]
country.translations[I18n.locale.to_s] || country.name
end
当我尝试保存新地址时,出现此错误:
undefined method `translations' for "Australia":String
谁能看出这个方法定义有什么问题?
如果我将我的观点更改为:
<% if @profile.addresses.any? %>
<%= @profile.addresses.first.country.titlecase %>
<% else %>
<span class="profileeditlink">
<%= link_to "Add your location", new_address_path %>
</span>
<% end %>
然后记录显示 - 但作为 AU 而不是澳大利亚(这是地址模型中的方法提供的)。
地址table:
create_table "addresses", force: :cascade do |t|
t.string "unit"
t.string "building"
t.string "street_number"
t.string "street"
t.string "city"
t.string "region"
t.string "zip"
t.string "country"
t.boolean "main_address"
t.boolean "project_offsite"
t.string "time_zone"
t.float "latitude"
t.float "longitude"
t.integer "addressable_id"
t.integer "addressable_type"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "addresses", ["addressable_type", "addressable_id"], name: "index_addresses_on_addressable_type_and_addressable_id", unique: true, using: :btree
采纳 JAEHYEN 的建议,
我将地址模型中的国家/地区名称方法更改为:
def country_name
# self.country = ISO3166::Country(country)
# country.translations[I18n.locale.to_s] || country.name
iso_country = ISO3166::Country.find_by_name[country] # `country` should be name like 'Australia'
iso_country.translations[I18n.locale.to_s] || iso_country.name
end
我收到这个错误:
undefined method `translations' for nil:NilClass
另一次尝试:
我尝试将表单输入更改为:
<%= f.country_select :country, priority: [ "Australia", "New Zealand", "United Kingdom" ] %>
它仍然只显示国家代码而不是国家名称。我卡住了。
另一次尝试
我找到了这个 post:
Rails Simple_Form: How to show long name of the country
这个post中的答案建议将country_name定义为:
def country_name
country = ISO3166::Country[country_code]
country.translations[I18n.locale.to_s] || country.name
end
这与我之前的尝试略有不同,但是,当我尝试这个时,我得到了这个错误:
undefined local variable or method `country_code' for #<Address:0x007fbae5bfb290>
我尝试将方法更改为:
def country_name
self.country = ISO3166::Country[country_code]
country.translations[I18n.locale.to_s] || country.name
end
这给出了与不使用 'self' 的公式相同的错误。我认为这些尝试不起作用,因为我的地址 table 中的属性称为 'country'.
当我将方法更改为:
def country_name
self.country = ISO3166::Country[country]
country.translations[I18n.locale.to_s] || country.name
end
我收到单词 'translations' 的错误。当我从方法中删除“.translations”时,我收到一个错误 'name'.
我正在失去理智试图解决这个问题。
另一次尝试
我尝试将国家 gem 添加到我的 gem 文件(在 country_select 之上)。
当我捆绑这个 gem 时没有任何变化。同样的问题。
另一次尝试
再试一次(因为我最初定义了方法),但安装了国家 gem(country_select gem 以上):
def country_name
self.country = ISO3166::Country[country]
country.translations[I18n.locale.to_s] || country.name
end
我收到此错误:"Cayman Islands":String
的未定义方法“翻译”
这是我最初遇到的同一个问题,所以我认为添加国家 gem 对解决问题没有帮助。
你的问题还不够,有些地方应该出错。
首先,
def country_name
self.country = ISO3166::Country[country]
country.translations[I18n.locale.to_s] || country.name
end
在这个方法中,你应该明确country / self.country
变量或实例。我无法想象 country
是 ISO3166::Country
实例或 String
第二,
明确它使用 ISO 代码或国家名称作为哈希键
更新:
您的国家/地区列是字符串。
调用 self.country = ISO3166::Country[country]
意味着在 country(string)
变量中分配 ISO3166::Country 个实例。所以它会出错。
我不知道你期待什么。
但是你应该使用 ISO03166::Country 的密钥作为 ISO 代码。喜欢 ISO3166::Country['AU']
。而且你不能在 self.country.
中分配它
def country_name
iso_county = ISO3166::Country[country] # `country` should be iso_code
iso_country.translations[I18n.locale.to_s] || iso_country.name
end
如果您在国家列中有国家名称,而不是 ISO 代码。使用 ISO3166::Country.find_by_name
def country_name
iso_county = ISO3166::Country.find_by_name(country) # `country` should be name like 'Australia'
iso_country.translations[I18n.locale.to_s] || iso_country.name
end
看起来答案将是您之前尝试的某种组合。
Country_select 使用国家代码而不是完整的国家名称:
country_select("user", "country", priority_countries: ["GB", "FR", "DE"])
gem 的 github 页面显示了这一点:
https://github.com/stefanpenner/country_select
由于 select return 是国家代码,因此我们可以假设国家属性将是国家代码而不是完整的国家名称。
考虑到这一点,我们将修改之前的答案:
def country_name
iso_country = ISO3166::Country[country] # `country` should be code like 'AU'
iso_country.translations[I18n.locale.to_s] || iso_country.name
end
最好避免创建与该模型中的属性同名的变量,因此在测试中坚持使用 iso_country 而不是国家/地区。
您遇到的问题是,当您将 ISO3166::Country 对象分配给对象的属性 (self.country = ISO3166::Country[国家/地区]) 时,它不会分配 ISO3166::Country 对象本身分配给该属性,而是将 ISO3166::Country 对象的名称分配给它。
我在 Rails 控制台中测试了这个:
user = User.new
#<User:0x007ff7de29d1b8
id: nil,
...
user.country = ISO3166::Country['AU']
#<ISO3166::Country:0x007ff7de3c6a08
@data=
{"continent"=>"Australia",
...
user.country
"Australia"
如您所见,它将国家名称(而不是国家对象)分配给属性。因此,当您尝试访问 country.translations 或 country.name 时,它将抛出错误,因为它正在访问地址属性而不是国家/地区对象。所以一定要保持变量名和属性名不同。
最后一件事,如果你确实有国家名称,那么使用方法 find_country_by_name 而不是 find_by_name 因为 find_by_name 将 return 一个数组,而 find_country_by_name 将 return 一个国家对象。这在您当前的场景中应该不是必需的,但如果您以后需要使用它,请记住它。
这段代码很适合我。我的用户 table 中有 国家/地区 列。
在我的模型上:-
def country_name
country = self.country
ISO3166::Country[country]
end
形式为:-
<%= form_for @user do |f| %>
<%= country_select("user", "country") %>
<% end %>
我正在尝试在 Rails 4 中制作一个应用程序。我使用简单的表格作为表格,country_select gem 作为国家/地区列表。
我有一个地址模型,其中包括这个方法:
def country_name
self.country = ISO3166::Country[country]
country.translations[I18n.locale.to_s] || country.name
end
当我尝试保存新地址时,出现此错误:
undefined method `translations' for "Australia":String
谁能看出这个方法定义有什么问题?
如果我将我的观点更改为:
<% if @profile.addresses.any? %>
<%= @profile.addresses.first.country.titlecase %>
<% else %>
<span class="profileeditlink">
<%= link_to "Add your location", new_address_path %>
</span>
<% end %>
然后记录显示 - 但作为 AU 而不是澳大利亚(这是地址模型中的方法提供的)。
地址table:
create_table "addresses", force: :cascade do |t|
t.string "unit"
t.string "building"
t.string "street_number"
t.string "street"
t.string "city"
t.string "region"
t.string "zip"
t.string "country"
t.boolean "main_address"
t.boolean "project_offsite"
t.string "time_zone"
t.float "latitude"
t.float "longitude"
t.integer "addressable_id"
t.integer "addressable_type"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "addresses", ["addressable_type", "addressable_id"], name: "index_addresses_on_addressable_type_and_addressable_id", unique: true, using: :btree
采纳 JAEHYEN 的建议,
我将地址模型中的国家/地区名称方法更改为:
def country_name
# self.country = ISO3166::Country(country)
# country.translations[I18n.locale.to_s] || country.name
iso_country = ISO3166::Country.find_by_name[country] # `country` should be name like 'Australia'
iso_country.translations[I18n.locale.to_s] || iso_country.name
end
我收到这个错误:
undefined method `translations' for nil:NilClass
另一次尝试:
我尝试将表单输入更改为:
<%= f.country_select :country, priority: [ "Australia", "New Zealand", "United Kingdom" ] %>
它仍然只显示国家代码而不是国家名称。我卡住了。
另一次尝试
我找到了这个 post: Rails Simple_Form: How to show long name of the country
这个post中的答案建议将country_name定义为:
def country_name
country = ISO3166::Country[country_code]
country.translations[I18n.locale.to_s] || country.name
end
这与我之前的尝试略有不同,但是,当我尝试这个时,我得到了这个错误:
undefined local variable or method `country_code' for #<Address:0x007fbae5bfb290>
我尝试将方法更改为:
def country_name
self.country = ISO3166::Country[country_code]
country.translations[I18n.locale.to_s] || country.name
end
这给出了与不使用 'self' 的公式相同的错误。我认为这些尝试不起作用,因为我的地址 table 中的属性称为 'country'.
当我将方法更改为:
def country_name
self.country = ISO3166::Country[country]
country.translations[I18n.locale.to_s] || country.name
end
我收到单词 'translations' 的错误。当我从方法中删除“.translations”时,我收到一个错误 'name'.
我正在失去理智试图解决这个问题。
另一次尝试
我尝试将国家 gem 添加到我的 gem 文件(在 country_select 之上)。
当我捆绑这个 gem 时没有任何变化。同样的问题。
另一次尝试
再试一次(因为我最初定义了方法),但安装了国家 gem(country_select gem 以上):
def country_name
self.country = ISO3166::Country[country]
country.translations[I18n.locale.to_s] || country.name
end
我收到此错误:"Cayman Islands":String
的未定义方法“翻译”这是我最初遇到的同一个问题,所以我认为添加国家 gem 对解决问题没有帮助。
你的问题还不够,有些地方应该出错。
首先,
def country_name
self.country = ISO3166::Country[country]
country.translations[I18n.locale.to_s] || country.name
end
在这个方法中,你应该明确country / self.country
变量或实例。我无法想象 country
是 ISO3166::Country
实例或 String
第二,
明确它使用 ISO 代码或国家名称作为哈希键
更新:
您的国家/地区列是字符串。
调用 self.country = ISO3166::Country[country]
意味着在 country(string)
变量中分配 ISO3166::Country 个实例。所以它会出错。
我不知道你期待什么。
但是你应该使用 ISO03166::Country 的密钥作为 ISO 代码。喜欢 ISO3166::Country['AU']
。而且你不能在 self.country.
def country_name
iso_county = ISO3166::Country[country] # `country` should be iso_code
iso_country.translations[I18n.locale.to_s] || iso_country.name
end
如果您在国家列中有国家名称,而不是 ISO 代码。使用 ISO3166::Country.find_by_name
def country_name
iso_county = ISO3166::Country.find_by_name(country) # `country` should be name like 'Australia'
iso_country.translations[I18n.locale.to_s] || iso_country.name
end
看起来答案将是您之前尝试的某种组合。
Country_select 使用国家代码而不是完整的国家名称:
country_select("user", "country", priority_countries: ["GB", "FR", "DE"])
gem 的 github 页面显示了这一点: https://github.com/stefanpenner/country_select
由于 select return 是国家代码,因此我们可以假设国家属性将是国家代码而不是完整的国家名称。 考虑到这一点,我们将修改之前的答案:
def country_name
iso_country = ISO3166::Country[country] # `country` should be code like 'AU'
iso_country.translations[I18n.locale.to_s] || iso_country.name
end
最好避免创建与该模型中的属性同名的变量,因此在测试中坚持使用 iso_country 而不是国家/地区。
您遇到的问题是,当您将 ISO3166::Country 对象分配给对象的属性 (self.country = ISO3166::Country[国家/地区]) 时,它不会分配 ISO3166::Country 对象本身分配给该属性,而是将 ISO3166::Country 对象的名称分配给它。
我在 Rails 控制台中测试了这个:
user = User.new
#<User:0x007ff7de29d1b8
id: nil,
...
user.country = ISO3166::Country['AU']
#<ISO3166::Country:0x007ff7de3c6a08
@data=
{"continent"=>"Australia",
...
user.country
"Australia"
如您所见,它将国家名称(而不是国家对象)分配给属性。因此,当您尝试访问 country.translations 或 country.name 时,它将抛出错误,因为它正在访问地址属性而不是国家/地区对象。所以一定要保持变量名和属性名不同。
最后一件事,如果你确实有国家名称,那么使用方法 find_country_by_name 而不是 find_by_name 因为 find_by_name 将 return 一个数组,而 find_country_by_name 将 return 一个国家对象。这在您当前的场景中应该不是必需的,但如果您以后需要使用它,请记住它。
这段代码很适合我。我的用户 table 中有 国家/地区 列。 在我的模型上:-
def country_name
country = self.country
ISO3166::Country[country]
end
形式为:-
<%= form_for @user do |f| %>
<%= country_select("user", "country") %>
<% end %>