2016-01-02 4 views
1

В RoR, когда вы создаете вложенный ресурс, нужно ли устанавливать атрибуты во время создания ресурса с родительской ассоциацией внутри модели?Создание вложенных ресурсов Rails

У меня есть эта модель ролей, которая может принадлежать и иметь другие роли.

employee = Role.find_by_slug :employee 
employee.role 
=> nil 
employee.roles 
=> [...more roles...] 
waitress = employee.roles.create(slug: :waitress) 
=> #<Role id... 
waitress.role 
=> #<Role slug: 'employee'... 
waitress.roles 
=> [] 

Ролевая модель имеет логический атрибут подтипа. Всякий раз, когда я создаю роль из существующей роли, я бы хотел, чтобы для подтипа было установлено значение true.

employee.subtype 
=> false 

И официантка будет выглядеть следующим образом:

waitress.subtype 
=> true 

ответ

1

Всякий раз, когда я создаю роль из существующего роль, я хотел бы, чтобы для подтипа было установлено значение true.

#app/models/Role.rb 
class Role < ActiveRecord::Base 
    belongs_to :role 
    has_many :roles 

    validate :role_exists, if: "role_id.present?" 
    before_create :set_subtype, if: "role_id.present?" 

    private 

    def set_subtype 
    self.subtype = true 
    end 

    def role_exists 
     errors.add(:role_id, "Invalid") unless Role.exists? role_id 
    end 
end 

выше потребует другого запроса дБ; это только для создания &, это произойдет, когда вызывается модель (IE вы можете называть ее как угодно, когда вам это нужно).

-

Альтернативой этому было бы использовать acts_as_tree или подобный камень иерархии.

AAT добавляет parent_id колонку в вашей БД, к которому он будет затем добавить ряд методов, например, вы можете позвонить по телефону (parent, child и т.д.).

Это позволит вам избавиться от has_many :roles, и заменить его методом в children например:

#app/models/role.rb 
class Role < ActiveRecord::Base 
    acts_as_tree order: "slug" 
    #no need to have "subtype" column or has_many :roles etc 
end 

root  = Role.create   slug: "employee" 
child1 = root.children.create slug: "waitress" 
subchild1 = child1.children.create slug: "VIP_only" 

root.parent # => nil 
child1.parent # => root 
root.children # => [child1] 
root.children.first.children.first # => subchild1 
+0

Мне нравится это решение много, спасибо! – fbelanger

0

По вашему описанию, данному Role считается подтипом, если он не имеет родительскую роль. В этом случае, просто добавьте следующий метод Role:

def subtype? 
    !self.role.nil? 
end 
+0

Вы правы, по моему описанию это работает. Тем не менее, пользователи будут использовать форму для создания разных ролей. Поэтому я предпочитаю, чтобы они определяли, является ли это подтипом проверки. Таким образом, я могу написать что-то вроде: 'validates: role, presence: true, if:: subtype' и' validates: role, отсутствие: true, если:: subtype' – fbelanger

0

следующие изменения сделал трюк для меня:

от:

has_many :roles 

к:

has_many :roles do 
    def create(*args, &block) 
    args[0][:subtype] = true 
    super(*args, &block) 
    end 
end 
+0

Это называется ["monkeypatch"] (https : //en.wikipedia.org/wiki/Monkey_patch) :) –

Смежные вопросы