Here are my relevant models:
class ListItem < ActiveRecord::Base
belongs_to :inventory_item
belongs_to :shopping_list
belongs_to :item
end
class ShoppingList < ActiveRecord::Base
has_many :list_items
belongs_to :user, :foreign_key => :user_id
end
class InventoryItem < ActiveRecord::Base
belongs_to :item, :foreign_key => :item_id
belongs_to :vendor
has_many :list_items
end
I want to have a button to create ListItems that belong to a user specified list that they own. The new ListItem also needs to be passed the respective :item_id and :inventory_item_id. Here's the relevant part of my current view:
<tr>
<% item.inventory_items.each do |product| %>
<td><%= button_to "#{product.price}",
{:controller => :list_items,
:action => 'create',
:id => #what goes here??,
:method => :create %></td>
<% end %>
</tr>
And my ListItems controller create method:
def create
ListItem.create
flash[:success] = "List Item Added."
redirect_to search_results_path(params[:search])
end
Clearly my create method isn't all that useful right now because it just creates a ListItem with no attributes other than :id. What's the best way to pass the appropriate parameters to my controller? Any help is much appreciated! Thanks in advance.
After doing a bunch of snooping around SO etc. I think the best way to accomplish this is to use a form with hidden fields, as below:
<%= form_tag("/list_items", method: "post") do %>
<%= hidden_field_tag(:item_id, item.id) %>
<%= hidden_field_tag(:inventory_item_id, product.id) %>
<%= hidden_field_tag(:shopping_list_id, ShoppingList.first.id) %>
<%= submit_tag("#{product.price}") %>
This is working well for me and is cleaner in this instance than using a button_to.
Related
I want to create a link to delete a record and it's sub record in a foreign table.
My models are like this :
class Cv < ActiveRecord::Base
has_many :formation
end
class Formation < ActiveRecord::Base
belongs_to :cv
validates :cv_id, presence: true
end
in my index view I have :
<%- #cv.each do |p| -%>
<%= link_to p.nom, cvsindex2_path(p) %>
<%= link_to 'delete', cvsdestroy_path(p) %></br>
<%- end -%>
My route :
cvsdestroy DELETE /cvs/:id(.:format)
How can I do that?
Thanks in advance.
If you will add dependent destroy to your relationship it will delete all its associated records from foreign key tables also.
class Cv < ActiveRecord::Base
has_many :formation, dependent: destroy
end
You need to add dependent: :destroy to your formation model in order to delete the associated record.
class Formation < ActiveRecord::Base
belongs_to :cv, dependent: :destroy
validates :cv_id, presence: true
end
And also change formation to formations in your cv model as you have has_many relation.
Update
You should also change your Delete link to like this
<%= link_to 'delete', cvsdestroy_path(p), method: :delete %>
Thank you that work with this
<%= link_to 'delete', #cv, :data => {:confirm => 'Are you sure?'}, :method => :delete %>
and
def destroy
#cvdestroy = Cv.find(params[:id])
#cvdestroy.destroy
redirect_to cvs_path, :notice => "Your CV has been deleted"
end
I having the following in my show.html.erb:
<% if #doctor.referrals_as_from.count > 0 %>
<% #doctor.referrals_as_from.each do |referral| %>
<%= referral.to_id %>
<% end %>
<% end %>
This works fine, giving me a list of matching id numbers from my referral model.
But, rather than getting a list of id numbers I would like to cross reference the "full_name" column from the Doctors model by using the identified id in referrals,basically an inner join. What is the most elegant way of doing this? Add a new method to the controller and to do a joins or includes, or is there a simpler way?
Models:
doctor.rb
class Doctor < ActiveRecord::Base
self.primary_key = "npi"
has_many :referrals_as_from, :class_name => 'Referral', :foreign_key => 'from_id'
has_many :referrals_as_to, :class_name => 'Referral', :foreign_key => 'to_id'
end
referral.rb
class Referral < ActiveRecord::Base
belongs_to :doctor
end
Use this.
<% if #doctor.referrals_as_from.count > 0 %>
<% #doctor.referrals_as_from.each do |referral| %>
<%= referral.doctor.full_name %>
<% end %>
<% end %>
The Referral model actually has two doctors associated with it, as defined by to_id and from_id. So you might need to do the following:
referral.rb
class Referral < ActiveRecord::Base
belongs_to :to_doctor, :class_name => "Doctor", :primary_key => "to_id", :foreign_key => "npi"
belongs_to :from_doctor, :class_name => "Doctor", :primary_key => "from_id", :foreign_key => "npi
end
Then the code becomes
referral.to_doctor.full_name
I have the following models where UserTreatment is essentially a lookup table but it has another field called instance_cost which stores an integer against each relationship.
class User < ActiveRecord::Base
has_many :user_treatments
has_many :users, :through => :user_treatments
end
class UserTreatment < ActiveRecord::Base
attr_accessible :instance_cost
belongs_to :user
belongs_to :treatment
end
class Treatment < ActiveRecord::Base
attr_accessible :name
has_many :user_treatments
has_many :users, :through => :user_treatments
end
So I can do things like this to get the first instance cost for user id 14
1.9.3p429 :181 > User.find(14).user_treatments.first.instance_cost
=> 100
and this to get the name of the treatment
1.9.3p429 :181 > User.find(14).user_treatments.first.treatment.name
=> "Sports Massage"
However I have a problem representing them in a form using simple_form_for
<% simple_form_for #user do |f| %>
# This sucessfully gives us the checkboxes of all treatments and stores them in the UserTreatments table
<%= f.collection_check_boxes(:treatment_ids, Treatment.all, :id, :name) %>
<%= f.fields_for :user_treatments do |pt| %>
<tr>
<td>
<!-- I WANT THE NAME OF THE TREATMENT HERE -->
</td>
<td><span>£</span> <%= pt.input :instance_cost, :as => :string, wrapper: false, label: false %></td>
</tr>
<% end %>
end
There are two things I need to do.
Show the name of the treatment (how do I do express User.user_treatments.treatment.name with simple_form ?)
Set the instance_cost correctly. Its currently not getting set at all.
When you do fields_for for a nested association then you need to add the following in your User model:
accepts_nested_attributes_for :user_treatments
Otherwise, it will not save the information.
And to access the name of the treatment, you could go through the object method of the form creator object, like this:
<%= f.fields_for :user_treatments do |pt| %>
<tr>
<td><%= pt.object.treatment.name %></td>
...
</tr>
<% end %>
I want to create a multiple form for editing scores from a different model.
The main model is a Formrule model that consists of a habtm association with a Scoretype model
and has a habtm association with a Room model.
Both models are used to query a Scores model resulting in a #scores instance. It is for this instance I want to create a form, but the problem is that no field_for are being created. I know that the #scores is populated correctly, but the form does not show up.
This is the form as I have it now
<%= form_tag '/scores/update_scores' do %>
<table>
<tr>...</tr>
<% for score in #scores %>
<% fields_for :scores, score do |score| %>
<tr>
<td>
<%= score.hidden_field(:form_id) %>
<%= score.hidden_field(:team_id) %>
<%= score.hidden_field(:scoretype_id) %>
</td>
<td>
<%= score.number_field :scorevalue %>
</td>
</tr>
<% end %>
<% end %>
</table>
<%= submit_tag 'Update' %>
<% end %>
And these are the Models:
Formrule
class Formrule < ActiveRecord::Base
belongs_to :form
has_and_belongs_to_many :scoretypes
has_and_belongs_to_many :rooms
has_many :teams, :through => :rooms
end
Scoretype
class Scoretype < ActiveRecord::Base
has_many :scores
has_and_belongs_to_many :formrules
end
Room
class Room < ActiveRecord::Base
has_many :teams
has_and_belongs_to_many :formrules
end
Team
class Team < ActiveRecord::Base
has_many :scores
belongs_to :room
belongs_to :group
end
Score
class Score < ActiveRecord::Base
belongs_to :form
belongs_to :team
belongs_to :scoretype
validates_uniqueness_of :id, :scope => [:team, :scoretype]
end
And finally, the used controller (Formrule)
def show
#formrule = Formrule.find(params[:id])
#scoretypes = #formrule.scoretypes.all.collect
#rooms = #formrule.rooms.all.collect
#teams = Team.find(:all, :conditions => {:room_id => #rooms})
#scores = Score.order("team_id").all(:conditions => {:scoretype_id => #scoretypes, :team_id => #teams})
...
end
Why is the form not showing up? any suggestions?
Thank you all in advance!
Try using <%= fields_for ... %> instead of <% fields_for ...%>.
I am working on a project involving three models (recipient, award, announcer) and need to have a nested attributes when issuing an award by an announcer to multiple recipients. For an example, award form need to have the ability to do 3 things:
Can add multiple-recipients (i.e. "add recipient", "remove recipient") - nested attributes
After creating a new award, the award will be posted into recipient's profile.
Enables future polling of #recipient.awards and #announcer.awards
Really struggle in terms of how to smartly solve this problem. The following data structure kind of made sense, however can not do "accepts_nested_attributes_for :recipients" in the award form. Can you help? Many thanks in advance.
class Recipient < ActiveRecord::Base
has_many :awards
has_many :announcers, :through => :awards
end
class Announcer < ActiveRecord::Base
has_many :awards
has_many :recipients, :through => :awards
end
class Award < ActiveRecord::Base
belongs_to :announcer
belongs_to :recipient
end
You're just about there. The main issue is that you're trying to create recipient objects in the form rather than just creating a relationship between the award and another object (user). You could do something like this:
class User < ActiveRecord::Base
has_many :recipients
has_many :awards, :through => :recipients
end
# this is your relationship between an award and a user
class Recipient < ActiveRecord::Base
belongs_to :user
belongs_to :award
end
class Award < ActiveRecord::Base
has_many :recipients
has_many :users, :through => :recipients
belongs_to :announcer
accepts_nested_attributes_for :recipients, :allow_destroy => true
end
class Announcer < ActiveRecord::Base
has_many :awards
has_many :recipients, :through => :awards
end
Then you would just do a nested form that would build the recipients_attributes array:
<%= form_for #award do |f| %>
<%= f.text_field :name %>
<div id="recipients">
<% #award.recipients.each do |recipient| %>
<%= render :partial => '/recipients/new', :locals => {:recipient => recipient, :f => f} %>
<% end %>
</div>
<%= link_to_function 'add recipient', "jQuery('#recipients').append(#{render(:partial => '/recipients/new').to_json})" %>
<% end %>
And, to keep it DRY just push the nested part into a partial:
# app/views/recipients/_new.html.erb
<% recipient ||= Recipient.new %>
<%= f.fields_for 'recipients_attributes[]', recipient do |rf| %>
<%= rf.select :user_id, User.all %>
<%= fr.check_box '_delete' %>
<%= fr.label '_delete', 'remove' %>
<% end %>
Obviously the User.all call isn't ideal so maybe make that an autocomplete.