A User has many Skills through UserSkills.
A Skill has many Users through UserSkills.
In my new user form, I'm able to add checkboxes for skills but if I add a Proficiency (string) attribtue to the UserSkills model, how can I include this?
My current code:
<%= f.label :skills %>
<%= hidden_field_tag "user[skill_ids][]", nil %>
<% Skill.all.each do |skill| %>
<%= check_box_tag "user[skill_ids][]", skill.id, #user.skill_ids.include?(skill.id), id: dom_id(skill) %>
<%= link_to skill.skilltitle, skill_path(skill.id) %>
class User < ActiveRecord::Base
has_many :user_skills
accepts_nested_attributes_for :user_skills
end
class UserSkill < ActiveRecord::Base
belongs_to :user
belongs_to :skill
accepts_nested_attributes_for :skill
accepts_nested_attributes_for :user
end
... meanwhile.. in your form
<%= form_for #user do |f| %>
<%= f.fields_for :user_skills do |f2| %>
<%# add your user_skill attributes here %>
<%= f2.check_box :proficiency %>
<%= f2.fields_for :user do |f3| %>
<%# user attributes to go here %>
<% end %>
<% end %>
Related
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.
I'm trying to build a nested form for a survey and having problems with my params hash missing values from within the fields_for block.
I have the following models. The way the app works is that an admin creates a MiniPost and its MiniPostQuestions. Then a client creates a new MiniPostSurvey using one of the MiniPosts. The client then emails out SurveyInvites to users. When a user responds, a new SurveyResponse is created, along with a new QuestionAnswer for each MiniPostQuestion in the survey.
class MiniPost < ActiveRecord::Base
has_many :mini_post_questions
has_many :question_answers, through: :mini_post_questions
has_many :mini_post_surveys
belongs_to :employer
def questions
mini_post_questions
end
def surveys
mini_post_surveys
end
end
class MiniPostQuestion < ActiveRecord::Base
has_many :question_answers
belongs_to :mini_post
belongs_to :employer
def answers
question_answers
end
end
class MiniPostSurvey < ActiveRecord::Base
belongs_to :mini_post
belongs_to :employer
belongs_to :company
has_many :survey_invites
has_many :survey_responses, through: :survey_invites
def questions
mini_post.questions
end
end
class SurveyInvite < ActiveRecord::Base
belongs_to :mini_post_survey
has_many :survey_responses
def responses
survey_responses
end
end
class SurveyResponse < ActiveRecord::Base
belongs_to :survey_invite
has_many :question_answers
has_many :mini_post_questions, through: :question_answers
end
class QuestionAnswer < ActiveRecord::Base
belongs_to :survey_response
belongs_to :mini_post_question
validates :answer, presence: true
end
Here is my response form.
<div class="form-box">
<%= form_for #response, url: "/survey?key=#{#invite.key}", method: :post, html: { role: 'form' } do |f| %>
<% #questions.each do |question| %>
<div class="form-group">
<%= f.fields_for :mini_post_questions, question do |q| %>
<%= q.fields_for :question_answers, question.question_answers.build do |a| %>
<%= f.label question.question %>
<%= a.text_area :answer, class: 'form-control' %>
<%= a.hidden_field :survey_response_id, value: #survey.id %>
<% end %>
<% end %>
</div>
<% end %>
<div><%= f.submit "Submit", :class => "btn btn-primary" %></div>
<% end %>
</div>
My form renders correctly, however when I submit it, my params hash looks like this:
{"utf8"=>"✓",
"authenticity_token"=>"p8Tky2So10TH4FUUvLKhIh7j2vjNN39b3HDsF0cYE14=",
"survey_response"=>{"mini_post_questions"=>{"question_answers"=>{"answer"=>"", "survey_response_id"=>"11"}}},
"commit"=>"Submit",
"key"=>"e4fab42244db2286d471082696",
"controller"=>"surveys",
"action"=>"create"}
I would expect a mini_post_question key for each question, but I'm not sure how to get to that point.
I think you are on the right track, but you need to have your models accept nested attributes for the objects that you want in your form.
So I think in your SurveyResponse model, you would have
class SurveyResponse < ActiveRecord::Base
belongs_to :survey_invite
has_many :question_answers
accepts_nested_attributes_for :question_answers
has_many :mini_post_questions, through: :question_answers
end
Also, since it looks like you are not modifying the mini question here, I would say that you don't need to accept nested attributes for the questions, but just have a hidden field that assigns the mini_question_id to the question_answer
So your form should be something like this
<div class="form-box">
<%= form_for #response, url: "/survey?key=#{#invite.key}", method: :post, html: { role: 'form' } do |f| %>
<% #questions.each do |question| %>
<div class="form-group">
<%= f.fields_for :question_answers, #survey.question_answers.build do |q| %>
<%= q.label question.question %>
<%= q.text_area :answer, class: 'form-control' %>
<%= q.hidden_field :mini_post_question_id, value: question.id %>
<% end %>
</div>
<% end %>
<div><%= f.submit "Submit", :class => "btn btn-primary" %></div>
<% end %>
</div>
Since your form is accepting nested attributes for question_answers, you won't need to supply the survey_id.
This should get you closer to what you would need in your form.
So there is a plethora of questions about the "uninitialized constant" error, and it's almost always due to an incorrectly specified association (e.g. plural model names instead of singular, incorrectly writing your association inside the model, etc). My models and form look spotless, so maybe this is something new (or I'm blind)?
A "user" has one "move". A "move" has many "neighborhood_preferences", and through this, many "neighborhoods".
Models:
class User < ActiveRecord::Base
has_one :move
accepts_nested_attributes_for :move, allow_destroy: true
end
class Move < ActiveRecord::Base
belongs_to :user
has_many :neighborhood_preferences
has_many :neighborhoods, through: :neighborhood_preferences
accepts_nested_attributes_for :neighborhood_preferences, allow_destroy: true
end
class NeighbhoodPreference < ActiveRecord::Base
belongs_to :neighborhood
belongs_to :move
end
class Neighborhood < ActiveRecord::Base
belongs_to :city
has_many :neighborhood_preferences
has_many :moves, through: :neighborhood_preferences
end
View:
<%= simple_form_for(#user, :html => { class: :form } ) do |u| %>
<%= u.fields_for :move do |m| %>
<div>
<%= m.label :start_date %>
<%= m.date_field :start_date %>
</div>
<div>
<%= m.label :end_date %>
<%= m.date_field :end_date %>
</div>
<div>
<%= m.label :min_price %>
<%= m.text_field :min_price %>
</div>
<div>
<%= m.label :max_price %>
<%= m.text_field :max_price %>
</div>
<%= m.association :neighborhood_preferences %>
<% end %>
<%= u.submit "Save Changes" %>
<% end %>
There is a typo in class name NeighbhoodPreference.
I have recipe and ingredient in a many to many relation.
I have defined the following commands in my presentation.
<div>
<%= render :partial => 'ingredients/form',
:locals => {:form => recipe_form} %>
</div>
the partial begins with
<%= form_for(#ingredient) do |ingredient_form| %>
but received #ingredient nill.
Then I tried
<%= recipe_form.fields_for :ingredients do |builder| %>
<%= render 'ingredient_fields', f: builder %>
<% end %>
where my render was
<p class="fields">
<%= f.text_field :name %>
<%= f.hidden_field :_destroy %>
</p>
but nothing was printed.
then I tried
<% #recipe.ingredients.each do |ingredient| %>
<%= ingredient.name %>
<% end %>
and only then all of the ingredients were printed.
What was I doing wrong in the previous tries ?
Thank you.
my ingredient recipe relation defined as follows
class Ingredient < ActiveRecord::Base
has_many :ingredient_recipes
has_many :recipes, :through => :ingredient_recipes
...
class Recipe < ActiveRecord::Base
has_many :ingredient_recipes
has_many :ingredients, :through => :ingredient_recipes
...
accepts_nested_attributes_for :ingredient_recipes ,:reject_if => lambda { |a| a[:content].blank?}
class IngredientRecipe < ActiveRecord::Base
attr_accessible :created_at, :ingredient_id, :order, :recipe_id
belongs_to :recipe
belongs_to :ingredient
end
You don't exactly specify what you are trying to do, so I am presuming you have a page that shows a recipe, with many ingredients that can be edited and added to. In your controller you have something like:
class RecipeController < ApplicationController
def edit
#recipe = Recipe.find(params[:id]
end
end
I am also presuming that you are looking to have a form that post backs to the create action. I therefore think you want a form like this:
<%= form_for #recipe do |form| %>
<%= label_for :name %>
<%= text_field :name %>
<%= form.fields_for :ingredients do |ingredients_fields| %>
<div class="ingredient">
<%= f.text_field :name %>
<%= f.hidden_field :_destroy %>
</div>
<% end %>
<% end %>
Also, change your recipe to accept nested attributes for ingredients, not ingredient_recipes:
class Recipe < ActiveRecord::Base
has_many :ingredient_recipes
has_many :ingredients, :through => :ingredient_recipes
...
accepts_nested_attributes_for :ingredients, :reject_if => lambda { |a| a[:content].blank?}
And finally, add attr_accessible for your content:
class Ingredient < ActiveRecord::Base
attr_accessible :content
...
Does that work for you?
In this scenario I can insert values to the Member table and the Club table. But there is a field called :task in the memberships table that I want to submit a value to, and in the Memberships table member_id and club_id are inserted automatically by Rails. How do I include the task field in the form below? Thank you in advance.
View/form:
<%= form_for #member ,:url=>{:action =>"create"} do |f| %>
<%= f.text_field :email %>
<%= f.fields_for :clubs do |s| %>
<%= s.text_field :name %>
<% end %>
<%= f.submit "submit" %>
<% end %>
Models
class Member < ActiveRecord::Base
has_many :clubs ,:through=> :memberships
has_many :memberships
accepts_nested_attributes_for :clubs
attr_accessible :clubs_attributes
end
class Club < ActiveRecord::Base
has_many :members ,:through=>:memberships
has_many :memberships
end
class Memberships < ActiveRecord::Base
belongs_to :Member
belongs_to :Club
end
<%= f.fields_for :memberships do |m| %>
<%= m.text_field :task %>
<%= m.fields_for :clubs do |s| %>
<%= s.text_field :name %>
<% end %>
<% end %>