`
jlaky
  • 浏览: 42875 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Rails tips (1) dependent 设置问题

阅读更多

 

has_many has_one belongs_to都有设置dependent属性

 

has_many的文档里写的dependent是设置为:destroy将调用关联对象destroy方法,如果设置为:delete_all将调用class.delete_all而不调用destroy方法,:nullify就是直接将外键设为null.

 

has_one的文档里写的dependent是设置为:destroy将调用关联对象destroy方法,如果设置为:delete将调用class.delete而不调用destroy方法,:nullify就是直接将外键设为null.

 

belongs_to的文档里写的dependent是设置为:destroy将调用关联对象destroy方法,如果设置为:delete将deleted而不调用destroy方法.

 

 

 

继续查源代码了解清楚一点:

 

1) has_many的源代码

 

def has_many(association_id, options = {}, &extension)
        reflection = create_has_many_reflection(association_id, options, &extension)

        configure_dependency_for_has_many(reflection)
        ...
      end
 

 

        # delete children, otherwise foreign key is set to NULL.
        def configure_dependency_for_has_many(reflection)
          if reflection.options.include?(:dependent)
            # Add polymorphic type if the :as option is present
            dependent_conditions = []
            dependent_conditions << "#{reflection.primary_key_name} = \#{record.quoted_id}"
            dependent_conditions << "#{reflection.options[:as]}_type = '#{base_class.name}'" if reflection.options[:as]
            dependent_conditions << sanitize_sql(reflection.options[:conditions]) if reflection.options[:conditions]
            dependent_conditions = dependent_conditions.collect {|where| "(#{where})" }.join(" AND ")

            case reflection.options[:dependent]
              when :destroy # 一个个用destroy删除
                method_name = "has_many_dependent_destroy_for_#{reflection.name}".to_sym
                define_method(method_name) do
                  send("#{reflection.name}").each { |o| o.destroy }
                end
                before_destroy method_name
              when :delete_all # 用delete_all指令删除,hook proc到before_destroy
                module_eval "before_destroy { |record| #{reflection.class_name}.delete_all(%(#{dependent_conditions})) }"
              when :nullify # 用update_all指令更新为null,hook proc到before_destroy
                module_eval "before_destroy { |record| #{reflection.class_name}.update_all(%(#{reflection.primary_key_name} = NULL),  %(#{dependent_conditions})) }"
              else
                raise ArgumentError, "The :dependent option expects either :destroy, :delete_all, or :nullify (#{reflection.options[:dependent].inspect})"
            end
          end
        end

 

如果只是简单的关联,has_many的delete_all方法会比destroy效率高不少,destroy是一个n+1查询。

实践证明其实对于大表的删除,最好不使用dependent属性,性能问题迟早会找上来 

 

2) has_one的源代码:

 

def has_one(association_id, options = {})
    ...
    configure_dependency_for_has_one(reflection)
end
 

 

        def configure_dependency_for_has_one(reflection)
          if reflection.options.include?(:dependent)
            case reflection.options[:dependent]
              when :destroy # 创建destroy关联方法,hook到before_destroy 
                method_name = "has_one_dependent_destroy_for_#{reflection.name}".to_sym
                define_method(method_name) do
                  association = send("#{reflection.name}")
                  association.destroy unless association.nil?
                end
                before_destroy method_name
              when :delete # 创建delete关联方法,调用类的delete(id)方法,hook到before_destroy 
                method_name = "has_one_dependent_delete_for_#{reflection.name}".to_sym
                define_method(method_name) do
                  association = send("#{reflection.name}")
                  association.class.delete(association.id) unless association.nil?
                end
                before_destroy method_name
              when :nullify # 调用record.update(attr,nil),hook到before_destroy 
                method_name = "has_one_dependent_nullify_for_#{reflection.name}".to_sym
                define_method(method_name) do
                  association = send("#{reflection.name}")
                  association.update_attribute("#{reflection.primary_key_name}", nil) unless association.nil?
                end
                before_destroy method_name
              else
                raise ArgumentError, "The :dependent option expects either :destroy, :delete or :nullify (#{reflection.options[:dependent].inspect})"
            end
          end
        end

 

3) belongs_to相关源代码:

 

def belongs_to(association_id, options = {})
    ...
    configure_dependency_for_belongs_to(reflection)
end

 

 

        def configure_dependency_for_belongs_to(reflection)
          if reflection.options.include?(:dependent)
            case reflection.options[:dependent]
              when :destroy # 直接调用destroy删除,hook到before_destroy 
                method_name = "belongs_to_dependent_destroy_for_#{reflection.name}".to_sym
                define_method(method_name) do
                  association = send("#{reflection.name}")
                  association.destroy unless association.nil?
                end
                before_destroy method_name
              when :delete #调用类方法的delete(id)删除,hook到before_destroy
                method_name = "belongs_to_dependent_delete_for_#{reflection.name}".to_sym
                define_method(method_name) do
                  association = send("#{reflection.name}")
                  association.class.delete(association.id) unless association.nil?
                end
                before_destroy method_name
              else
                raise ArgumentError, "The :dependent option expects either :destroy or :delete (#{reflection.options[:dependent].inspect})"
            end
          end
        end

 

 

分享到:
评论

相关推荐

    rails-settings, 使用 Ruby on Rails 管理设置.zip

    rails-settings, 使用 Ruby on Rails 管理设置 Rails的设置 ruby gem,通过在单独的数据库表中将它们存储为序列化的哈希来处理。 包含命名空间和默认值。要求ruby 1.9.3或者更高版本Rails 3.1或者更高版本( 包括 ...

    Rails Tips: Rails docs with Jamis template

    附上Jamis的rdoc模板文件,tar解压即可。 博文链接:https://lgn21st.iteye.com/blog/199681

    Rails的中文乱码问题

    标题中的“Rails的中文乱码问题”涉及到的是在使用Ruby on Rails框架开发Web应用时,遇到的中文字符编码不正确的问题。Rails是一个基于Ruby语言的开源Web开发框架,它遵循MVC(Model-View-Controller)架构模式。在...

    rails-practice-dependent-destroy

    Rails 实践 设置 分叉并克隆存储库 安装 gems - bundle 设置数据库 - rake db:create db:migrate db:seed 启动服务器 - rails s 您可以使用以下命令运行规范: rspec 注意:由rake db:seed填充的现有用户的电子...

    bower-rails, 在 Rails 上,为 Bower 设置类似 DSL + rake任务.zip

    bower-rails, 在 Rails 上,为 Bower 设置类似 DSL + rake任务 rails Bower 对 Rails 项目的支持。 依赖文件是 Rails root 目录中的bower.json,如果使用 DSL,则为 Bowerfile 。 查看最新变更和发布的变更日志文件...

    chef-rails, 厨房设置一个可以与 Nginx 和 Rails 一起滚动的Ubuntu服务器.zip

    chef-rails, 厨房设置一个可以与 Nginx 和 Rails 一起滚动的Ubuntu服务器 主厨 rails安装一个准备为 Ruby on Rails 栈准备的Ubuntu服务器:NginxPostgreSQLRedisMemcached带RVM的rubyPhusion乘客独立要求Ubuntu ...

    Rails 101 入门电子书

    #### 七、练习作业1-建立Group-CRUD与RESTful - **CRUD操作**: - Create (创建): 创建新的Group对象。 - Read (读取): 显示Group的信息。 - Update (更新): 修改Group的信息。 - Delete (删除): 删除Group。 - ...

    Rails101_by_rails4.0

    此外,书中还介绍了一些Rails中的高级概念,如Strong Parameters(强参数),它在Rails 4.0版本中引入,用于解决之前版本中的参数篡改问题,从而帮助开发者安全地处理外部提交的数据。 通过一系列的教学内容,包括...

    Rails项目源代码

    1. **Rails框架基础**: Rails的核心理念是DRY(Don't Repeat Yourself),它鼓励开发者编写简洁、可复用的代码。框架提供了丰富的内置功能,如路由、ORM(对象关系映射)、数据库迁移和强大的脚手架工具,帮助快速...

    Rails

    1. **约定优于配置**(Convention Over Configuration):Rails通过默认的约定减少开发者需要明确配置的细节,如数据库表名与类名的对应关系。 2. **Active Record**:这是Rails中的ORM(对象关系映射)库,它允许...

    Ruby on Rails安装指南(Ruby 1.8.6+Rails 2.0.2)

    知识点1:Ruby 安装 * 下载 Ruby One-Click Installer 版本 * 安装 Ruby * 检查 Ruby 版本 知识点2:Rails 安装 * 下载 Rails 2.0.2 版本 * 安装 Rails * 检查 Rails 版本 知识点3:Mongrel 安装 * 下载 ...

    使用Aptana+Rails开发Rails Web应用(中文)

    例如,要在Rails应用中创建一个新的资源,如博客文章,你需要在models目录下创建一个名为`post.rb`的文件,定义Post类,并设置属性如标题和内容。在controllers目录下创建`posts_controller.rb`,定义控制器方法,如...

    rails2-sample

    从给定的文件信息来看,我们正在探讨的是一本关于Ruby on Rails的书籍,书名为《Simply Rails2》,作者是Patrick Lenz。本书旨在为初学者提供深入理解Ruby on Rails框架的指南,从基础概念到高级主题均有涵盖,是...

    rails和mysql数据库连接中出现的问题以及解决办法

    然而,有时在尝试连接Rails应用到MySQL数据库时,可能会遇到一些问题。本篇文章将深入探讨这些常见问题及其解决方案。 首先,Rails与MySQL的连接问题可能源于配置不正确。在`config/database.yml`文件中,你需要...

    Advanced Rails

    1. **优化性能**:Rails应用在处理大量请求时可能会面临性能挑战。书中会介绍如何通过缓存(如Action Cache和Page Cache)、数据库查询优化、资产管道优化等手段提升应用性能。 2. **复杂的路由**:Rails的路由系统...

    关于rails 3.1 cucumber-rails 1.2.0

    Rails 3.1 和 Cucumber-Rails 1.2.0 是两个在Web开发领域非常重要的工具,尤其对于Ruby on Rails框架的测试和自动化流程。本文将深入探讨这两个组件,以及它们如何协同工作来增强软件开发的效率和质量。 首先,...

    Rails recipes

    Rails Recipes是一本针对Ruby on Rails框架的实用书籍,它收集了一系列高效解决问题的技巧和方法,也被称为“Rails开发者的宝典”。作者们通过分享自己的经验和见解,为Rails程序员提供了一本既有实际操作指导又有...

    rails本地安装包完整版

    1. **activesupport-2.1.0.gem**:ActiveSupport是Rails的一个重要库,提供了许多实用的工具和方法,如时间区处理、字符串格式化、数组和哈希操作等。它也包含了一些核心的Ruby扩展,帮助开发者编写更简洁、更具表达...

Global site tag (gtag.js) - Google Analytics