How to change existing model attribute through association - ruby-on-rails

I have two tables: invoices and Invoice_Line_Items , invoice has_many Invoice_Line_items. Invoice_Line_Items belongs_to Invoice. Invoice has its foreign key in Invoice_line_items. When I create a new invoice, I choose the different Invoice_line_items and then save. However when I go and check the Invoice_line_item its invoice_id: is nil. It does not update the invoice_id foreign key in each of the Invoice_line_item.
update
It is true I am saving the child item before the parent (invoice).
models
class Invoice < ActiveRecord::Base
belongs_to :client
has_many :proposal_line_items, dependent: :destroy
has_many :suppliers, :through => :proposal_line_items
end
class Proposal_Line_Item < ActiveRecord::Base
belongs_to :proposal
belongs_to :supplier
belongs_to :invoice
end
form_for Invoice
<%= form_for(#invoice) do |f| %>
<% if #invoice.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#invoice.errors.count, "error") %> prohibited this invoice from being saved:</h2>
<ul>
<% #invoice.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :fecha_de_expedicion %><br>
<%= f.datetime_select :fecha_de_expedicion %>
</div>
<div class="field">
<%= f.label :invoice_line_item %><br>
<%= collection_select( :invoice_line_item, :invoice_line_item_id, #invoice_line_items, :id, :supplier_id, {}, {:multiple => true}) %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
thank you

Related

Provide another model's fields for nested form in Rails

I have a Rails app I'm building to manage a fantasy tennis bracket game.
Here are my models.
The game where the players will submit their picks:
class Game < ActiveRecord::Base
belongs_to :user
belongs_to :event
has_many :picks, dependent: :destroy
accepts_nested_attributes_for :picks
The matches where I match up two tennis players:
class Match < ActiveRecord::Base
belongs_to :event
belongs_to :player_1, class_name: "Player"
belongs_to :player_2, class_name: "Player"
has_many :picks, dependent: :destroy
The pick model.
class Pick < ActiveRecord::Base
belongs_to :game
belongs_to :match
I am using a nested form inside of another form which I have working.
<%= form_for(#game) do |f| %>
<% if #game.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#game.errors.count, "error") %> prohibited this game from being saved:</h2>
<ul>
<% #game.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :user_id %><br>
<%= f.collection_select(:user_id, User.all, :id, :name) %>
</div>
<div class="field">
<%= f.label :event_id %><br>
<%= f.collection_select(:event_id, Event.all, :id, :title) %>
</div>
<div class="field">
<%= f.label :score %><br>
<%= f.number_field :score %>
</div>
<% #matches.each do |g| %>
<%= f.fields_for :picks do |ff| %>
<fieldset>
<%= ff.label :match_id %>
<%= ff.text_field :match_id %>
<%= ff.label :winner, "Select the Winner" %>
<%= ff.text_field :winner %>
</fieldset>
<br>
<% end %>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
I would like to use the fields from the Match model to populate the fields on the Pick model. For example, the Match has two players, I want to be able to pull the player's names into the :picks form, and will probably use an f.select on them.
I have some player data on the Match model I want to dynamically pull into the Pick model. Can't figure out how to query the database and get the field attributes to be accessed by the Pick nested form. Any help would be appreciated.
Here's what I'd do.
Get rid of "games"
Make "picks" the model to store "game" information
I think the major issue you have currently is the Game and Pick models are trying to do the same thing.
#app/models/match.rb
class Match < ActiveRecord::Base
# columns id | event_id | name | player_1 | player_2
belongs_to :event
has_many :picks
belongs_to :player_1, class_name: "Player", primary_key: :player_1
belongs_to :player_2, class_name: "Player", primary_key: :player_2
def players
[player_1, player_2]
end
end
#app/models/pick.rb
class Pick < ActiveRecord::Base
# columns id | user_id | match | winner | etc
belongs_to :user
belongs_to :match, primary_key: :match
has_one :winner, primary_key: :winner
end
This means you'll be able to do the following:
#app/views/picks/new.html.erb
<% #matches.each do |match| %>
<%= match.name %>
<%= form_for match.picks.new do |f| %>
<%= f.hidden_field :match, match.id %>
<%= f.collection_select :winner, match.players, :id, :name, prompt: "Who will win?" %>
<%= f.submit %>
<% end %>
<% end %>
#app/controllers/picks_controller.rb
class PicksController < ActionController::Base
def new
#matches = Match.all
end
def create
#pick = Pick.new pick_params
#pick.save
end
private
def pick_params
params.require(:pick).permit(:match, :winner).merge(user_id: current_user)
end
end
This will give you the ability to "pick" the players in the most simple & extensible way.

RubyOnRails - Creating new objects with relations

i have 2 models, User and Technician
class User < ActiveRecord::Base
has_one :technician
end
class Technician < ActiveRecord::Base
belongs_to :user
validates :user, presence: true
end
When creating a new Technician and trying to associate with an existing User it gives the error: User cannot be blank
the view of Technician.new (form) is:
<%= form_for(#technician) do |f| %>
<% if #technician.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#technician.errors.count, "error") %> prohibited this technician from being saved:</h2>
<ul>
<% #technician.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :codigo %><br>
<%= f.number_field :codigo %><br><br>
<%= f.label :user_id %><br>
<%= f.select :user_id, options_for_select(User.all.map{|u|[u.nome, u.id]}) %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
What am I doing wrong if, selecting an user from the select it won't associate it to the attribute user_id?
Thanks
Try using with collect like this
<%= f.select :user_id, User.all.collect {|u|[u.nome, u.id]}) %>
OR
If you are using Rails 4,you can use pluck
<%= f.select :user_id, User.pluck(:nome, :id))
For more details see this API
If that doesn't work,change your validation in Technician model like this
class Technician < ActiveRecord::Base
belongs_to :user
validates :user_id, presence: true
end
Update
As you are using Rails4,you should be adding user_id to the permitted parameters like this
def your_params
params.require(:technician).permit(:user_id,:codigo)
end

How to include both dynamic select menu and nested attributes together in rails?

Consider i have three tables users, countries, states. I have a page to add a new user and when i add a new user i have to list the countries in the select box and on selecting the country the multiple select box should be loaded with the states of the country and i should be able to select the desired states.
Similarly i can click on the add button to add another select box and select another country and select states that belongs to that country and so on. And i know this needs nested attributes and dynamic select menu functionality but do not know how i can use these together.
The following are the ones that i tried
Models:
class Country < ActiveRecord::Base
has_many :states
attr_accessible :name
end
and
class User < ActiveRecord::Base
serialize :state_id
has_many :user_countries
accepts_nested_attributes_for :user_countries, :allow_destroy => true
has_many :state
attr_accessible :username, :user_countries_attributes
end
and
class State < ActiveRecord::Base
belongs_to :country
attr_accessible :name, :country_id
end
and
class UserCountry < ActiveRecord::Base
serialize :state_id
belongs_to :users
attr_accessible :country_id, :user_id, :state_id
end
Also the following image shows what i am trying to accomplish clearly
UPDATE
<%= form_for(#user) do |f| %>
<% if #user.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#user.errors.count, "error") %> prohibited this user from being saved:</h2>
<ul>
<% #user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :username %><br />
<%= f.text_field :username %>
</div>
<%= f.fields_for :user_countries do |country| %>
<%= render "user_country_fields", :f => country %>
<% end %>
<div class="add_variant"><%= link_to_add_fields "Add Country", f, :user_countries %></div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Update1:
<div class="entry_field">
<label>Country :</label>
<div id="field_country">
<%= f.collection_select :country_id, Country.all, :id, :name, :prompt => 'Select Country' %>
</div>
<div id="field_state">
<%= f.collection_select :state_id, State.all, :id, :name, {:prompt => 'Select State'}, { :multiple => true } %>
</div>
<%= link_to_remove_fields "remove", f %></div>
You can use nested_form (https://github.com/ryanb/nested_form) to achieve this in following way,
<%= nested_form_for(#user) do |f| %>
....
<%= f.fields_for :user_countries do |country| %>
<%= render "user_country_fields", :f => country %>
<% end %>
<div class="add_variant"><%= f.link_to_add "Add" :user_countries %></div>
<div class="actions">
<%= f.submit %>
</div>
Similarly, in partial
<%= f.link_to_remove "Remove" %>

Nested Attributes in Form Not showing

I have the 3 Models, that says a Voter has many votes and i'm trying to get the voter to vote on the same form as when the voting object is created but the field in my form isn't showing.
Here are my models:
class Voter < ActiveRecord::Base
attr_accessible :email_address, :verification_code, :verified, :votes_attributes
has_many :votes, :class_name => "Vote"
accepts_nested_attributes_for :votes
end
class Vote < ActiveRecord::Base
belongs_to :entry
belongs_to :voter
attr_accessible :entry, :voter, :voter_id
end
And in my form I have:
<%= form_for(#voter) do |f| %>
<% if #voter.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#voter.errors.count, "error") %> prohibited this voter from being saved:</h2>
<ul>
<% #voter.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :email_address %><br />
<%= f.text_field :email_address %>
</div>
<div class="field">
<%= f.label :verification_code %><br />
<%= f.text_field :verification_code %>
</div>
<div class="field">
<%= f.label :verified %><br />
<%= f.check_box :verified %>
</div>
<div class="field">
<% f.fields_for :votes do |builder| %>
<fieldset>
<%= builder.label :votes, "Entry" %>
<%= collection_select(:entry, :entry_id, Entry.all, :id, :email_address, :prompt => 'Please select an Entry') %>
<% end %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
But the votes field isn't showing. And I can't understand why.
In rails 3 you need to use:
<%= f.fields_for :votes do |builder| %>
This will fix the problem.

Rails 3.1 - Editing Attributes in join models?

I'm having real trouble getting my head around editing attributes in has_many through join models. I've set up a very simple app to experiment with; Recipes, Ingredients and Recipe_Ingredients (the join).
Can anyone help with making this work as it should? As it is, it'll pulling through 'qty' from the join model, but not the actual ingredient.
I've put a public repo up that anyone can download to play with: https://github.com/EssentialMusic/Recipes
The models:
class Ingredient < ActiveRecord::Base
attr_accessible :name
has_many :recipe_ingredients, :dependent => :destroy
has_many :recipes, :through => :recipe_ingredients
end
class Recipe < ActiveRecord::Base
attr_accessible :author, :description, :name, :recipe_ingredients_attributes, :ingredients_attributes
has_many :recipe_ingredients, :dependent => :destroy
has_many :ingredients, :through => :recipe_ingredients
accepts_nested_attributes_for :ingredients, :reject_if => lambda { |a| a[:name].blank? }, :allow_destroy => :true
accepts_nested_attributes_for :recipe_ingredients
end
class RecipeIngredient < ActiveRecord::Base
belongs_to :recipe
belongs_to :ingredient
attr_accessible :measure, :qty, :special_instructions
end
The form
<%= form_for(#recipe) do |f| %>
<% if #recipe.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#recipe.errors.count, "error") %> prohibited this recipe from being saved:</h2>
<ul>
<% #recipe.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :author %><br />
<%= f.text_field :author %>
</div>
<div class="field">
<%= f.label :description %><br />
<%= f.text_area :description %>
</div>
<div>
<%= f.fields_for :recipe_ingredients do |ri| %>
<%= ri.text_field :qty %> -
<%= ri.fields_for :ingredients do |i| %>
<%= i.text_field :name %><br>
<% end %>
<% end %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Cheers!!
Substitute the ri with f in the second nested fields_for like this:
<%= f.fields_for :recipe_ingredients do |ri| %>
<%= ri.text_field :qty %> -
<%= **f**.fields_for :ingredients do |i| %>
<%= i.text_field :name %><br>
<% end %>
<% end %>

Resources