ActiveRecord (Rails 2.3.8) - обновлять существующие, добавлять новые записи при обновлении вложенных атрибутов - PullRequest
0 голосов
/ 26 октября 2010

У меня есть «пользовательская» модель, которая имеет «has_one» «членство» (активна одновременно).В целях аудита и целостности данных мне бы хотелось, чтобы, если членство изменилось для пользователя, старая / текущая запись (если она существует) поменялась неактивным / активным флагом и была добавлена ​​новая строка для новой измененной записи,Если нет никаких изменений в членстве, я хотел бы просто проигнорировать обновление.Я пытался реализовать это с обратным вызовом before_save в моей пользовательской модели, но много раз терпел неудачу.Любая помощь с благодарностью.

модели:

class User < ActiveRecord::Base
  has_one :membership, :dependent => :destroy
  accepts_nested_attributes_for :membership, :allow_destroy => true  
end

class Membership < ActiveRecord::Base
  default_scope :conditions => {:active => 1}
  belongs_to :user
end

Ответы [ 4 ]

1 голос
/ 26 октября 2010

У меня есть довольно элегантное решение. Вот ваша модель пользователя:

class User < ActiveRecord::Base
  has_one :membership, :dependent => :destroy
  accepts_nested_attributes_for :membership

  def update_membership_with_history attributes
    self.membership.attributes = attributes
    return true unless self.membership.changed?

    self.membership.update_attribute(:active, false)
    self.build_membership attributes

    self.membership.save
  end
end

Этот метод update_membership_with_history позволяет нам обрабатывать измененные или неизмененные записи. Следующая модель членства:

class Membership < ActiveRecord::Base
  default_scope :conditions => {:active => true}
  belongs_to :user
end

Я немного изменил это, поскольку active должен быть логическим, а не 1 и 0. Обновите вашу миграцию, чтобы соответствовать. Теперь действие обновления, которое является единственной частью вашего леса, которое нужно изменить:

  def update
    @user = User.find(params[:id], :include => :membership)
    membership_attributes = params[:user].delete(:membership_attributes)

    if @user.update_attributes(params[:user]) && @user.update_membership_with_history(membership_attributes)
      redirect_to users_path
    else
      render :action => :edit
    end
  end

Мы просто анализируем атрибуты членства (так что вы можете использовать fields_for в своем представлении) и обновляете их отдельно, и только при необходимости.

0 голосов
/ 26 октября 2010

Почему бы вам просто не предположить, что последнее членство является активным. Это избавит вас от головной боли.

class User < ActiveRecord::Base
  has_many :memberships, :dependent => :destroy
end

class Membership < ActiveRecord::Base
  nested_scope :active, :order => "created_at DESC", :limit => 1
  belongs_to :user

  def update(attributes)
    self.class.create attributes if changed?
  end
end

тогда вы можете использовать

@user.memberships.active

, чтобы получить активное членство, и вы можете просто обновить любое членство, чтобы получить новое членство, которое станет активным членством, поскольку оно самое последнее.

0 голосов
/ 26 октября 2010

Получил это работает. Хотя это, вероятно, не самая лучшая реализация, все мои тесты проходят. Спасибо за вклад, ребята.


  before_save :soft_delete_changed_membership

  def soft_delete_changed_membership
    if !membership.nil? then
      if !membership.new_record? && membership.trial_expire_at_changed? then
        Membership.update_all( "active = 0", [ "id = ?", self.membership.id ] )
        trial_expire_at = self.membership.trial_expire_at
        self.membership = nil
        Membership.create!( 
          :user_id => self.id, 
          :trial_expire_at => trial_expire_at, 
          :active => true 
        )
        self.reload
      end
    end
  end
0 голосов
/ 26 октября 2010

Вы смотрели на acts_as_versioned before_save из Membership вы можете создать новую версию User, которая будет acts_as_versioned.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...