Rails 3 has_one / belongs_to与子目录中的model关系

时间:2012-08-22 20:47:58

标签: ruby-on-rails-3 migration belongs-to subdirectory has-one

我正在尝试创建一个简单的关系,但在Rails 3.2下的子目录中有一个模型

我有一个User类,每个用户都有一个电子邮件订阅..因为会有其他类型的订阅(也填充添加到用户)我把它们放在一个子目录中。 (我的用户恰好来自Devise,但我怀疑这无所谓。)

这是代码

model/user.rb

class User < ActiveRecord::Base
  has_one :email_sub

  before_create :build_email_subscription

  private

  def build_email_subscription
    Subscription::EmailSub.create(:is_subscribed => true, :user_id => self.id)
    true
  end
end

请注意,我还创建了一种添加默认订阅的方法。

model/subscriptions/email_sub.rb

class Subscriptions::EmailSub < ActiveRecord::Base
  belongs_to :user
end

除了创建这两个类的迁移之外,我还为该关系创建了以下迁移。

class AddSubscriptionToUser < ActiveRecord::Migration
  def change_table :subscriptions_email_sub do |t|
    t.referneces :users
  end
end

但是,这似乎不起作用。它似乎没有生成user_id列。

2 个答案:

答案 0 :(得分:1)

看起来我得到了它的工作。我正在分享和注释我的结果,供其他人学习。

model/user.rb

class User < ActiveRecord::Base
  has_one :email_sub, :class_name => "Subscriptions::EmailSub"

  before_create :build_email_subscription

  private

  def build_email_subscription
    build_email_sub(:announcements => true, :notifications => true, :master => true)
    true
  end
end

我明确地包含class_name以在子目录中找到模型。我使用了build_<attribute>并传递了三个订阅的参数(稍后从表单中进入,但现在只是设置默认值)。

model/subscriptions/email_sub.rb

class Subscriptions::EmailSub < ActiveRecord::Base
  attr_accessible :announcements, :daily_deals, :master
  belongs_to :user
end

(我将这些属性排除在上面,因为它们与问题并不相关,但我会明确地将它们包含在这里以供初学者使用。)

我修改了EmailSubs模型的原始迁移,而不是新的迁移。

class CreateSubscriptionsEmailSubs < ActiveRecord::Migration
  def change
    create_table :subscriptions_email_subs do |t|
      t.boolean :master
      t.boolean :daily_deals
      t.boolean :announcements

      t.references :user    # I added this line to the generated migration
      t.timestamps
    end
  end
end

我添加了t.references行。请注意,我之前有多个而不是单数(在迁移中,表名需要为复数,字段为单数)。 t.references将知道查找给定的_id字段。

希望这可以帮助他人节省一些时间。

答案 1 :(得分:0)

我会重做您设置模型的方式。我认为尝试编辑rails自动创建的关系表是不错的做法。

对于您的模型user.rb

class User < ActiveRecord::Base
    has_many :subscriptions
    // Put whatever before_create logic here if that's still working correctly
end

将subscription.rb更改为:

class Subscription < ActiveRecord::Base
    belongs_to :user
    belongs_to :subscription_type
end

然后创建另一个模型subscription_type.rb

class SubscriptionType < ActiveRecord::Base
    has_many :subscriptions
end

此模型将包含3列:id,subscription_id和subscription_type_id(可能还有列subscription_type_name)。然后使subscription_type_id为1的约定是电子邮件订阅,2是杂志订阅或其他等等。或者,您可以在订阅模型中添加subscription_type列。

为了更轻松地查看模型中的列,请使用annotate gem,这是how to use的快速教程