代码之家  ›  专栏  ›  技术社区  ›  Mel

轨道4-国家选择和简单形式

  •  0
  • Mel  · 技术社区  · 9 年前

    我正在尝试在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而不是Australia(这是地址模型中的方法提供的)。

    地址表:

    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
    

    再次尝试:

    我找到了此资源: http://www.scriptscoop.net/t/4ee6d5ef4577/displaying-countries-using-country-select-gem-in-rails-4.html

    我尝试将表单输入更改为:

            <%= f.country_select  :country, priority: [ "Australia", "New Zealand", "United Kingdom" ] %>
    

    它仍然只显示国家代码而不是国家名称。我被卡住了。

    另一次尝试

    我发现了这个帖子: Rails Simple_Form: How to show long name of the country

    本文中的答案建议将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”的公式相同的错误。我认为这些尝试不起作用,因为我的地址表中的属性被称为“国家”。

    当我将方法更改为:

      def country_name
        self.country = ISO3166::Country[country]
        country.translations[I18n.locale.to_s] || country.name
      end
    

    我发现“翻译”一词有误。当我删除'时。从方法“translations”,我得到一个单词“name”的错误。

    我想弄明白这一点,真是大吃一惊。

    另一次尝试

    我尝试将countrygem添加到我的gem文件中(country_select上方)。

    当我捆绑这颗宝石时,一切都没有改变。同样的问题。

    另一次尝试

    再次尝试(正如我最初定义的方法),但安装了countrygem(在country_select gem上面):

    定义国家名称
    自己country=ISO3166::国家[国家]
    country.translations[I18n.locale.to_s]||country.name
    终止
    

    我得到这个错误:“Cayman Islands”的未定义方法“translations”:String

    这是我最初遇到的问题,所以我不认为添加国家宝石有助于解决问题。

    3 回复  |  直到 7 年前
        1
  •  5
  •   Purry    9 年前

    这个代码对我来说很好 列。 在我的模型上:-

       def country_name
        country = self.country
        ISO3166::Country[country]
       end
    

    格式为:-

        <%= form_for @user do |f| %>
           <%= country_select("user", "country") %>
        <% end %>
    
        2
  •  0
  •   Jaehyun Shin    9 年前

    你的问题还不够,有些地方应该出错。

    第一

    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代码或国家名称作为散列键

    更新:

    您有一个字符串的country列。 使命感 self.country = ISO3166::Country[country] 指在中分配ISO3166::Country实例 country(string) 变量所以它会出错。

    我不知道你期望什么。
    但您应该使用ISO03166::Country的键作为ISO代码。喜欢 ISO3166::Country['AU'] 。你不能在自己的国家分配这个。

    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
    
        3
  •  0
  •   MTarantini    9 年前

    看起来答案将是你之前尝试的某种组合。

    Country_select使用国家代码而不是国家全名:

    country_select("user", "country", priority_countries: ["GB", "FR", "DE"])
    

    这显示在该宝石的github页面上: https://github.com/stefanpenner/country_select

    由于select返回国家代码,因此我们可以假设国家属性将是国家代码而不是完整的国家名称。 考虑到这一点,我们将修改前面的答案:

    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而不是country。

    您遇到的问题是,当您将ISO3166::Country对象指定给对象的属性(self.Country=ISO3166::Country[Country])时,并不是将ISO3166::County对象本身指定给该属性,而是将ISO3166::Countary对象的名称指定给它。

    我在Rails控制台中测试了这一点:

    user = User.new
      #<User:0x007ff7de29d1b8
      id: nil,
      ...
    user.country = ISO3166::Country['AU']
      #<ISO3166::Country:0x007ff7de3c6a08
      @data=
      {"continent"=>"Australia",
      ...
    user.country
      "Australia"
    

    如您所见,它为属性指定了国家名称(而不是国家对象)。因此,当您尝试访问国家时。翻译或国家。name将抛出一个错误,因为它正在访问address属性而不是country对象。所以一定要保持变量名与属性名不同。

    最后一件事,如果您有国家名称,那么使用find_country_by_name方法代替find_by_name,因为find_byname将返回一个数组,而find_cuntry_by-name将返回country对象。这在您当前的场景中不应该是必需的,但是如果您以后需要使用它,请记住这一点。