`
yangzhihuan
  • 浏览: 165786 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

对于model是全部放在model下面,还是应该分开包来管理的疑问

阅读更多

ruby和rails的文章看了不少.不过都没有看到过讲述如何在rails下面,按模块来分类model的资料(比如像java那样用包来分类java文件,呵呵 ...我是一个java程序员).

我也试了一下把不同功能的model放在model(rails默认的)文件夹下面的子文件夹(模块,也是包),也是可以成功的,不过这样做的话,rails的约定高于配置就用不上了,因为要自己指定各个类的class.比如:

has_one :my_test,:class_name => 'Content::MyTest'

 这样.

我觉得这样比较不爽.

 

另外,

include Human

这样的代码在model和controller里面似乎并不起它就有的作用.比如:我有一Human::User的类,在controll入er里面加

include Human
,再使用
User.new

 这样的代码就会出错,提示也就是说找不到User类云云....

 

最后的感觉就是,rails的约定优于配置思想,确实是还来了好多方便,不过有时候未免不能随心所欲.

呵呵 ...... 也许是我强求了.

 

 

 

分享到:
评论
25 楼 liusong1111 2008-04-24  
pig345 写道
如果问题是:
liusong1111 写道

class A
end

module C
  module A
    class B
      # use class A
    end
  end
end



那么,考虑下:

ruby存在的时间比java更久,这么基础的问题(严重点说——缺陷)难道只有咱们碰到过?

或者是ruby社区长久以来对此一直视而不见???这、这ruby还能用么。。。




先放两句大话,呵呵,其实也是最近才找到解决方法,分享下:

class A
  def self.who?
    puts self
  end
end

module C
  module A
    class B
      def self.ask_A
        A.who? 
        ::A.who?
      end
    end
    def self.who?
      puts self
    end
  end
end

C::A::B.ask_A


irb里面实验下看看?


我前面的想法跟你所说没有冲突,我当时的思路还不清晰。
不是ruby的问题,而是直接依赖rails的自动加载机制不行,从理论上说,也无法解决。
假设你上面代码,class A定义在a.rb中,module C定义在c.rb中。c.rb没有显式require 'a.rb',我们假定事先加载了rails(或具体的active_support)。
module C中那行A.who? ,因为查找时先找到了module A,所以就用了它。而我本期望它会自动加载a.rb,使用class A的。由于提前找到const(module A)而短路了自动加载机制的const_missing,所以依赖这种加载的自动化不行。
解决方式有两种,一是手工require 'a.rb',并像你上面::A这样用。二是用model :a的声明。第二种方式我没有查看它的源码,大致推想它直接找到models目录的文件加载,跟第一种方法本质一样。

结论是:不是加载不到,而是不能自动加载到。
24 楼 blogbin 2008-03-18  
不过migrate无法支持按模块创建目录,所有的migratee都会放在一个db/migrate目录下。
习惯了java的package管理,感觉ruby or rails在这方面比较别扭。
23 楼 magicgod 2008-03-16  
2.0已经有了命名空间,例如:
ruby script/generate model Admin::User


这样将会生成
      create  app/models/admin
      create  test/unit/admin
      create  test/fixtures/admin
      create  app/models/admin/user.rb
      create  test/unit/admin/user_test.rb
      create  test/fixtures/admin_users.yml
      exists  db/migrate
      create  db/migrate/002_create_admin_users.rb


controller也可以。
22 楼 lllyq 2008-03-10  
我测试了一下,还有一个model不放在根下,要求跟control,helper的分层一致的理由
我用rspec,如果不一致,generate出来的代码还需要手工改,很麻烦,一致就没问题,例如都在users层(module)下,ruby script/generate rspec_controller users\user
21 楼 carlosbdw 2008-03-07  
希望rails能把controller分成两类:

1,主表维护
2,业务操作
20 楼 pig345 2008-03-07  
其实说严重点,这可以算ruby的一个语法陷阱,一般人很难会把所有使用类的地方都写上全路径,因此“写ruby第一要注意的就是:想尽一切办法避免重名”仍然是需要时刻提醒自己的。
19 楼 pig345 2008-03-07  
如果问题是:
liusong1111 写道

class A
end

module C
  module A
    class B
      # use class A
    end
  end
end



那么,考虑下:

ruby存在的时间比java更久,这么基础的问题(严重点说——缺陷)难道只有咱们碰到过?

或者是ruby社区长久以来对此一直视而不见???这、这ruby还能用么。。。




先放两句大话,呵呵,其实也是最近才找到解决方法,分享下:

class A
  def self.who?
    puts self
  end
end

module C
  module A
    class B
      def self.ask_A
        A.who?
        ::A.who?
      end
    end
    def self.who?
      puts self
    end
  end
end

C::A::B.ask_A


irb里面实验下看看?
18 楼 liusong1111 2008-03-06  
rails的自动加载机制源码在active_support的dependencies.rb,Waves框架的创始人说他的更好,抽成了一个叫autocode的gem: http://rubyforge.org/projects/autocode/

本质都是重写const_missing,难点是在重新加载文件之前需要卸载干净(remove_const)以前的const定义,否则在内存中相当于在老的const定义基础上合并了新的定义,会造成一些不可预期的问题 -- 比如重新加载的文件中对类A加了方法a,重定义了方法b,删了方法c,在运行过程中发现a,b都正确了,c居然还存在。由于const的定义本质是在执行过程中动态加入的,可以做到很灵活的添加const,没有机制标记某个const就是对应在哪个文件中创建的,所以需不需要以及如何标记哪些const可以被reload也是问题。rails于是约定了自动加载的类和其文件名/路径的对应关系(ruby语言本身没有这种强性要求)。

autocode的代码比rails清晰多了。
17 楼 seemoon 2008-03-06  
刚接触ruby没多少天,由于之前是用java的,觉得ruby在命名空间似乎处理得不如java那般明确,加上rails隐藏了很多类加载的机制和潜规则,所以如何来合理组织一个代码项目结构似乎成为了ror开发要解决的一大问题。不知道做过项目的同学能不能共享一下经验?
16 楼 liusong1111 2008-03-06  
pig345 写道
liusong1111 写道
按模块划分代码时,感觉rails的支持不是很完美。
如lgn21st所说,有时需要了解一些深层的原理,比如module和class在ruby中都是constant等。
module名和model名相同时也可能产生问题,比如有/controllers/admin/account_controller.rb和/models/admin.rb, 在account_controller里使用类似Admin.find(:all)时它会报错: Admin没有find方法。
这是因为在account_controller.rb在定义了Admin::AccountController,即module Admin和其下的class AccountController,而在admin.rb定义了class Admin,两个地方都定义了constant叫Admin,以哪个为准,取决于ruby查找constant的机制,ruby不同版本间也可能有差异,是不是还跟文件加载顺序相关我不清楚,对于这种情况我们用了rails2.0里已经去掉的model :admin声明,保证在controller里能正确加载使用model admin。--而不是直接找到它上层的module而绕过rails自动加载机制的const_missing。

写ruby第一要注意的就是“想尽一切办法避免重名”,不论是类/模块,还是方法/变量。。。
否则有你忙活的时候。


我们也在尽力避免重复和二义性情况的出现,能把类、模块、方法、变量的名字起到刻骨的好的程度,就是优秀设计的显著的外在表现,可世事难预料啊,呵呵~
ruby的module用于持有一些独立功能,它有两个职责:mixin和namespace,两者在原理上并没有明显的界限,前者重在功能动态增强,后者重在功能静态隔离,在实际使用中有可能重点使用职责之一。
ajoo老大前面的贴子提出当module作为namespace职责时表达形式不直观,我现在的问题是namespace的名字和类的名字冲突了,在java里package是小写,类名是大写,文件名/路径 与 package/class名字强制保持一致,ruby把namespace(module)和class都作为constant看待,rails重载const_missing实现自动加载,这是两者的不同,对于java来说这种问题就不容易出现。
namespace和class不应该重名吗?
以java的经验看,重名是可以理解的。以ruby实现的角度看,有潜在问题。
我现在也只好记着这个技术约束,注意父模块和同级的类重名的问题~

---
写ruby第一要注意的就是“想尽一切办法避免重名”,--- 我刚刚体会到你这句话的意思,对,深有体会,重名时执行的先后顺序决定最终结果,可能导致诡异的问题,动态性真是个双刃剑。我上面的问题跟这还有些区别:

class A
end

module C
  module A
    class B
      # use class A
    end
  end
end

15 楼 fiyuer 2008-03-06  
model比较多时可以放在多个目录下,只要在environment.rb下设置一下就可以直接拿过来用了

Rails::Initializer.run do |config|
  config.load_paths += Dir["#{RAILS_ROOT}/app/models/[a-z]*"]
end

[ "app/models" ].each do |path|
  Dir["#{RAILS_ROOT}/#{path}/**/*.rb"].each{|file|
    load file
  }
end
14 楼 lllyq 2008-03-06  
除了model,其他的controllers/services/helpers你都可以分层,就像java Package一样的,rails的classloader机制可以让你同一个module下不需require,所以只要分层一样用起来也很方便,这样也可以避免一些同名问题
13 楼 pig345 2008-03-06  
liusong1111 写道
按模块划分代码时,感觉rails的支持不是很完美。
如lgn21st所说,有时需要了解一些深层的原理,比如module和class在ruby中都是constant等。
module名和model名相同时也可能产生问题,比如有/controllers/admin/account_controller.rb和/models/admin.rb, 在account_controller里使用类似Admin.find(:all)时它会报错: Admin没有find方法。
这是因为在account_controller.rb在定义了Admin::AccountController,即module Admin和其下的class AccountController,而在admin.rb定义了class Admin,两个地方都定义了constant叫Admin,以哪个为准,取决于ruby查找constant的机制,ruby不同版本间也可能有差异,是不是还跟文件加载顺序相关我不清楚,对于这种情况我们用了rails2.0里已经去掉的model :admin声明,保证在controller里能正确加载使用model admin。--而不是直接找到它上层的module而绕过rails自动加载机制的const_missing。

写ruby第一要注意的就是“想尽一切办法避免重名”,不论是类/模块,还是方法/变量。。。
否则有你忙活的时候。
12 楼 yangzhihuan 2008-03-03  
如果model比较多,有100来个,那么全部放到models目录下,估计也是相当的壮观,找起来嘛,呵呵...更加是不用说了.
不过我暂时没有这么多model,所以暂时没有这个烦恼.

多谢大家热烈的讨论.....
11 楼 liusong1111 2008-03-03  
我们的controller组织在多层module/目录下,把model全部放在/models下,效果不错。
10 楼 liusong1111 2008-03-03  
按模块划分代码时,感觉rails的支持不是很完美。
如lgn21st所说,有时需要了解一些深层的原理,比如module和class在ruby中都是constant等。
module名和model名相同时也可能产生问题,比如有/controllers/admin/account_controller.rb和/models/admin.rb, 在account_controller里使用类似Admin.find(:all)时它会报错: Admin没有find方法。
这是因为在account_controller.rb在定义了Admin::AccountController,即module Admin和其下的class AccountController,而在admin.rb定义了class Admin,两个地方都定义了constant叫Admin,以哪个为准,取决于ruby查找constant的机制,ruby不同版本间也可能有差异,是不是还跟文件加载顺序相关我不清楚,对于这种情况我们用了rails2.0里已经去掉的model :admin声明,保证在controller里能正确加载使用model admin。--而不是直接找到它上层的module而绕过rails自动加载机制的const_missing。
9 楼 lllyq 2008-03-03  
我测试了,先include module再直接调用module下class是可以的,而且不同位置的同名module可以merge

不过activerecord这个问题估计难以解决,恐怕只能加class_name
8 楼 liusu 2008-03-02  
一直对Python,Ruby等语言的源码组织方法没有个好的办法。
因为做实际的项目从Java开始,习惯了Java的源码组织方法,呵呵
7 楼 lgn21st 2008-03-02  
在Ruby中,类名跟Java中的类名引用机制不同,Ruby的类名其实就是一个constant常量,模块名也是,跟在其他地方定义的常量一样,也就是说,你可以这样写
Book = Demo1::Book
@book = Book.new
不过我相信一旦习惯了ruby这种路子以后,就不会在觉得写Demo1::Book.new是很烦的事情了,因为看着直观哪.
6 楼 yangzhihuan 2008-03-02  
其实无他,我只是觉得
@book = Demo1::Book.new 

这样写有些长而已,我之前一直是搞java的,习惯了import一个包进来,然后就写一个类名.
不管怎么样,多谢lgn21st .

相关推荐

Global site tag (gtag.js) - Google Analytics