How can I fill in the hidden fields in app/views/rounds/shot_fields.html.erb?
app/models/player.rb
class Player < ActiveRecord::Base
has_many :shots, :dependent => :destroy
belongs_to :team
belongs_to :user
has_many :games
has_and_belongs_to_many :home_games, :class_name => "Game"
has_and_belongs_to_many :away_games, :class_name => "Game"
end
app/models/round.rb
class Round < ActiveRecord::Base
belongs_to :game, :counter_cache => true
has_many :shots, :dependent => :destroy
accepts_nested_attributes_for :shots, :allow_destroy => true
validates_presence_of :number
validates_numericality_of :number
end
app/models/shot.rb
class Shot < ActiveRecord::Base
belongs_to :player, :counter_cache => true
belongs_to :game
belongs_to :round
belongs_to :team
end
app/models/game.rb
class Game < ActiveRecord::Base
has_many :shots, :dependent => :destroy
has_many :rounds, :order => 'number', :dependent => :destroy
accepts_nested_attributes_for :shots
belongs_to :away, :class_name => 'Team'
belongs_to :home, :class_name => 'Team'
has_and_belongs_to_many :home_players, :class_name => 'Player', :association_foreign_key => "home_player_id"
has_and_belongs_to_many :away_players, :class_name => 'Player', :association_foreign_key => "away_player_id"
accepts_nested_attributes_for :rounds, :allow_destroy => true
end
app/controllers/rounds_controller.rb
def new
#game = Game.find(params[:game_id])
#round = #game.rounds.build
#round.number = #game.rounds.count > 1 ? #game.rounds.count + 1 : 1
end
app/views/rounds/_form.html.erb
<% if #round.errors.any? %>
<div class="error">
<% #round.errors.full_messages.each do |msg| %>
<%= msg %><br/>
<% end %>
</div>
<% end %>
<%= form_for #game do |f| %>
<%= field_set_tag "Rounds" do %>
<table class="sortable">
<thead>
<tr>
<th>Number</th>
<th><%= #game.away_players[0].name %></th>
<th><%= #game.away_players[1].name %></th>
<th><%= #game.away_players[2].name %></th>
<th><%= #game.home_players[0].name %></th>
<th><%= #game.home_players[1].name %></th>
<th><%= #game.home_players[2].name %></th>
<th>Remove</th>
</tr>
</thead>
<tbody>
<%= f.fields_for :rounds do |round_form| %>
<%= render 'round_fields', :f => round_form %>
<% end -%>
</tbody>
</table>
<p>
<%= link_to_add_fields "Add Round", f, :rounds %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
<% end %>
app/views/rounds/round_fields.html.erb
<% 6.times { f.object.shots.build } if f.object.new_record? -%>
<tr>
<td>
<%= f.text_field :number, :size => 3 %>
</td>
<%= f.fields_for :shots do |shot_form| %>
<%= render 'shot_fields', :f => shot_form %>
<% end -%>
<td>
<%= f.check_box(:_destroy) %>
<%= f.hidden_field :id %>
</td>
</tr>
app/views/rounds/shot_fields.html.erb
<td>
<%= f.select :cup, [["Miss", 0], 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ["No Shot", ""], ["Suicide", 11]] %>
<%= f.hidden_field :id %>
<%= f.hidden_field :game_id, :value => params[:id] %>
<%# f.hidden_field :player_id, :value => player.id %>
<%# f.hidden_field :team_id, :value => team.id %>
</td>
Passing them in via locals should work.
<%= render 'shot_fields', :locals => { :f => shot_form, :player => some_player_you_dont_have_defined, :team => some_team_variable_i_dont_see } %>
I don't quite understand what you're trying to do (lots of code, not a lot of context), but this is how you pass information into partials.
Related
Using cocoon to build my nested form for a has_many through association. The association gets created, however it doesn't update or remove the associations. The following is my nested form:
edit.html.erb:
<div class="case_contacts-edit-container">
<%= link_to_add_association 'ADD CONTACT', f, :case_contacts, :"data-association-insertion-node" => "tbody#case_contacts_", :"data-association-insertion-method" => "append", class: 'action-button insure pull-right' %>
<table id="info-table3">
<tbody id="case_contacts_">
<tr>
<td class="right">
<strong>Name</strong>
</td>
<td class="right">
<strong>Role</strong>
</td>
<td class="right">
<strong>Note</strong>
</td>
<td>
</td>
</tr>
<%= f.simple_fields_for :case_contacts do |case_contact| %>
<%= render 'case_contact_fields', :f => case_contact %>
<% end %>
</tbody>
</table>
_case_contact_fields.html.erb:
<tr class="nested-fields">
<td>
<%= f.association :contact, :collection => (Contact.all.select(:first_name, :last_name, :email, :company_name, :id).map { |contact| [contact.name_with_company, contact.id] }), :prompt => "Add Contact", :class => 'table-input', :label => false %>
</td>
<td>
<%= f.input :role, collection: Contact::TYPES, :prompt => "Add Role", :class => 'table-input', :label => false %>
</td>
<td>
<%= f.input :note, :prompt => "Add Note", :class => 'table-input', :label => false %>
</td>
<%= f.hidden_field :firm_id, :value => #firm.id %>
<td class="insurance-icon" style="text-align: center;">
<%= link_to_remove_association f, class: 'dark-small remove_case_contacts' do %><span id="remove" class="glyphicon glyphicon-trash" original-title="Remove Contact"></span><% end %>
</td>
</tr>
cases_controller.rb (update method):
#case.assign_attributes(case_params)
#case.save
cases_controller.rb (permitted parms):
def case_params
params.require(:case).permit(:name, :case_number, :docket_number, :description, :case_type, :subtype,
:court, :county, :corporation, :status, :hearing_date, :filed_suit_date, :fee_agreement,
:case_contacts_attributes => [:id, :case_id, :updated_at, :created_at, :firm_id, :role, :contact_id, :note, :_destroy])
end
case.rb (model):
has_many :case_contacts, :dependent => :destroy
has_many :contacts, :through => :case_contacts
accepts_nested_attributes_for :case_contacts, :reject_if => :all_blank, :allow_destroy => :true
contact.rb (model):
has_many :case_contacts, :dependent => :destroy
has_and_belongs_to_many :cases, :join_table => 'case_contacts'
case_contact.rb (joiner model):
belongs_to :affair, class_name: 'Case', :foreign_key => 'case_id'
belongs_to :contact
I have more curious questions for all you amazing people!
I am creating a forum and when you create a topic, you are also creating the first post at the same time.
I need to assign variables to certain fields.
Example: :user_id => current_user.id,
I don't have the param settings correct, so many of the fields are NULL when stored in the database.
Models
class Topic < ActiveRecord::Base
belongs_to :forum
has_many :posts, :dependent => :destroy
belongs_to :user
accepts_nested_attributes_for :posts
end
class Post < ActiveRecord::Base
belongs_to :topic
belongs_to :user
end
Topics Controller
# GET /topics/new
def new
#topic = Topic.new
#topic.posts.build
end
def create
#topic = Topic.new(topic_params)
if #topic.save
##topic.responses = Post.new(params[:responses])
flash[:success] = "Topic Posted"
redirect_to "/forums/#{#topic.forum_id}"
else
render :new
end
end
def topic_params
# last_post_at = (:last_post_at => Time.now)
params.require(:topic).permit(
:name,
:description,
[:last_poster_id => current_user.id],
[:last_post_at => Time.now],
[:user_id => current_user.id],
:forum_id,
posts_attributes: [:id, :content, :topic_id, :user_id => current.user.id] )
end
Post Controller
# GET /posts/new
def new
#post = Post.new
end
def create
#post = Post.new(
:content => params[:post][:content],
:topic_id => params[:post][:topic_id],
:user_id => current_user.id)
if #post.save
#topic = Topic.find(#post.topic_id)
#topic.update_attributes(
:last_poster_id => current_user.id,
:last_post_at => Time.now)
flash[:notice] = "Successfully created post."
redirect_to "/topics/#{#post.topic_id}"
else
render :action => 'new'
end
end
_form for View/Topic
<%= form_for(#topic) do |f| %>
<% if params[:forum] %>
<input type="hidden"
id="topic_forum_id"
name="topic[forum_id]"
value="<%= params[:forum] %>" />
<% end %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :description %><br>
<%= f.text_field :description %>
</div>
<%= f.fields_for :posts do |p| %>
<%= p.label :content %><br />
<%= p.text_area :content %>
<% end %>
<%= f.submit :class => "btn btn-primary" %>
<% end %>
You'll likely be looking for a function called:
accepts_nested_attributes_for
You put this into the model you're working with (in your case Post) and it will pass paeans for the nested model through to the corresponding controller
There is a good RailsCast about this and I've gr some experience with it too. If you want me to post working live code, let me know (I'm on my iPhone)
Live Code
Models
#app/models/image_post.rb
belongs_to :post, :class_name => 'Post'
belongs_to :image, :class_name => 'Image'
accepts_nested_attributes_for :image, :allow_destroy => true
#app/models/post.rb
has_many :images, -> { uniq }, :class_name => 'Image', :through => :images_posts, dependent: :destroy
has_many :images_posts, :class_name => 'ImagePost'
accepts_nested_attributes_for :images_posts, :allow_destroy => true
Controller
def new
#post = Post.new
#post.images_posts.build.build_image
end
def create
#Using Inherited Resources Gem
create!
end
private
def permitted_params
{:post => params.require(:post).permit(:title, :body, images_posts_attributes: [:caption, image_attributes: [:image]] )}
end
Form
<%= form_for [:admin, resource], :html => { :multipart => true } do |f| %>
<table class="resource_table">
<thead>
<th colspan="2"><%= params[:action].capitalize %> <%= resource_class %></th>
</thead>
<tbody class="form">
<% attributes.each do |attr| %>
<tr class="<%= cycle('odd', '')%>">
<td><%= resource_class.human_attribute_name(attr) %></td>
<td>
<% if attr == "body" %>
<%= f.text_area attr, :rows => 60, :cols => 80, :class => "redactor" %>
<% else %>
<%= f.text_field attr, :value => resource.public_send(attr).to_s %>
<% end %>
</td>
</tr>
<% end %>
<%= f.fields_for :images_posts do |images_posts| %>
<%= images_posts.fields_for :image do |images| %>
<tr>
<td>Image</td>
<td><%= images.file_field :image %></td>
</tr>
<% end %>
<tr>
<td>Caption</td>
<td><%= images_posts.text_field :caption %></td>
</tr>
<% end %>
<tr class="dull">
<td colspan="2"><%= f.submit "Go" %></td>
</tr>
</tbody>
</table>
<% end %>
Use accepts_nested_attributes
class topic
accepts_nested_attributes :posts
end
class post
accepts_nested_attributes :topic
end
Then in form you can use fields_for posts while creating topic form
Also in post form fileds_for for topic
You may want to fetch the post params as
params[:topic].fetch(:post_attributes, nil)
Rails 4 has been sanitized the mass-assignment to be called as strong_params
Example
I have 3 models:
class DropShipOrderLineItem < ActiveRecord::Base
belongs_to :drop_ship_order
belongs_to :line_item
validates_associated :drop_ship_order
validates_associated :line_item
validates :drop_ship_order_id, :presence => true
validates :line_item_id, :presence => true
attr_accessible :missing
end
class DropShipOrder < ActiveRecord::Base
attr_accessible :line_items, :line_items_attributes, :orders, :order_attributes
belongs_to :retailer
belongs_to :order
belongs_to :shipping_method
has_many :drop_ship_order_line_items
has_many :line_items, :through => :drop_ship_order_line_items
has_many :shipments, :dependent => :destroy
accepts_nested_attributes_for :line_items
accepts_nested_attributes_for :order
accepts_nested_attributes_for :drop_ship_order_line_items
before_create :generate_order_number
scope :by_number, lambda {|number| where("drop_ship_orders.number = ?", number)}
scope :between, lambda {|*dates| where("drop_ship_orders.created_at between ? and ?", dates.first.to_date, dates.last.to_date)}
scope :by_customer, lambda {|customer| joins(:order).joins(:user).where("users.email =?", customer)}
scope :by_state, lambda {|state| where("state = ?", state)}
scope :complete, where("drop_ship_orders.completed_at IS NOT NULL")
scope :incomplete, where("drop+ship_orders.orders.completed_at IS NULL")
make_permalink :field => :number
validates_associated :order
validates_associated :retailer
end
LineItem.class_eval do
has_one :drop_ship_order_line_item, :dependent => :destroy
has_one :drop_ship_order, :through => :drop_ship_order_line_items
accepts_nested_attributes_for :drop_ship_order_line_item
attr_accessible :drop_ship_order_line_item
# def missing
# self.drop_ship_order_line_item.missing
# end
end
View #1:
<div data-hook="admin_order_edit_form">
<div id="order-form-wrapper">
<%= render :partial => 'form', :locals => {:drop_ship_order => #drop_ship_order} %>
</div>
</div>
View form:
<%= form_for(#drop_ship_order, :url => admin_drop_ship_order_path(#drop_ship_order), :html => { :method => :put}) do |f| %>
<%= f.hidden_field :number %>
<table class="index">
<tbody id='line-items'>
<tr data-hook="admin_order_form_line_items_headers">
<th><%= t('item_description') %></th>
<th class="price"><%= t('price') %></th>
<th class="qty"><%= t('qty') %></th>
<th class="total"><span><%= t('total') %></span></th>
<th class="orders-actions" data-hook="admin_order_form_line_items_header_actions"></th>
</tr>
<%= f.fields_for :line_items do |li_form| %>
<%= render :partial => "admin/drop_ship_orders/line_item", :locals => { :f => li_form } %>
<% end %>
</tbody>
<tbody id='subtotal' data-hook="admin_order_form_subtotal">
<tr id="subtotal-row">
<td colspan="3"><b><%= t('subtotal') %>:</b></td>
<td class="total"><span><%= number_to_currency #drop_ship_order.item_total %></span></td>
<td></td>
</tr>
</tbody>
view line_item:
<tr id="<%= dom_id(f.object) %>" data-hook="admin_order_form_line_item_row">
<td width="300"><%=f.object.variant.product.name%> <%= "(" + variant_options(f.object.variant) + ")" unless f.object.variant.option_values.empty? %></td>
<td valign="top" class="price"><%= number_to_currency f.object.price %></td>
<td valign="top" class="qty"><strong><%= f.object.quantity %></strong></td>
<td valign="top" class="total"><%= number_to_currency (f.object.price * f.object.quantity)%></td>
<td data-hook="admin_order_form_line_item_actions">
<!--<input type="checkbox" name="apple" id="apples"/>-->
<%#= f.object.drop_ship_order_line_item.missing %>
<%= f.fields_for :drop_ship_order_line_item do |build|%>
<%= build.check_box :missing, :type => "checkbox" %>
<% end %>
</td>
</tr>
The :missing attribute is not being updated, and I just can't figure out why! Although the checkboxe is correctly being ticked if I manually change the values in my SQL table.
p.s: I just posted the relevant parts of my code.
In your LineItem model change attr_accessible :drop_ship_order_line_item to attr_accessible :drop_ship_order_line_item_attributes.
What is the :type => "checkbox" for in the following code:
<%= build.check_box :missing, :type => "checkbox" %>
The second parameter for the check_box form helper should be the method. I think if you change to the following code, it should work:
<%= build.check_box :missing %>
Im trying to update some nested params from a form. I can see that the parameters im getting from the form is correct, however the database dont get updated.
the view
<% form_for #order do |f| %>
<% f.fields_for :itemgroups do |ff, i| %>
<% ff.fields_for :items do |fff| %>
<%= ff.text_field :text, :id => "textField", :disabled => true %>
<%= ff.text_field :price, :class => "priceField", :disabled => true %>
<%= fff.check_box :registered, :class => i %>
<% end %>
<% end %>
<%= submit_tag 'Save', :disabled_with => "Saving..." %>
<% end %>
Itemgroup class
class Itemgroup < ActiveRecord::Base
belongs_to :order
has_many :items, :dependent => :destroy
has_one :kind
accepts_nested_attributes_for :items, :kind
end
Order class
class Order < ActiveRecord::Base
has_many :itemgroups, :dependent => :destroy
has_many :items, :through => :itemgroups, :dependent => :destroy
has_many :kinds, :through => :itemgroups
accepts_nested_attributes_for :itemgroups, :allow_destroy => true
validates_associated :itemgroups, :items ,:kinds
end
The important part of the controller.
def update
#order = Order.find(params[:id])
if #order.update_attributes(params[:order])
flash[:notice] = 'Order was successfully edited.'
redirect_to(#order)
else
flash[:notice] = 'An error occured.'
render(:action => :edit)
end
end
Change
<% f.fields_for :itemgroups do |ff, i| %>
<% ff.fields_for :items do |fff| %>
<%= ff.text_field :text, :id => "textField", :disabled => true %>
<%= ff.text_field :price, :class => "priceField", :disabled => true %>
<%= fff.check_box :registered, :class => i %>
<% end %>
To EDITED
<% f.fields_for :itemgroups do |ff, i| %>
<%= ff.text_field :text, :id => "textField", :disabled => true %>
<%= ff.text_field :price, :class => "priceField", :disabled => true %>
<% ff.fields_for :items do |fff| %>
<%= fff.check_box :registered, :class => i %>
<% end %>
and check
Fixed the problem!
class Order < ActiveRecord::Base
has_many :itemgroups, :dependent => :destroy
has_many :items, :through => :itemgroups, :dependent => :destroy
has_many :kinds, :through => :itemgroups
accepts_nested_attributes_for :itemgroups, :allow_destroy => true
# validates_associated :itemgroups, :items ,:kinds
end
the validates_associated line was removed. Then it worked
I get this uninitialized constant error when i submit my nested forms.
order.rb
class Order < ActiveRecord::Base
has_many :items, :dependent => :destroy
has_many :types, :through => :items
accepts_nested_attributes_for :items
accepts_nested_attributes_for :types
validates_associated :items
validates_associated :types
end
item.rb
class Item < ActiveRecord::Base
has_one :types
belongs_to :order
accepts_nested_attributes_for :types
validates_associated :types
end
type.rb
class Type < ActiveRecord::Base
belongs_to :items
belongs_to :orders
end
new.erb.html
<% form_for #order do |f| %>
<%= f.error_messages %>
<% f.fields_for :items do |builder| %>
<table border="0">
<th>Type</th>
<th>Amount</th>
<th>Text</th>
<th>Price</th>
<tr>
<% f.fields_for :type do |m| %>
<td> <%= m.collection_select :type, Type.find(:all, :order => "created_at DESC"), :id, :name, {:prompt => "Select a Type" }, {:id => "selector", :onchange => "type_change(this)"} %> </td>
<% end %>
<td> <%= f.text_field :amount, :id => "amountField", :onchange => "change_total_price()" %> </td>
<td> <%= f.text_field :text, :id => "textField" %> </td>
<td> <%= f.text_field :price, :class => "priceField", :onChange => "change_total_price()" %> </td>
<td> <%= link_to_remove_fields "Remove Item", f %> </td>
</tr>
</table>
<% end %>
<p><%= link_to_add_fields "Add Item", f, :items %></p>
<p>
<%= f.label :total_price %><br />
<%= f.text_field :total_price, :class => "priceField", :id => "totalPrice" %>
</p>
<p><%= f.submit "Create"%></p>
<% end %>
<%= link_to 'Back', orders_path %>
create method in orders_controller.rb
def create
#order = Order.new(params[:order])
respond_to do |format|
if #order.save
flash[:notice] = 'Post was successfully created.'
format.html { redirect_to(#order) }
format.xml { render :xml => #order, :status => :created,
:location => #order }
else
format.html { render :action => "new" }
format.xml { render :xml => #order.errors,
:status => :unprocessable_entity }
end
end
end
Hopefully you can see what i cant
You need to pay careful attention to pluralization in Rails. In this case you're setting up a singular relationship to a plural thing, so it's presumed that you're actually calling a class named "Types" and not "Type".
has_one, belongs_to are singular
has_many is plural
Possible fixes:
class Item < ActiveRecord::Base
has_one :type
belongs_to :order
accepts_nested_attributes_for :type
validates_associated :type
end
class Type < ActiveRecord::Base
belongs_to :item
belongs_to :order
end
In rails, type is a reserved word. You have to rename your model to something else. Also you have to follow tadman's instruction about singular names for has_one association.
Reference
Reserved words in rails