【问题标题】:How to have a drop down <select> field in a rails form?如何在 rails 表单中有一个下拉 <select> 字段?
【发布时间】:2013-01-01 18:27:49
【问题描述】:

我正在创建一个脚手架 -

rails g scaffold Contact email:string email_provider:string 

但我希望电子邮件提供商是一个下拉列表(使用 gmail/yahoo/msn 作为选项)而不是文本字段。我怎样才能做到这一点 ?

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 drop-down-menu input selectlist


    【解决方案1】:

    你可以看看the Rails documentation。无论如何,以你的形式:

      <%= f.collection_select :provider_id, Provider.order(:name),:id,:name, include_blank: true %>
    

    您可以猜到,您应该在另一个模型 -Provider 中预定义电子邮件提供者,以便从中选择它们。

    【讨论】:

    • 所以模型将是contact.rb,但是我应该把那个下拉逻辑放在哪里?对不起,天真的问题,我是 RoR 开发的新手
    • 你的问题没问题。如果您查看 app/views/contacts 的结构,您会发现一个文件 _form.html.erb 。你可以试着把它放在那里。这个“局部视图”负责创建和更新您生成的脚手架的操作。
    • 建议将 order(:name) 移动到模型中的范围(这是一种方法)。这不是什么大问题,但随着时间的推移,你会发现,在视图模板上拥有的本质上是这样的业务逻辑(排序)变得一团糟。将其移至控制器,或者理想情况下是模型,并在那里提供一个可用的范围,您可以使用它。一个例子——如果你最终得到三个使用下拉菜单的屏幕或模板,那么视图中的顺序意味着 3 X 重复。将它放在模型中意味着它被定义在一个地方,这是唯一可以更改它的地方。
    【解决方案2】:

    或用于自定义选项

    <%= f.select :desired_attribute, ['option1', 'option2']%>
    

    【讨论】:

    【解决方案3】:

    您在 Contact 控制器中创建集合 -

    app/controllers/contacts_controller.erb 
    

    添加

    @providers = Provider.all.by_name
    

    使用 Provider 模型中的 by_name 的范围 - app/models/provider.rb - 用于按名称排序的新方法、创建和编辑方法

    scope by_name  order(:name)
    

    然后在视图中——app/views/contacts/_form.html.erb——你使用

    <%= f.collection_select :provider_id, @providers, :id, :name, include_blank: true %>
    

    对于 Rails 表单,我还强烈建议您查看像 simple_form - https://github.com/plataformatec/simple_form 这样的表单构建器 - 它将完成所有繁重的工作。

    【讨论】:

    • 谢谢迈克尔,我编辑了这个问题并添加了另一个对我有用的代码,所以只是想知道使用 Select 和 collection_select 有什么区别,如下面的答案所述?
    【解决方案4】:

    这是一个漫长的过程,但如果您还没有实现,那么您最初可以通过这种方式创建模型。以下方法描述了更改现有数据库。

    1) 为电子邮件提供商创建一个新模型:
    $ rails g model provider name

    2) 这将创建带有名称字符串和时间戳的模型。它还创建了我们需要添加到架构中的迁移:
    $ rake db:migrate

    3) 添加迁移以将提供者 ID 添加到联系人中:
    $ rails g migration AddProviderRefToContacts provider:references

    4) 检查迁移文件以检查它是否正常,然后也进行迁移:
    $ rake db:migrate

    5) 好的,现在我们有了 provider_id,我们不再需要原来的 email_provider 字符串:
    $ rails g migration RemoveEmailProviderFromContacts

    6) 在迁移文件中,添加如下所示的更改:

    class RemoveEmailProviderFromContacts < ActiveRecord::Migration
      def change
        remove_column :contacts, :email_provider
      end
    end
    

    7) 完成后,迁移更改:
    $ rake db:migrate

    8) 让我们借此机会更新我们的模型:
    联系人:belongs_to :provider
    提供者:has_many :contacts

    9) 然后,我们在视图中的 _form.html.erb 部分设置下拉逻辑:

      <div class="field">
        <%= f.label :provider %><br>
        <%= f.collection_select :provider_id, Provider.all, :id, :name %>
      </div>
    

    10) 最后,我们需要自己添加提供者。一种最好的方法是使用种子文件:

    Provider.destroy_all
    
    gmail = Provider.create!(name: "gmail")
    yahoo = Provider.create!(name: "yahoo")
    msn = Provider.create!(name: "msn")
    

    $ rake db:seed

    【讨论】:

      【解决方案5】:

      &lt;%= f.select :email_provider, ["gmail","yahoo","msn"]%&gt;

      【讨论】:

        【解决方案6】:

        请看here

        你可以使用 rails 标签或者使用纯 HTML 标签

        Rails 标记

        <%= select("Contact", "email_provider", Contact::PROVIDERS, {:include_blank => true}) %>
        

        *上面一行代码会变成HTML代码(HTML Tag),在下面找到它*

        HTML 标记

        <select name="Contact[email_provider]">
          <option></option>
          <option>yahoo</option>
          <option>gmail</option>
          <option>msn</option>
        </select>
        

        【讨论】:

        • 谢谢,我还是一头雾水,我知道
        【解决方案7】:

        在您的模型中,

        class Contact
          self.email_providers = %w[Gmail Yahoo MSN]
          validates :email_provider, :inclusion => email_providers
        end
        

        在你的表格中,

        <%= f.select :email_provider, 
            options_for_select(Contact.email_providers, @contact.email_provider) %>
        

        options_for_select 的第二个参数将选择任何当前的 email_provider。

        【讨论】:

          【解决方案8】:

          Rails 使用文章和类别的 has_many 关联下拉:

          has_many :articles
          
          belongs_to :category
          
          <%= form.select :category_id,Category.all.pluck(:name,:id),{prompt:'select'},{class: "form-control"}%>
          

          【讨论】:

            猜你喜欢
            • 2011-01-02
            • 1970-01-01
            • 1970-01-01
            • 2014-06-24
            • 1970-01-01
            • 2020-07-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多