Сохранение Rails 3 с несколькими ассоциациями

Я создаю приложение Rails 3 с доской вакансий, где работники могут подавать заявки на работу. У меня следующие ассоциации:

Job:
  has_many :bids
  has_many :workers, :through => :bid

Bid:
  belongs_to :job
  belongs_to :worker

Worker:
  has_many :bids
  has_many :jobs, :through => :bid

У меня есть форма на странице «Показать вакансию», в которой работники могут подавать заявки. В контроллерах у меня есть следующее:

Job Controller:
  def show
    @bid = current_worker.bids.build
  end   

Bid Controller:
  def create
    @bid = current_worker.bids.build(params[:bid])
    @bid.save
  end

С приведенным выше кодом отправленная заявка не будет правильно сохранена, поскольку в ней отсутствует job_id:

1) Как правильно сохранить ставку с ОБОИМ идентификатором job_id и worker_id?

2) (У меня возникли проблемы с передачей job_id из метода show контроллера заданий в метод create контроллера ставок) — безопасно ли передавать job_id в переменной сеанса?

Для справки форма заявки выглядит так:

<%= form_for(@bid) do |f| %>

  <%= f.label :min_price, "Minimum Price" %>
  <%= f.text_field :min_price %>

  <%= f.label :fee %>
  <%= f.text_field :fee %>

  <%= f.label :comments %>
  <%= f.text_area :comments, placeholder: "Comments..." %>
  <%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>

person Krishna    schedule 31.05.2013    source источник
comment
Разве ваш метод bids_controller#create не должен вызывать new вместо build? Почему бы просто не добавить <%= f.hidden_field :job_id, @job.id %> к form_for(@bid)?   -  person coreyward    schedule 31.05.2013
comment
Передача job_id в качестве скрытого поля небезопасна. Пользователь может использовать firebug или другую программу для изменения job_id при отправке формы.   -  person Krishna    schedule 31.05.2013
comment
И если они могут претендовать на любую работу, то это не имеет значения. Если есть ограничения на идентификатор задания, вам, вероятно, все равно следует проверять его на стороне сервера.   -  person coreyward    schedule 31.05.2013


Ответы (3)


Код зависит от того, какую безопасность вы хотите, я полагаю, вы хотите иметь защищенные задания, на которые current_worker не может делать ставки, поэтому вам нужно, чтобы это не зависело от ставки, а в задании.

Поскольку вы впервые создаете заявку, вы можете передать job_id в форме или как часть маршрута.

Если вы хотите запретить работнику участвовать в торгах на какую-либо работу, вы можете сделать что-то вроде этого:

Bids Controller:

  def create
    job = Job.find(params[:job_id])
    if current_worker.can_bid? job
      @bid = current_worker.bids.build params[:bid]
    else
      # handle unauthorised bidding

В рабочей модели это всего лишь пример:

def can_bid?(job)
  # Implement code here
  # example:
  # job.public? or invited_to?(job)
end

# example of invited_to?(job)
def invited_to?(job)
  job.invitees.include? self
end

Я не уверен, что это отвечает на ваш вопрос.

Я думаю, вы могли бы использовать это для передачи идентификатора задания по маршруту:

Маршруты

resources :jobs do
  resources :bids
end

Вид

= form_for @job, @bid ...

Поскольку в первый раз у вас нет @job, вы можете использовать:

= form_for :job, @bid
person sites    schedule 31.05.2013
comment
Хуанпастас - как мне передать job_id как часть маршрута, а не в форме? - person Krishna; 31.05.2013

Я новичок в рельсах, но я думаю, вместо того, чтобы говорить

<%= form_for(@bid) do |f| %>

пытаться

<%= form_for(@job, @bid) do |f| %>

затем в вашем новом действии контроллера ставок сделайте что-то вроде этого

def new
  @job = Job.find(params[:job_id])
  @bid = @job.bids.build
end

а затем в ваших маршрутах вы должны вложить ставку под ресурсы работы, например

resources :jobs do
  resources :bids
end

это должно сделать это, я надеюсь, как я уже сказал, я новичок и могу ошибаться в этом.

person zechtz    schedule 31.05.2013

Просто проверьте свою модель Bid. Это относится к двум моделям. Поэтому вам нужно сделать это как полиморфную таблицу. Переструктурируйте свои модели следующим образом.

Bid:
  belongs_to :bidable, polymorphic: true

Job:
  has_many :workers, :through => :bid
  has_many :bids, :as => :bidable

Worker:
  has_many :bids, :as => :bidable
  has_many :jobs, :through => :bid
person Jyothu    schedule 31.05.2013
comment
Я вижу - я читал о полиморфной таблице, и это имеет смысл. Но как только я внесу изменения, которые вы предлагаете, как мне изменить контроллер заданий и контроллер заявок (и форму, если необходимо), чтобы создать новую ставку, сохраняя при этом как job_id, так и worker_id, не используя скрытую форму для хранения идентификаторов? - person Krishna; 31.05.2013