Updating nested params not working.. whats wrong? - ruby-on-rails

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

Related

Name error while rendering

I need to render a sub form in my main form and i tried to render it in the main form
this issue has relation with three models
Class PrdItem model< ActiveRecord::Base
has_one :prd_allisland_flat_delivery, dependent: :destroy, inverse_of: :prd_item
accepts_nested_attributes_for :prd_allisland_flat_delivery, allow_destroy: true
has_many :prd_province_vise_deliveries, dependent: :destroy, inverse_of: :prd_item
accepts_nested_attributes_for :prd_province_vise_deliveries, allow_destroy: true
end
Class PrdAllislandFlatDelivery < ActiveRecord::Base
belongs_to :prd_item
end
Class PrdProvincevisedelivery < ActiveRecord::Base
belongs_to :prd_item
end
In prd_item/new.html.erb the _form.html.erb is rendered
in that _form.html.erb
i wrote this code fragment
<%= p.fields_for :prd_allisland_flat_deliveries do |i| %>
<%= render(:partial => 'prd_allisland_flat_delivery_field', :locals => {:f => p})%>
<% end %>
this is a fragment of that form partial
<div class="col-md-4">
<%= f.text_field(:delivery_period, {placeholder: '0', class: 'form-control input_border input_field_text_align_right'})%>
</div>
that gives me
undefined method
`delivery_period' for #
error
in _form.html.erb
<%= p.fields_for :prd_allisland_flat_deliveries do |i| %>
<%= render(:partial => 'prd_allisland_flat_delivery_field', :locals => {:f => i})%>
<% end %>
and
<%= f.text_field(:delivery_period, {placeholder: '0', class: 'form-control input_border input_field_text_align_right'})%>

nested form "Can't mass-assign protected attributes"

I have 3 models; Quote, Item, and Product.
My quote/new.html.erb is set up to render a partial which contains the item form, and in that item form a partial is rendered to choose a product.
the error: ActiveModel::MassAssignmentSecurity::Error in QuotesController#create
"Can't mass-assign protected attributes: products"
(I edited out irrelevant stuff in the following)
Quote.rb
class Quote < ActiveRecord::Base
attr_accessible :items_attributes
has_many :items, :dependent => :destroy
accepts_nested_attributes_for :items
end
Item.rb
class Item < ActiveRecord::Base
attr_accessible :price, :product_attributes
belongs_to :quote
belongs_to :product
accepts_nested_attributes_for :product
end
Product.rb
class Product < ActiveRecord::Base
attr_accessible :name, :item_make
has_many :items
accepts_nested_attributes_for :items
end
new.html.erb
<%= simple_nested_form_for #quote do |m| %>
<%= m.simple_fields_for :items, :html => { :multipart => true } do |quoteform| %>
<%= render "form", f: quoteform %>
<% end %>
<%= m.link_to_add "Add an item", :items %>
<%= m.button :submit %>
<% end %>
_form.html.erb
<%= f.simple_fields_for :products, :html => { :multipart => true } do |x| %>
<% render "layouts/styleselect", g: x %>
<% end %>
_styleselect.html.erb
<% g.hidden_field :item_make, :value => #item.make %>
<%= g.input :name, collection: Product.where(:item_make => 1), label: false, input_html: {:id=>"sst_style"} %>
So basically the nested form goes Quote->Item->Product, but item belongs to product, which maybe is causing the problem? I tried adding product_attributes or products_attributes to both the item model and the quote model, and the same with accepts_nested_attributes_for product(s).
Any help would be appreciated, thanks.
Looks like you need to make products singular.
<%= f.simple_fields_for :product, :html => { :multipart => true } do |x| %>
<% render "layouts/styleselect", g: x %>
<% end %>
You currently have:
<%= f.simple_fields_for :products, :html => { :multipart => true } do |x| %>

Rails: trouble with pending / accepted invitations using :conditions hash

I'm currently trying to make an app for uploading pics. there are users, albums, pics. The catch is that there can be multiple owners for each album, so in the form to create an album there is a check box portion where you highlight your friends names and "invite them" to be an owner. However I'm trying to make it so that an invite has to be "accepted" before ownership is shared. I'm trying to do this using a join table (album_user) and having a album and pending_album, which are distinguished by their :status when created
This is my
albums/new.html.erb (no issue here)
<%= form_for ([#user, #album]), :html => { :id => "uploadform" } do |f| %>
<div class="formholder">
<%= f.label :name %>
<%= f.text_field :name %>
<br>
<label>Hosts</label>
<% #user.friends.each do |friend| %>
<%= friend.name %>
<%= check_box_tag 'album[user_ids][]', friend.id, #album.users.include?(friend) %>
<% end %>
<%= f.label :description %>
<%= f.text_area :description %>
<br>
<%=f.submit %>
</div>
<% end %>
albums controller (issue here with status)
def create
#user = User.find(params[:user_id])
#album = #user.albums.build(params[:album].merge(:status => 'accepted'))
#friends = #user.friends.find(params[:album][:user_ids])
if #user.save
for friend in #friends
AlbumUser.create({:user_id => friend.id, :album_id => #album.id, :status => 'pending'})
# friend.albums.build(params[:album].merge(:status => 'pending'))
end
redirect_to user_album_path(#user, #album), notice: 'Album was successfully created.'
else
render action: "new"
end
end
user model
class User < ActiveRecord::Base
has_secure_password
attr_accessible :email, :name, :password, :password_confirmation, :profilepic
validates_presence_of :password, :on => :create
validates_format_of :name, :with => /[A-Za-z]+/, :on => :create
validates_format_of :email, :with => /\A([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i, :on => :create
validates_length_of :password, :minimum => 5, :on => :create
# validates :album, :uniqueness => true
has_many :album_users
has_many :albums, :through => :album_users, :conditions => {status: 'accepted'}
has_many :pending_albums, :through => :album_users, :source => :album, :conditions => {status: 'pending'}
accepts_nested_attributes_for :albums
has_many :friendships, :dependent => :destroy
has_many :friends, :through => :friendships, :conditions => "status = 'accepted'"
has_many :requested_friends, :through => :friendships, :source => :friend, :conditions => "status = 'requested'", :order => :created_at
has_many :pending_friends, :through => :friendships, :source => :friend, :conditions => "status = 'pending'", :order => :created_at
has_attached_file :profilepic
before_save { |user| user.email = email.downcase }
def name_with_initial
"#{name}"
end
private
def create_remember_token
self.remember_token = SecureRandom.urlsafe_base64
end
end
album model
class Album < ActiveRecord::Base
attr_accessible :name, :description, :user_ids, :status
validates_presence_of :name
has_many :album_users
has_many :users, :through => :album_users
has_many :photos
end
album_user model
class AlbumUser < ActiveRecord::Base
attr_accessible :album_id, :user_id, :status
belongs_to :album
belongs_to :user
end
ISSUE HERE: users/show.html.erb (where I have an icon for each album, but it seems like when albums are being created, they aren't saving as pending_albums even though their :status is 'pending'.
<% #user.pending_albums.each do |pending_album| %>
<div class="albumthumb">
<%= link_to image_tag(pending_album.photos ? pending_album.photos.first.avatar.url(:medium) : ("questionmark.png"), :size => "150x150"), user_album_path(#user, pending_album) %>
<br>
<%= pending_album.name %>
<% if signed_in? %>
<%= form_for(:album_user, :url => user_albums_path(:user_id => current_user.id, :album_id => pending_album.id)) do |f| %>
<%= f.submit "Accept Invitation" %>
<% end %>
<% end %>
</div>
<% end %>
<% #user.albums.each do |album| %>
<div class="albumthumb">
<%= link_to image_tag(!album.photos.empty? ? album.photos.first.avatar.url(:medium) : ("questionmark.png"), :size => "150x150"), user_album_path(#user, album) %>
<br>
<%= album.name %>
</div>
<% end %>
my issue is that the albums aren't saving as pending_albums. I thought my :conditions in the user model would help distinguish which are albums and which are pending albums? Everything seems to be falling under albums, even if they are supposed to be pending. Can anyone help?

Rails 3.1+ Simple Nested Form validation and Twitter Bootstrap control states

I need some help with handling validations with Twitter Bootstrap properly. The validations are working properly, the issue is Twitter Bootstrap Flash screen. This is what I mean:
No fields filled out and submitted returns: http://i.stack.imgur.com/8pvUc.png
The 2 of the required 4 fields submitted returns: http://i.stack.imgur.com/J6lCi.png
(notice that it doesn't flash the errors)
I have a basketball app where a Player can be on many Rosters(for player roster archiving purposes) and a Roster can have many Players.
Roster.rb
class Roster < ActiveRecord::Base
belongs_to :team
has_many :rosterizes
has_many :players, :through => :rosterizes
accepts_nested_attributes_for :players
validates_presence_of :jersey_number, :class_year
attr_accessible :jersey_number, :class_year, :players, :team_id, :players_attributes
end
Rosterizes.rb(poorly named I know...)
class Rosterize < ActiveRecord::Base
belongs_to :player
belongs_to :roster
attr_accessible :player_id, :roster_id
end
Player.rb
class Player < ActiveRecord::Base
has_many :rosterizes
has_many :rosters, :through => :rosterizes
validates_presence_of :first_name, :last_name
attr_accessible :first_name, :last_name, :active
end
_add_player_form.html.erb
(nested form)
<%= simple_nested_form_for #roster, :url =>player_added_team_path, :html => { :class => 'form-horizontal' } do |f| %>
<%= f.simple_fields_for :players, #roster.players.build do |x| %>
<%= x.input :first_name %>
<%= x.input :last_name %>
<%= x.input :active, :as => :hidden, :input_html => {:value => true} %>
<%end%>
<%=f.input :class_year %>
<%=f.input :jersey_number %>
<%=f.input :team_id, :as => :hidden, :input_html => {:value => params[:id]}%>
<div class="well">
<%= f.button :submit, :class => 'btn-primary icon-plus-sign btn-success', :value => "Add To Team" %>
</div>
<%end%>
Thanks for the help in advance!
SOLUTION
My problem is that every time the view was loaded, it was building a new form, thus never getting back the errors on the rollback
I made a change to my controller that builds for the nested form
Controller
def add_player
...
#new_player = #roster.players.build
end
And made the change accordingly to the view
_add_player_form.html.erb
<%= f.simple_fields_for :players, #new_player do |x| %>
...
<%end%>
This did the trick, thanks Mober!
the reason why only the first level validation is shown an the associated not is fairly simple... You do a <%= f.simple_fields_for :players, #roster.players.build do |x| %> which buildes the association ALWAYS new when the sites's rendered. What you want to is building the association only if it does not exists yet...
<% #roster.players.build if !#roster.players %>
<%= f.simple_fields_for :player do |player_form| %>
...
<% end %>
Twitter Bootstrap doesn't actually validate anything, it just provides styling for validation classes (error, success, etc).
Now, I'm not a Ruby expert by any means but it looks like you are ending your form early:
<%= f.simple_fields_for :players, #roster.players.build do |x| %>
<%= x.input :first_name %>
<%= x.input :last_name %>
<%= x.input :active, :as => :hidden, :input_html => {:value => true} %>
<%end%> <---- here
<%=f.input :class_year %>
<%=f.input :jersey_number %>
<%=f.input :team_id, :as => :hidden, :input_html => {:value => params[:id]}%>
Should be this?
<%= f.simple_fields_for :players, #roster.players.build do |x| %>
<%= x.input :first_name %>
<%= x.input :last_name %>
<%= x.input :active, :as => :hidden, :input_html => {:value => true} %>
<%= f.input :class_year %>
<%= f.input :jersey_number %>
<%= f.input :team_id, :as => :hidden, :input_html => {:value => params[:id]}%>
<% end %>

Complex Multi Model Rails From

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.

Resources