我正在尝试输入外键值以及从表单收集的数据。表单数据提交完美,但外键总是输入为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
答案 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在常规上严重依赖 。你真的,真的应该遵循它们,让你的生活更轻松。
我建议您使用正确的关联,而不是手动关联User
和Company
。
这样,在你的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
可能是因为company_id
始终为1的原因是因为id
返回的实例的current_user
为1。