【问题标题】:Accessing model attributes from module method从模块方法访问模型属性
【发布时间】:2021-02-05 16:44:57
【问题描述】:

我知道有一些宝石可以让你开箱即用。不过,我认为做类似的事情是一种很好的学习方式。

由于我在多个模型中使用 slug,我决定创建一个模块并通过 ActiveSupport::Concern 包含它。

这是我的模块sluggable.rb:

module Sluggable
    extend ActiveSupport::Concern

    module ClassMethods
        def slug(*atts_to_slug)
            after_validation set_slug(atts_to_slug)
        end

        def set_slug(atts)
            slug_string = atts.map{|f| f.parameterize}.join("-")
            # Then I would think I can do something like:
            # model_instance.send("slug", slug_string)
        end
    end
end

那我想在模型中做这样的事情:

class Classification < ApplicationRecord
    include Sluggable

    slug :name, :street
end

我发现的问题是:

如何在模块中设置模型的属性slug

【问题讨论】:

    标签: ruby-on-rails ruby


    【解决方案1】:

    after_validation 是一个回调,它需要方法名称、块或可调用对象 (proc/lambda)。

    您当前使用它的方式。它会在首次调用 slug 时调用一次 set_slug 而不是之后。

    slug 应该将所需的属性设置为某个(类级别)变量。 after_validation 应该调用应该是实例方法的 set_slug 方法。然后在set_slug 实例方法中,您可以访问所有属性。

    module Sluggable
      extend ActiveSupport::Concern
    
      module ClassMethods
        def slug(*atts_to_slug)
          @atts_to_slug = atts_to_slug
        end
    
        def atts_to_slug
          @atts_to_slug
        end
      end
    
      included do # instance scope
        after_validation :set_slug
    
        def set_slug
          slug_string = self.class.atts_to_slug.map do |f|
            # send since we're in the instance and I want to just call `name`
            public_send(f).parameterize
          end.join("-")
          self.slug = slug_string
        end
      end
    end
    

    【讨论】:

      猜你喜欢
      • 2013-11-23
      • 2012-02-06
      • 2020-05-07
      • 1970-01-01
      • 1970-01-01
      • 2020-10-17
      • 1970-01-01
      • 2012-03-19
      • 1970-01-01
      相关资源
      最近更新 更多