foreign_key总是1

时间:2011-02-28 23:56:47

标签: ruby-on-rails

我正在尝试输入外键值以及从表单收集的数据。表单数据提交完美,但外键总是输入为1.我已经尝试了几种输入信息的方法,我当前的创建方法尝试如下:

def create

    @product = Product.new(params[:product])

    @username = User.select("company").where("email= ?", current_user.email.to_s)
    @cid = User.select("id").where("company= ?", @username)

    if @username != nil    
      @product.company_id = @cid
      @product.save 
    end

end

此外,find_by_something(和to_i)方法会抛出No Such Method错误,因此我使用了上述查询语法作为解决方法。如果有人可以解释这一点......

编辑,模型:用户模型:

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :token_authenticatable, :confirmable, :lockable and :timeoutable

  # Setup accessible (or protected) attributes
  attr_accessible :email, :password, :password_confirmation, :remember_me, :company

  validates :company, :presence => true
  devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable, :timeoutable

  after_save :correspond


  def correspond
    c = Company.find_or_create_by_name(self.company)
  end

end

公司型号:

class Company < ActiveRecord::Base

  has_many :product, :foreign_key => 'company_id', :class_name => 'Product'

end

产品型号

class Product < ActiveRecord::Base
  belongs_to :company

  validates :brand, :presence => true

end

4 个答案:

答案 0 :(得分:2)

好的,经过评论中的冗长讨论,我认为你需要这个:

# app/models/user.rb
class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :token_authenticatable, :confirmable, :lockable and :timeoutable

  # Setup accessible (or protected) attributes
  attr_accessible :email, :password, :password_confirmation, :remember_me

  devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable, :timeoutable

  # You'll need to add a new column to your users table, called `company_id`
  belongs_to :company
end

# app/models/company.rb
class Company < ActiveRecord::Base
  # has_many should _always_ be a pluralised version of the class you're associating. This way, you 
  # don't need to explicitly specify the class/foreign_keys
  has_many :products

  # Also, you may as well link back to your Users
  has_many :users
end


# app/models/product.rb
class Product < ActiveRecord::Base
  belongs_to :company
  validates :brand, :presence => true
end


# app/controllers/products_controller.rb
def create
  # and now, to associate the product with the company, all you need to do is this:

  @product = current_user.company.products.build(params[:product])

  if @product.save
    # redirect
  else
    # render and show errors
  end
end

Rails在常规上严重依赖 。你真的,真的应该遵循它们,让你的生活更轻松。

我建议您使用正确的关联,而不是手动关联UserCompany

这样,在你的Controller中,你需要做的就是调用current_user.company来获取公司,然后在关联上使用build方法,Rails将自动处理分配外键。< / p>

答案 1 :(得分:2)

Dan上面的回答是正确的,但作为一个更简单的版本,要创建你所描述的需要的关联:

class Company < ActiveRecord::Base
  has_many :products
  has_many :users
end

class Product < ActiveRecord::Base
  belongs_to :company
end

class User < ActiveRecord::Base
  belongs_to :company
end

产品和用户表需要一个名为company_id的列。

就是这样!现在,ActiveRecord将代表您智能地关联对象,您可以执行以下操作:

@product = Product.new(params[:product])
@product.company = current_user.company
@product.save

了解所有这些关系如何工作的最佳方式是在控制台中使用它们。尝试以下方式:

Company.first.products
Company.find(2).products
Company.find_by_name('Acme').products.order('price DESC')
User.last.products.where(...)

依旧......

最后,一个想法:通过阅读有关Rails的介绍性书籍,您将获益匪浅。我推荐'Beginning Rails 3'。这是一个快速阅读,你可以在一个周末完成它,它将全面了解如何以及为什么轨道的工作方式非常清楚。阅读本书所花费的时间将使您的工作效率和学习更高级的东西的速度达到最高,因为您将从坚实的基础开始,并以“轨道方式”解决问题。

今天你的问题肯定是“你做错了”的情况,这并不意味着你的逻辑有任何问题,只是因为你试图重新发明轮子使得一个简单的问题变得更加困难不必要的。学习“轨道方式”将使您的工作效率更高,并使整个事情变得更有趣。

答案 2 :(得分:0)

基于你上面的内容......这很令人困惑,我会冒险猜测:

您可能想尝试:

def create
  @product = Product.new(params[:product])
  @product.company = current_user.company
  @product.save
  ...
end

上面介绍的方法显示了很好的SQL知识,但是你对Ruby或Rails不是很熟悉。让ActiveRecord让您的生活更轻松,您不应该尝试手动设置外键,而应该使用对象构建关系,如上所示。

如果您不熟悉约定,如果您想在控制器中处理验证错误等,则应使用以下省略号:

if @product.save
  redirect_to ... # Redirect to whatever the next page you want them to see is if it saves correctly.
else
  render 'edit' # Otherwise show the edit view again with the errors that prevented saving
end

答案 3 :(得分:0)

你在这里做了很多冗余的查询。您应该能够将其简化为以下内容:

def create
    # so far, so good
    @product = Product.new(params[:product])

    # assuming that `current_user` returns an instance of User, you can replace the following two lines
    # @username = User.select("company").where("email= ?", current_user.email.to_s)
    # @cid = User.select("id").where("company= ?", @username)

    # Rather than going back to the database twice to get an ID, you can simply grab it from `current_user`
    unless current_user.company.blank?
      @product.company_id = current_user.id
      @product.save
    end

    # you should probably have an error handling / redirect / render routine here
end

那说,关于你的逻辑的东西似乎有点过时了。我希望company_id能够引用Company而非User

的实例的ID

可能是因为company_id始终为1的原因是因为id返回的实例的current_user为1。