foreign_key всегда 1 - PullRequest
       1

foreign_key всегда 1

2 голосов
/ 01 марта 2011

Я пытаюсь ввести значение внешнего ключа вместе с данными, полученными из формы.Данные формы отправляются идеально, но внешний ключ всегда вводится как 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 ]

2 голосов
/ 01 марта 2011

Ответ Дана, приведенный выше, является правильным, но, как более простая версия, для создания ассоциации, которую вы описываете, вам нужно:

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

Таблицам Product и User нужен столбец с именем 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 голосов
/ 01 марта 2011

Хорошо, после долгой дискуссии в комментариях, я думаю, что вам нужно:

# 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, я предложил вам использовать правильную связь.

Таким образом, внутри вашего контроллера все, что вам нужно сделать, это позвонить по номеру current_user.company, чтобы получить компанию, затем использовать метод build для ассоциации, и Rails автоматически обработает присвоение внешних ключей.

0 голосов
/ 01 марта 2011

Вы делаете много лишних запросов здесь.Вы должны быть в состоянии упростить это до следующего:

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.

0 голосов
/ 01 марта 2011

Исходя из того, что у вас есть выше ... что весьма запутанно, я рискну сделать дикое предположение:

Вы можете попробовать:

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

Подход, который вы использовали выше, показывает хорошее знание SQL, но также и то, что вы не очень хорошо знакомы с Ruby или Rails. Позвольте ActiveRecord сделать вашу жизнь проще, вам никогда не следует пытаться вручную устанавливать внешний ключ, вместо этого вы должны строить отношения, используя объекты, как показано выше.

В качестве отдельного случая, если вы не знакомы с соглашением, если вы хотите обрабатывать ошибки проверки и т. Д. В контроллере, вы должны использовать это там, где значение elipsis выше:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...