2014-06-12 14 views
9

Ruby on Rails 4.1Chọn enum từ biểu mẫu để đặt vai trò

Tôi đang sử dụng Devise với vai trò enum. Nó hiện đang thiết lập một vai trò defualt khi người dùng được tạo ra. Tôi muốn thêm một trường vào biểu mẫu tạo Người dùng để đặt vai trò enum.

Tôi đọc this nhưng không nói cách sử dụng các vai trò mới.

Đây là lớp người dùng

devise :database_authenticatable, :registerable, :confirmable, 
    :recoverable, :rememberable, :trackable, :validatable 
enum role: [:user, :vip, :admin, :developer, :marketing, :support, :translator] 
after_initialize :set_default_role, :if => :new_record? 

def set_default_role 
    self.role ||= :user 
end 

Đây là một phần của hình thức mà tôi đang cố gắng để có một lựa chọn để chọn một vai trò quan enum:

<div class="form-group"> 
    <%= f.collection_select :role, User.roles, :id, :enum, {prompt: "Select a role"}, {class: "form-control input-lg"} %> 
</div> 

Lỗi:

NoMethodError - undefined method `enum' for ["user", 0]:Array: 
actionview (4.1.1) lib/action_view/helpers/form_options_helper.rb:761:in `value_for_collection' 

Tôi chưa bao giờ sử dụng enum trước và the documentation không chứng tỏ hữu ích. Làm cách nào để tôi hiển thị các tùy chọn enum?

Trả lời

20

Để bắt đầu, enum không phải là tên của thuộc tính. Tên của thuộc tính là role.

Hãy xem ứng dụng ví dụ rails-devise-pundit, cụ thể là tệp ứng dụng/lượt xem/người dùng/_user.html.erb là một phần tạo biểu mẫu cho phép quản trị viên thay đổi vai trò của người dùng. Tôi nghi ngờ bạn muốn sử dụng collection_select cho trình trợ giúp (phù hợp nếu bạn có một mô hình Vai trò riêng biệt). Thay vào đó, một trình trợ giúp biểu mẫu select bình thường sẽ hoạt động.

Dưới đây là một ví dụ đơn giản mà hardcodes các tùy chọn vai trò:

<%= f.select(:role, [['User', 'user'], ['Vip', 'vip'], ['Admin', 'admin']]) %> 

Dưới đây là một ví dụ tốt hơn mà tránh thể xác định rõ vai trò trong các hình thức:

<%= f.select(:role, User.roles.keys.map {|role| [role.titleize,role]}) %> 

Những tuyên bố có được một loạt các vai trò từ Mô hình người dùng và tạo một mảng các cặp khóa-giá trị sử dụng phương thức map.

+0

Điều duy nhất còn lại cần làm là ghi đè lên Devise :: RegistrationsController # tạo để cho phép vai trò ngay bây giờ. +1 – DDDD

+0

Không cần phải ghi đè lên bộ điều khiển Đăng ký. Bạn có thể làm điều đó trong bộ điều khiển Ứng dụng. Xem [Rails Devise Tutorial] của tôi (http://railsapps.github.io/rails-devise/) hoặc [Devise README] (https://github.com/plataformatec/devise). –

+0

Tôi nghĩ tôi đã làm điều đó một cách không lười biếng. Tôi đã tạo một Users: RegistrationsController với một before_filter: configure_permitted_parameters mà sanitizer.for (: sign_up) Nếu tôi đăng mã đó, bạn có thể cho tôi biết nếu đó là cách an toàn để thực hiện nó không? – DDDD

3

Cách sạch mà tôi đã đi với để sử dụng collection_select với enum s như sau:

f.collection_select :diet_preference, User.roles.map{ |dp| [dp.first, dp.first.humanize] }, :first, :second 
7

Vì bạn đang sử dụng Rails 4 hoặc cao hơn, enums thậm chí còn ít phức tạp hơn.

Với enum sau:

enum role: { 
    admin: 1 
} 

Enums mong đợi HTML tùy chọn thuộc tính value là chìa khóa enum:

<option value="admin"> <!-- As opposed to: <option value="1"> --> 

Biết được điều này, bạn có thể vượt qua trong những chìa khóa enum.

<%= f.select :role, User.roles.keys, {}, class: 'user-roles-select' %> 

Sau đó, sử dụng CSS, bạn có thể sửa đổi giao diện.

.user-roles-select option { 
    text-transform: capitalize; 
} 
1

Đây là cách tôi đã làm, với quốc tế hóa và đặt hàng, và tự động chọn vai trò current_user nếu đã được xác định. Nó giả định rằng bạn có một tập tin địa phương với vai trò: loại có chứa tất cả các vai trò enum của bạn như:

# your locale file 
en: 
roles: 
    admin: "Administrator" 
    mode: "Moderator" 


# model user.rb 
enum role: { admin: 0, mode: 1 } 
ROLES = User.roles.map { |r,| [I18n.t("roles.#{r}"), r] }.sort_by { |r| I18n.t("roles.#{r}") } 

# view 

<%= f.select :role, User::ROLES, { prompt: t("users.roles.prompt"), selected: @user.role }, { class: "form-control" } %> 
0

Như enum là một wrapper cho số nguyên trong Rails, và tôi muốn để lưu trữ các chuỗi trong DB thay vào đó, tôi đã làm như sau:

class Child < ApplicationRecord 
     enum year: { 
      Infant: 'Infant', 
      '2-5_years': '2_to_5_years', 
      '5-8_years': '5_to_8_years', 
      '8-10_years': '8_to_10 years', 
      'More_than_10_years': 'More_than_10_years' 
     } 
     AGE_YEARS = Child.years.map { |k, v| [k.humanize, v] } 
    } 

Ở dạng của tôi,

<%= f.select :age, options_for_select(Child::AGE_YEARS, params[:age]), include_blank: 'Select an age-group.' %> 

Khi tôi đang sử dụng máy chủ PostgreSQL trong đó một datatype được xác định trước có thể được khai báo, tôi gắn một cột gọi là 'năm' cho mô hình con của loại'year '.

rails generate migration AddYearToChildren year:year 

và thay đổi tệp di chuyển như dưới đây.

class AddYearToChildren < ActiveRecord::Migration[5.0] 
    def up 
    execute <<-SQL 
     CREATE TYPE year AS ENUM ('Infant', '2_5_years', '5_8_years', '8_10_years', 'More_than_10_years'); 
    SQL 
    add_column :children, :year, :year, index: true 
    end 

    def down 
    remove_column :children, :year 

    execute <<-SQL 
     DROP TYPE year; 
    SQL 
    end 
end 

Cuối cùng, rails db:migrate cho các thay đổi di chuyển DB.

Vì vậy, hiện tại đường ray enum có thể được sử dụng để lưu trữ chuỗi trong DB.

Các vấn đề liên quan