在Rails模型中使用多个with_options

时间:2014-11-07 22:58:29

标签: ruby-on-rails ruby

有一个模型。我希望有多个with_options语句,并根据save之前的一些内部标志执行一些操作。这是一个类,例如:

class User < ActiveRecord::Base

  with_options if: :with_password do |record|
    # some validation and before_filter stuff
  end

  with_options if: :resetting_password do |record|
    # some other validation and before_filter stuff
  end

  def save_with_password
    self.with_password = true
    save
  end

  def reset_password
    self.resetting_password = true
    assign_attributes(password: DEFAULT_PASSWORD)
    save
  end

  private

  attr_accessor :with_password
  attr_accessor :resetting_password

end

此代码无效,因为第一个with_options被第二个with_options覆盖,如果self.with_password == true则第一个with_options未被执行(以及第二个)。

那我怎样才能让它发挥作用呢?

---更新

以下是with_options if: :resetting_password低于with_options if: :with_password时通过的测试示例,反之亦然。

describe '#reset_password' do
  let(:instance) { stub_model(described_class, name: 'admin') }
  subject { instance.reset_password }

  it 'sets password to a default one' do
    subject
    expect(instance.has_password?("default")).to eq true
  end

end

Gemfile.lock的:

GEM
  remote: https://rubygems.org/
  specs:
    actionmailer (4.1.1)
      actionpack (= 4.1.1)
      actionview (= 4.1.1)
      mail (~> 2.5.4)
    actionpack (4.1.1)
      actionview (= 4.1.1)
      activesupport (= 4.1.1)
      rack (~> 1.5.2)
      rack-test (~> 0.6.2)
    actionview (4.1.1)
      activesupport (= 4.1.1)
      builder (~> 3.1)
      erubis (~> 2.7.0)
    activemodel (4.1.1)
      activesupport (= 4.1.1)
      builder (~> 3.1)
    activerecord (4.1.1)
      activemodel (= 4.1.1)
      activesupport (= 4.1.1)
      arel (~> 5.0.0)
    activesupport (4.1.1)
      i18n (~> 0.6, >= 0.6.9)
      json (~> 1.7, >= 1.7.7)
      minitest (~> 5.1)
      thread_safe (~> 0.1)
      tzinfo (~> 1.1)
    arel (5.0.1.20140414130214)
    builder (3.2.2)
    chunky_png (1.3.1)
    compass (0.12.7)
      chunky_png (~> 1.2)
      fssm (>= 0.2.7)
      sass (~> 3.2.19)
    compass-rails (2.0.0)
      compass (>= 0.12.2)
    diff-lcs (1.2.5)
    erubis (2.7.0)
    execjs (2.2.0)
    fssm (0.2.10)
    haml (4.0.5)
      tilt
    haml-rails (0.5.3)
      actionpack (>= 4.0.1)
      activesupport (>= 4.0.1)
      haml (>= 3.1, < 5.0)
      railties (>= 4.0.1)
    hike (1.2.3)
    i18n (0.6.9)
    jbuilder (2.1.1)
      activesupport (>= 3.0.0, < 5)
      multi_json (~> 1.2)
    jquery-rails (3.1.1)
      railties (>= 3.0, < 5.0)
      thor (>= 0.14, < 2.0)
    json (1.8.1)
    mail (2.5.4)
      mime-types (~> 1.16)
      treetop (~> 1.4.8)
    mime-types (1.25.1)
    mini_magick (3.8.0)
      subexec (~> 0.2.1)
    mini_portile (0.6.0)
    minitest (5.3.5)
    multi_json (1.10.1)
    nokogiri (1.6.3.1)
      mini_portile (= 0.6.0)
    nokogiri (1.6.3.1-x86-mingw32)
      mini_portile (= 0.6.0)
    polyglot (0.3.5)
    rack (1.5.2)
    rack-test (0.6.2)
      rack (>= 1.0)
    rails (4.1.1)
      actionmailer (= 4.1.1)
      actionpack (= 4.1.1)
      actionview (= 4.1.1)
      activemodel (= 4.1.1)
      activerecord (= 4.1.1)
      activesupport (= 4.1.1)
      bundler (>= 1.3.0, < 2.0)
      railties (= 4.1.1)
      sprockets-rails (~> 2.0)
    railties (4.1.1)
      actionpack (= 4.1.1)
      activesupport (= 4.1.1)
      rake (>= 0.8.7)
      thor (>= 0.18.1, < 2.0)
    rake (10.3.2)
    rdoc (4.1.1)
      json (~> 1.4)
    rspec (3.0.0)
      rspec-core (~> 3.0.0)
      rspec-expectations (~> 3.0.0)
      rspec-mocks (~> 3.0.0)
    rspec-activemodel-mocks (1.0.1)
      activemodel (>= 3.0)
      activesupport (>= 3.0)
      rspec-mocks (>= 2.99, < 4.0)
    rspec-core (3.0.2)
      rspec-support (~> 3.0.0)
    rspec-expectations (3.0.2)
      diff-lcs (>= 1.2.0, < 2.0)
      rspec-support (~> 3.0.0)
    rspec-html-matchers (0.6.1)
      nokogiri (~> 1)
      rspec (~> 3)
    rspec-mocks (3.0.2)
      rspec-support (~> 3.0.0)
    rspec-rails (3.0.1)
      actionpack (>= 3.0)
      activesupport (>= 3.0)
      railties (>= 3.0)
      rspec-core (~> 3.0.0)
      rspec-expectations (~> 3.0.0)
      rspec-mocks (~> 3.0.0)
      rspec-support (~> 3.0.0)
    rspec-support (3.0.2)
    sass (3.2.19)
    sass-rails (4.0.3)
      railties (>= 4.0.0, < 5.0)
      sass (~> 3.2.0)
      sprockets (~> 2.8, <= 2.11.0)
      sprockets-rails (~> 2.0)
    sdoc (0.4.0)
      json (~> 1.8)
      rdoc (~> 4.0, < 5.0)
    sprockets (2.11.0)
      hike (~> 1.2)
      multi_json (~> 1.0)
      rack (~> 1.0)
      tilt (~> 1.1, != 1.3.0)
    sprockets-rails (2.1.3)
      actionpack (>= 3.0)
      activesupport (>= 3.0)
      sprockets (~> 2.8)
    sqlite3 (1.3.9)
    sqlite3 (1.3.9-x86-mingw32)
    subexec (0.2.3)
    thor (0.19.1)
    thread_safe (0.3.4)
    tilt (1.4.1)
    treetop (1.4.15)
      polyglot
      polyglot (>= 0.3.1)
    tzinfo (1.2.1)
      thread_safe (~> 0.1)
    tzinfo-data (1.2014.5)
      tzinfo (>= 1.0.0)
    uglifier (2.5.1)
      execjs (>= 0.3.0)
      json (>= 1.8.0)

PLATFORMS
  ruby
  x86-mingw32

DEPENDENCIES
  compass-rails
  haml-rails (~> 0.5.3)
  jbuilder (~> 2.0)
  jquery-rails
  mini_magick
  rails (= 4.1.1)
  rspec-activemodel-mocks
  rspec-html-matchers
  rspec-rails (~> 3.0.0)
  sass-rails (~> 4.0.3)
  sdoc (~> 0.4.0)
  sqlite3
  tzinfo-data
  uglifier (>= 1.3.0)

1 个答案:

答案 0 :(得分:1)

解决。像这样重写了with_options

class User < ActiveRecord::Base

  with_options if: :with_password do |record|
    # some validation and before_filter stuff
  end

  with_options if: :resetting_password do |record|
    # some other validation and before_filter stuff
  end

  with_options if: ->{ with_password || resetting_password } do |record|
    # some common stuff
  end

end