论坛首页 编程语言技术论坛

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

浏览 10720 次
该帖已经被评为良好帖
作者 正文
   发表时间:2008-03-01  

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的约定优于配置思想,确实是还来了好多方便,不过有时候未免不能随心所欲.

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

 

 

 

   发表时间:2008-03-01  
ruby module又不是java的package,import一下就可以不写package name了
多写个class_name又怎么了?
0 请登录后投票
   发表时间:2008-03-01  
建模要适度,OO别滥用
0 请登录后投票
   发表时间:2008-03-01  
按模块来分类model其实是有的,只是楼主还没有完全理解rails的autoloading-class机制

比如在"app/model"下,建立一个文件夹"demo",在下面创建两个模型
# model class
class Demo::Public < ActiveRecord::Base
  has_many :books
end
class Demo::Book < ActiveRecord::Base
  belongs_to :public
end

# migration script:
  def self.up
    create_table :publics do |t|
      t.string :name
    end
    create_table :books do |t|
      t.integer :public_id
      t.string :title
    end
  end

  def self.down
    drop_table :publics
    drop_table :books
  end


可以用console测试,两个model工作完全正常,因为两个模型在一个scope内,所以不需要class_name来指定类名,classload会优先在本地scope中查找class:
> public1 = Demo::Public.new(:name => "O'Reilly")
=> #<Demo::Public id: nil, name: "O'Reilly">
> public1.books << Demo::Book.new(:title => "Ruby CookBook")
=> [#<Demo::Book id: nil, public_id: nil, title: "Ruby CookBook">]
> public1.save
  Demo::Public Create (0.000635)   INSERT INTO publics ("name") VALUES('O''Reilly')
  Demo::Book Create (0.000202)   INSERT INTO books ("title", "public_id") VALUES('Ruby CookBook', 1)
=> true


rails对ruby的类加载机制作了增强,引用The rails way上的解释:
引用

• If the class or module is not nested, insert an underscore between the constant’s
  names and require a file of this name. For example:
    • EstimationCalculator becomes require ‘estimation_calculator’
    • KittTurboBoost becomes require ‘kitt_turbo_boost’
• If the class or module is nested, Rails inserts an underscore between each of the
  containing modules and requires a file in the corresponding set of subdirectories.
  For example:
    • MacGyver::SwissArmyKnife becomes require ‘mac_gyver/swiss_army_knife’

• Some::ReallyRatherDeeply::NestedClass becomes require ‘some/
  really_rather_deeply/nested_class’ and if not already loaded, Rails
  would expect to find it in a file called nested_class.rb, in a directory called
  really_rather_deeply, itself in the directory some of which can be found
  somewhere in Ruby’s load path (e.g., one of the app subdirectories, lib, or a plu-
  gin’s lib directory).


其实rails做的比你想像的要多,一旦理解,一切均变得理所当然
0 请登录后投票
   发表时间:2008-03-01  
多谢 lgn21st  的回复.可能是我没有描述明白我的问题吧.我建立的两个model不是在同一个名称空间下的.引用你的例子吧.假如在app/model下面,有两个文件夹,一个是demo1,一个是demo2,现在有两个model
 class Demo1::Public < ActiveRecord::Base  
  has_many :books  
 end  
 class Demo2::Book < ActiveRecord::Base  
  belongs_to :public  
 end

不知道又当如何呢?

另外如果我要在controller里面引用这两个model,以下的代码:
#test_controller.rb
class  Test < ApplicationController
include Demo1
  def index
        @book = Book.new
  end

end

肯定是错的.但是我又不想把代码写成:
  @book = Demo1::Book.new

我真的没能弄明白rails到底是怎么搞的.
0 请登录后投票
   发表时间:2008-03-02  
能告诉我你为什么不愿意写这样?
@book = Demo1::Book.new
或者实在是对rails的规则不满意,可以操刀改rails的classload的enhance部分吧
0 请登录后投票
   发表时间:2008-03-02  
其实无他,我只是觉得
@book = Demo1::Book.new 

这样写有些长而已,我之前一直是搞java的,习惯了import一个包进来,然后就写一个类名.
不管怎么样,多谢lgn21st .
0 请登录后投票
   发表时间:2008-03-02  
在Ruby中,类名跟Java中的类名引用机制不同,Ruby的类名其实就是一个constant常量,模块名也是,跟在其他地方定义的常量一样,也就是说,你可以这样写
Book = Demo1::Book
@book = Book.new
不过我相信一旦习惯了ruby这种路子以后,就不会在觉得写Demo1::Book.new是很烦的事情了,因为看着直观哪.
0 请登录后投票
   发表时间:2008-03-02  
一直对Python,Ruby等语言的源码组织方法没有个好的办法。
因为做实际的项目从Java开始,习惯了Java的源码组织方法,呵呵
0 请登录后投票
   发表时间:2008-03-03  
我测试了,先include module再直接调用module下class是可以的,而且不同位置的同名module可以merge

不过activerecord这个问题估计难以解决,恐怕只能加class_name
0 请登录后投票
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics