Krishna
Krishna

Reputation: 133

Rails 3 Saving with Multiple Associations

I am building a Rails 3 app with a job board, where workers can submit bids for jobs. I have the following associations:

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

I have a form on the Show Job Page in which workers can submit bids. In the controllers, I have the following:

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

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

With the code above, a submitted bid will not save correctly because it is missing the job_id:

1) What is the correct way to save the bid with BOTH the job_id and worker_id?

2) (I am having trouble passing the job_id from the Job Controller show method to the Bid Controller create method) - is it secure to pass the job_id in a sessions variable?

For reference, the bid form looks like:

<%= 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 %>

Upvotes: 0

Views: 751

Answers (3)

sites
sites

Reputation: 21775

Code depends on what safety you want, I suppose you want to have to protected jobs which current_worker can't make bids to, so you need that does not seems to depend on bid, instead in job.

As you are first creating a bid you can pass job_id, in the form or as part of the route.

If you want to deny a worker to bid to any job you could do something like this:

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

In worker model, this is just an example:

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

I am not sure if this answers your question.

I think you could use this to pass job id in route:

Routes

resources :jobs do
  resources :bids
end

View

= form_for @job, @bid ...

As in first time you don't have @job, you can use:

= form_for :job, @bid

Upvotes: 1

zechtz
zechtz

Reputation: 442

I'm a rails newbie but I think instead of saying

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

try

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

then in your bid controller new action do something like this

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

and then in your routes you should nest the bid under the job resources like

resources :jobs do
  resources :bids
end

that should do it I hope, like I said I'm a newbie and may be wrong on this.

Upvotes: 1

Jyothu
Jyothu

Reputation: 3144

Just check your model Bid. Its belogs to two models. So You have to make it as polymorphic table. Re Structure your models as follows

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

Upvotes: 0

Related Questions