$cache[$key] = empty($arr) ? NULL : $arr; return $cache[$key]; } // 门户 获取需要在频道显示的栏目主题数据 function portal_channel_thread($fid) { global $forumlist; if (empty($fid)) return NULL; $orderby = array('tid' => 1); $page = 1; // 遍历所有在频道显示内容的栏目 $category_forumlist = channel_category($fid); $arrlist = array(); $forum_tids = array(); $tidlist = array(); if ($category_forumlist) { foreach ($category_forumlist as &$_forum) { // 频道显示数据 $arrlist['list'][$_forum['fid']] = array( 'fid' => $_forum['fid'], 'name' => $_forum['name'], 'rank' => $_forum['rank'], 'type' => $_forum['type'], 'url' => $_forum['url'], 'channel_new' => $_forum['channel_new'], ); $forum_thread = thread_tid__find(array('fid' => $_forum['fid']), $orderby, $page, $_forum['channel_new'], 'tid', array('tid')); // 最新信息按栏目分组 foreach ($forum_thread as $key => $_thread) { $forum_tids[$key] = $_thread; } unset($forum_thread); } $tidlist += $forum_tids; } unset($category_forumlist); // 获取属性对应的tid集合 list($flaglist, $flagtids) = flag_thread_by_fid($fid); empty($flagtids) || $tidlist += $flagtids; unset($flagtids); // 频道置顶 $stickylist = sticky_list_thread($fid); empty($stickylist) || $tidlist += $stickylist; // 在这之前合并所有二维数组 tid值为键/array('tid值' => tid值) $tidarr = arrlist_values($tidlist, 'tid'); // 在这之前使用$tidarr = array_merge($tidarr, $arr)前合并所有一维数组 tid/array(1,2,3) if (empty($tidarr)) { $arrlist['list'] = isset($arrlist['list']) ? array_multisort_key($arrlist['list'], 'rank', FALSE, 'fid') : array(); return $arrlist; } $tidarr = array_unique($tidarr); $pagesize = count($tidarr); // 遍历获取的所有tid主题 $threadlist = well_thread_find_asc($tidarr, $pagesize); // 遍历时为升序,翻转为降序 $threadlist = array_reverse($threadlist); foreach ($threadlist as &$_thread) { // 各栏目最新内容 isset($forum_tids[$_thread['tid']]) AND $arrlist['list'][$_thread['fid']]['news'][$_thread['tid']] = $_thread; // 全站置顶内容 isset($stickylist[$_thread['tid']]) AND $arrlist['sticky'][$_thread['tid']] = $_thread; // 首页属性主题 if (!empty($flaglist)) { foreach ($flaglist as $key => $val) { if (isset($val['tids']) && in_array($_thread['tid'], $val['tids'])) { $arrlist['flaglist'][$key][array_search($_thread['tid'], $val['tids'])] = $_thread; ksort($arrlist['flaglist'][$key]); $arrlist['flag'][$_thread['tid']] = $_thread; } } } } unset($threadlist); if (isset($arrlist['sticky'])) { $i = 0; foreach ($arrlist['sticky'] as &$val) { ++$i; $val['i'] = $i; } } if (isset($arrlist['flag'])) { $i = 0; foreach ($arrlist['flag'] as &$val) { ++$i; $val['i'] = $i; } } if (isset($arrlist['flaglist'])) { foreach ($arrlist['flaglist'] as &$val) { $i = 0; foreach ($val as &$v) { ++$i; $v['i'] = $i; } } } isset($arrlist['list']) AND $arrlist['list'] = array_multisort_key($arrlist['list'], 'rank', FALSE, 'fid'); return $arrlist; } ?>ruby on rails - Accessing class constant from within a module - Stack Overflow
最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

ruby on rails - Accessing class constant from within a module - Stack Overflow

programmeradmin0浏览0评论

I need to access an ActiveRecord constant from an included module in a Rails app.

class User < ApplicationRecord
  include ModOne
  
  OPTIONS = {a: 1}.freeze

  ...
end
Module ModOne
  extend ActiveSupport::Concern

  included do
    do_semething(self::OPTIONS)
  end

  class_methods do
   def do_something(opts)
     ...
   end
  end
end

But I get

NameError: uninitialized constant User (call 'User.connection' to establish a connection)::OPTIONS Did you mean? User::OPTIONS

What am I missing here?

I have also tried to replace self with base_class and event User but I get the same error.

I need to access an ActiveRecord constant from an included module in a Rails app.

class User < ApplicationRecord
  include ModOne
  
  OPTIONS = {a: 1}.freeze

  ...
end
Module ModOne
  extend ActiveSupport::Concern

  included do
    do_semething(self::OPTIONS)
  end

  class_methods do
   def do_something(opts)
     ...
   end
  end
end

But I get

NameError: uninitialized constant User (call 'User.connection' to establish a connection)::OPTIONS Did you mean? User::OPTIONS

What am I missing here?

I have also tried to replace self with base_class and event User but I get the same error.

Share Improve this question asked Feb 6 at 15:38 SigSig 5,95811 gold badges60 silver badges99 bronze badges 3
  • 2 OPTIONS needs to be above the include – Alex Commented Feb 6 at 15:57
  • @Alex, why should it be above? – Sig Commented Feb 6 at 16:02
  • 5 because at the time of include it is not yet defined. order matters. – Alex Commented Feb 6 at 16:03
Add a comment  | 

1 Answer 1

Reset to default 4

It's simply a matter of order. You have to define the constant first. Ruby classes are really just a block of code and run top down and when you call include you're also calling the #included method on the module.

But a better approach if you want the functionality provided by a module to be customizable is to just write a so called macro method instead of hinging everything on the Module#included hook:

# You can obscure this with some syntactic sugar from ActiveSupport::Concern 
# if it makes you happy.
module Awesomeizer
  def foo
    self.class.awesomeize_options[:foo]
  end

  module ClassMethods
    def awesomeize_options
      @awesomeize_options ||= defaults
    end

    def awesomeize(**options) 
       awesomeize_options.merge!(options)
    end 

    def defaults
      {}
    end
  end

  def self.included(base)
    base.extend(ClassMethods)
  end
end

class Thing
  include Awesomeizer
  awesomeize(foo: :bar)
end

This pattern can be found everywhere in Ruby and is great way to get around the fact that Module#include doesn't allow you to pass any additional arguments.

In this example the awesomeize method just stores the options as a class instance variable.

One of the strongest reasons why this is preferable is that it lets you define a signature for the interface between the module and it's consumers instead of just making assumptions. Some gems like Devise even use this method to include it's submodules.

发布评论

评论列表(0)

  1. 暂无评论