I am building a job board where workers can bid on jobs and bosses can accept a single bid for each job they have, creating an "assignment". On the job show page, already constructed bids can be accepted by a boss. Among other things, I have the following associations:
Job:
has_many :bids
has_many :assignments, :through => :bids
Bid:
has_one :assignment
belongs_to :job
Assignment:
belongs_to :bid
has_one :job, :through => :bid
In the Job Show Page: (form for a boss to accept a bid)
<%= form_for :assignments, :url => '/assignments' do |f| %>
<%= f.submit "Accept Bid", class: "btn btn-mini" %>
<% end %>
In the Job Controller:
Show Action:
#job.bids.each { |bid| bid.build_assignment }
In the Assignment Controller:
Create Action:
#bid = Bid.find(params[:bid_id])
#assignment = #bid.build_assignment(params[:assignment])
#assignment.save
As you can see, I am trying to build an assignment through association with a bid. Questions:
1) When I click "accept bid" (form above), rails displays an error indicating the bid cannot be found (in the assignment controller create action). Why?
2) I also tried doing: <%= f.hidden_field :bid_id %> in the form and changing the Assignment create action to: #assignment = Assignment.new(params[:assignment]), but now the assignment object won't save because apparently there is no bid_id.
Related
I'm trying to do a nested form for a has_many :through association using Simple Form, and I can't figure out how to get around this error: ArgumentError in Variants#edit -- Association cannot be used in forms not associated with an object.
Here's what I'm trying to accomplish. I have a "Product Variant" model (called Variant). Each variant can have many parts (Part model) through a "Parts List Item" (PartsListItem) join model. Each variant should be able to have parts assigned to it in different quantities.
For instance, a guitar strap might have a part called "Backing Fabric" that has a quantity of 1. Meaning that the Guitar Strap variant needs 1 of the "Backing Fabric" part to be assembled. But the same variant might also have another part such as "Rivet" that has a quantity of 4. (As in 4 rivets are required to make this product variant.) After using the Variant form to add all the parts in various quantities to the variant, I'd like to show all of the parts with quantities on the variants#show page.
Here is the relevant code from my models:
class Variant < ApplicationRecord
has_many :parts_list_items, dependent: :destroy
has_many :parts, through: :parts_list_items, dependent: :nullify
accepts_nested_attributes_for :parts
end
class PartsListItem < ApplicationRecord
belongs_to :variant
belongs_to :part
end
class Part < ApplicationRecord
has_many :parts_list_items, dependent: :destroy
has_many :variants, through: :parts_list_items, dependent: :nullify
end
And my VariantsController:
class VariantsController < ApplicationController
def update
respond_to do |format|
if #variant.update(variant_params)
format.html { redirect_to #variant, notice: 'Variant was successfully updated.' }
else
format.html { render :edit }
end
end
end
private
def variant_params
params.require(:variant).permit(:account_id, :product_id, :sku,
:choice_ids => [], :part_ids => [])
end
end
And my form (views/variants/_edit_form.html.erb):
<%= simple_form_for #variant do |f| %>
<%= f.simple_fields_for :parts_list_items do |item| %>
<%= item.input_field :quantity %>
<%= item.association :parts %>
<% end %>
<% end %>
Note that this works just fine:
<%= simple_form_for #variant do |f| %>
<%= f.association :parts, as: :check_boxes %>
<% end %>
So, it works to associate parts directly to the variant through the PartsListItem join model. The trouble begins when I start trying to add the quantity for each associated part.
What am I doing wrong with this nested form? Is there a problem with my controllers or associations?
Do I need to create an additional model called PartsList that has_many :parts_list_items with additional associations? That seems like an extra step and that there should be a way to put the :quantity on the PartsListItem model.
I think you need to change parts to part
<%= simple_form_for #variant do |f| %>
<%= f.simple_fields_for :parts_list_items do |item| %>
<%= item.input_field :quantity %>
<%= item.association :parts %> <!-- HERE -->
<% end %>
<% end %>
I have three related models
class Opportunity < ActiveRecord::Base
has_many :proposals, :dependent => :destroy
end
class Proposal < ActiveRecord::Base
belongs_to :opportunity
belongs_to :panel
end
class Panel < ActiveRecord::Base
belongs_to :opportunity
has_many :proposals
accepts_nested_attributes_for :proposals
end
I have a single opportunity and i want to list all proposals in a form, each having four radio buttons to assign each to a one of four panels.
<%= form_for :proposal, :url => update_all_path, :html => { :method => :put } do %>
<% #proposals.each do |prop| %>
<%= fields_for "proposal[]", proposal do |proposal_fields| %>
<%= proposal.name %><br>
<%= proposal_fields.number_field :panel_id %><br>
<% end %>
<% end %>
<% end %>
This form seems to work ok at the basic info. Ideally I want a series of radio buttons instead of a number_field or select.
So I would have:
Proposal A -> 4 radio buttons**
Proposal B -> 4 radio buttons**
For now I'd be happy just getting the new panel_id into the database correctly.
Here is the returned params
"proposal"=>{"244"=>{"panel_id"=>"34"}, "245"=>{"panel_id"=>"33"}},
and my update method
def update_all
params['proposal'].keys.each do |id|
#proposal = Proposal.find(id.to_i)
#proposal.panel_id = params['proposal'][:id][panel_id]
end
redirect_to...
end
and without further ado... the error
NameError at /proposals/all
undefined local variable or method `panel_id' for #
<ProposalsController:0x007ff3cf714420>
Did you mean? panel_url
How do i save the panel_id for each proposal ?
Thanks in advance for any help.
I'm fairly new to Rails and I've been trying to extend Michael Hartl's tutorial in various ways. One of which is to model user interests using a has_many :through association. I have the following models set up:
class Interest < ActiveRecord::Base
has_many :user_interests, dependent: :destroy
has_many :users, through: :user_interests
end
class User < ActiveRecord::Base
has_many :user_interests, dependent: :destroy
has_many :interests, through: :user_interests
end
class UserInterest < ActiveRecord::Base
belongs_to :user
belongs_to :interest
end
My user_interests controller:
def index
end
def create
#user_interest = current_user.user_interests.build(params[:interest_ids])
if #user_interest.save
redirect_to current_user
flash[:success] = "Interests updated!"
else
render 'index'
end
end
def destroy
#user_interest = UserInterest.find(params[:user_id][:interest_ids])
current_user.user_interests(#user_interest).destroy
end
The view:
<%= form_for(current_user.user_interests.build(params[:interest_ids])) do |f| %>
<%= hidden_field_tag "user[interest_ids][]", nil %>
<% Interest.all.each do |interest| %>
<%= check_box_tag "user[interest_ids][]", interest.id, current_user.interest_ids.include?(interest.id), id: dom_id(interest) %>
<%= label_tag dom_id(interest), interest.activity %><br>
<% end %>
<%= f.submit "Update interests", class: "btn btn-large btn-primary" %>
<% end %>
When I run the app I can select a check box and click the submit button but only the user id is saved in the user_interests table. So it will look like:
id integer user_id interest_id created_at_timestamp updated_at_timestamp
1 2155 2014-04-06 ect... 2014-04-06 ect...
At first I was trying to use the users controller to create the association, but that was causing issues because I didn't have the interests check boxes displayed on the users#edit action, I wanted them to have their own page. What do I need to do to get the interest ids to save to the user_interests table along with the user id?
Please have a try with the following code.
def create
interests = Interest.where(id: params[:user][:interest_ids])
current_user.interests.push(interests)
flash[:success] = "Interests updated!"
redirect_to current_user
end
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 %>
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
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.
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
I'm trying to build a rather complex nested form in rails and am stuck.
Basically, I have three models - Applicant, DataPoint, ApplicantDataPointValue .
The user can create a new DataPoint, give it a name ("gender" etc.) select it's type ("string","integer" etc.). The type determines what column the data will eventually be saved in in the ApplicantDataPointValue table.
I then want the user, when they're creating a new Applicant, to be able to add a value for each DataPoint into the ApplicantDataPointValue table
My models look like the following:
Applicant:
class Applicant < ActiveRecord::Base
has_many :applicant_data_point_values, dependent: :destroy
has_many :data_points, :through => :applicant_data_point_values
accepts_nested_attributes_for :data_points
accepts_nested_attributes_for :applicant_data_point_values
attr_accessible :data_points_attributes, :applicant_data_point_values_attributes
end
DataPoint:
class DataPoint < ActiveRecord::Base
has_many :applicant_data_point_values
has_many :applicants, :through => :applicant_data_point_values
accepts_nested_attributes_for :applicant_data_point_values
end
ApplicantDataPointValue:
class ApplicantDataPointValue < ActiveRecord::Base
belongs_to :data_point
belongs_to :applicant
end
But I'm at a loss to what to do in the 'new' and 'create' sections of my controller or how to construct the form.
Any insight would be greatly appreciated.
From what I understand, the form for the User will also have multiple ApplicantDataPointValue fields. (but that form won't allow creating of new DataPoint fields, right?)
In the controller new action, you'll want to set up your model with associated data point values:
def new
#user = User.new
DataPoint.all.each do |data_point|
applicant_data_point_value = #user.applicant_data_point_values.build
applicant_data_point_value.data_point = data_point
end
end
And then, display a text box for each data point value.
<%= form_for #user do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<% #user.applicant_data_point_values.each do |data_point_value| %>
<%= f.fields_for :applicant_data_point_values, data_point_value do |fields| %>
<%= fields.label :value, data_point_value.data_point.type %>
<%= fields.text_field :value %>
<% end %>
<% end %>
Reference: http://railscasts.com/episodes/196-nested-model-form-part-1