I have a very simple rails application that collects "equipment" and assigns it to a "site"
class CreateEquipment < ActiveRecord::Migration[5.0]
def change
create_table :equipment do |t|
t.string :site_name
t.string :equip_name
t.string :equip_model
t.string :equip_make
t.string :equip_type
t.belongs_to :site
t.timestamps
end
end
end
class CreateSites < ActiveRecord::Migration[5.0]
def change
create_table :sites do |t|
t.string :site_name
t.timestamps
end
end
end
Two models "Equipment" and "Site"
class Equipment < ApplicationRecord
end
class Site < ApplicationRecord
has_many :equipment
end
I have set up the equipment belongs_to Site and site has_many Equipment.
In my equipment form I have a collection_select to choose the site to assign the equipment too.
<div class="field">
<%= f.label :site_name %>
<%= f.collection_select :site_name, Site.all, :site_name, :site_name, prompt: true %>
</div>
<div class="field">
<%= f.label :equip_name %>
<%= f.text_field :equip_name %>
</div>
<div class="field">
<%= f.label :equip_model %>
<%= f.text_field :equip_model %>
</div>
<div class="field">
<%= f.label :equip_make %>
<%= f.text_field :equip_make %>
</div>
<div class="field">
<%= f.label :equip_type %>
<%= f.text_field :equip_type %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
and on the site show page, I have begun to set up the page to show equipment.
<p>
<strong>Sitename:</strong>
<%= #site.site_name %>
</p>
<% #site.equipment.each do |equipment| %>
<p><%= equipment.equip_name %></p>
<% end %>
but I cannot see any equipment when I open the site show page.
I am not getting any faults or issues on the form or the page, I have allowed all params. I think I may have set up my collection_select incorrectly.
Update: Watching Michael Hartl's Ruby on Rails Tutorial Section 14.1.2 User/relationship associations and feel some enlightenment that anyone with this issue should get privy too.
Well I have learned alot over the time I have been playing with rails. Hopefully when a newbie finds this they will see the very simple error I made.
I didnt add the association to the site
class Equipment < ApplicationRecord
end
class Site < ApplicationRecord
has_many :equipment
end
should be
class Equipment < ApplicationRecord
belongs_to :site
end
class Site < ApplicationRecord
has_many :equipment
end
and the table should change from
class CreateEquipment < ActiveRecord::Migration[5.0]
def change
create_table :equipment do |t|
t.string :site_name
t.string :equip_name
t.string :equip_model
t.string :equip_make
t.string :equip_type
t.belongs_to :site
t.timestamps
end
end
end
class CreateEquipment < ActiveRecord::Migration[5.0]
def change
create_table :equipment do |t|
t.string :equip_name
t.string :equip_model
t.string :equip_make
t.string :equip_type
t.references :site
t.timestamps
end
end
end
I hope that helps someone :)
Related
Hope you all are well
I am creating a quiz application in which i have 3 models one question.rb, user.rb and result.rb
Question.rb
class Question < ApplicationRecord
validates :question, presence: true
validates :option1, presence: true
validates :option2, presence: true
validates :option3, presence: true
validates :option4, presence: true
validates :answer, presence: true
end
migrated file
class CreateQuestions < ActiveRecord::Migration[6.1]
def change
create_table :questions do |t|
t.text :question
t.text :option1
t.text :option2
t.text :option3
t.text :option4
t.text :answer
t.timestamps
end
end
end
result.rb
class CreateResults < ActiveRecord::Migration[6.1]
def change
create_table :results do |t|
t.text :user_choice
t.timestamps
end
end
end
Also question_id and User_id are the Foreign keys in this table.
result controller
class ResultController < ApplicationController
def create
#result=Result.create(user_choice: params[:user_choice],
question_id: params[:question_id],
user_id: current_user.id)
end
end
and finally
view/question/index
<div class="card o-hidden border-0 shadow-lg my-5">
<div class="card-body ">
<!-- Nested Row within Card Body -->
<div class="row py-5">
<div class="p-5">
<div class="text-center">
<h1 class="h4 text-gray-900 mb-4 ">Multiple-Choice Questions</h1>
</div>
<%= form_with model: #result ,url: result_path do |f| %>
<% #questions.each do |question| %>
<div>
<%= f.hidden_field :question_id, value: question.id %>
<%= f.hidden_field :user_id, value: current_user.id %>
<p><%= question.question %></p>
<% choices = [question.option1, question.option2, question.option3, question.option4] %>
<% choices.each do |c| %>
<div>
<%= f.radio_button :"user_choice[#{question.id}]", c %>
<%= f.label :user_choice, c %>
</div>
<% end %>
</div>
<% end %>
<div class="sub"> <%= f.submit "Submit", class:"btn btn-primary" %></div>
<% end %>
<div class="para1"><%= link_to 'New Question', new_question_path,class:"btn btn-primary btn-user" %>
</div>
</div>
</div>
</div>
</div>
</div>
Now everything is working perfectly the user choice is saving and user id is also saving current_user.id
Now the issue is question_id is not updating it's always show the id the last question have. In my cause it's 11. I don't know why it's not storing the id of the answered question.
Please i will be thankful if somebody help me in this.
class CreateResults < ActiveRecord::Migration[6.1]
def change
create_table :results do |t|
t.text :user_choice
t.timestamps
end
end
end
There is no question_id attribute for a result record.
If you meant to connect Question to Result you need to define the relationships on the models:
class Question < ApplicationRecord
has_many :results
end
class Result < ApplicationRecord
belongs_to :question
belongs_to :user
end
And you'll need your foreign keys on Result:
class CreateResults < ActiveRecord::Migration[6.1]
def change
create_table :results do |t|
t.text :user_choice
t.references :question
t.references :user
t.timestamps
end
end
end
Now Result will have question_id and user_id
I'm trying to create a form that creates a new exercise with muscle_groups that are primary and secondary to the exercise.
Here's the relevant part of the schema:
create_table "exercised_muscle_groups", force: true do |t|
t.integer "muscle_group_id"
t.integer "exercise_id"
t.string "used_as"
end
add_index "exercised_muscle_groups", ["exercise_id"], name: "index_exercised_muscle_groups_on_exercise_id", using: :btree
add_index "exercised_muscle_groups", ["muscle_group_id"], name: "index_exercised_muscle_groups_on_muscle_group_id", using: :btree
create_table "exercises", force: true do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "muscle_groups", force: true do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
end
Here's what I have for the models:
class Exercise < ActiveRecord::Base
has_many :exercised_muscle_groups, dependent: :destroy
has_many :muscle_groups, through: :exercised_muscle_groups
accepts_nested_attributes_for :muscle_groups
accepts_nested_attributes_for :exercised_muscle_groups
end
class MuscleGroup < ActiveRecord::Base
has_many :exercised_muscle_groups
has_many :exercises, through: :exercised_muscle_groups
accepts_nested_attributes_for :exercises
accepts_nested_attributes_for :exercised_muscle_groups
end
class ExercisedMuscleGroup < ActiveRecord::Base
belongs_to :exercise
belongs_to :muscle_group
end
Here's what I have so far for the controller actions for new and create:
def new
#exercise = Exercise.new
#exercise.exercised_muscle_groups.build
end
def create
#exercise = Exercise.new(exercise_params)
#exercise.save
#then loop through all muscle groups marked as primary and then create a record for each one with value of "primary" for used_as column
#then loop through all muscle groups marked as secondary and then create a record for each one with value of "secondary" for used_as column
#if all saves are successful, then redirect to show page for that exercise
#if any save unsuccessful, then redirect to new page with error message
end
Here's what I have for the form in the view. I know it's wrong and it doesn't work.
<%=form_for(#exercise) do |exercise_form| %>
<%= exercise_form.label :name %>
<%= exercise_form.text_field :name, class: 'text_field' %><br>
<div class="col-xs-12">
<% exercise_form.fields_for :exercised_muscle_groups do |muscle_group_form| %>
<%= muscle_group_form.label :primary %>
</div>
<% MuscleGroup.all.each do |muscle_group| %>
<div class="col-xs-6">
<span class="col-xs-3">
<%= check_box_tag "exercise[muscle_group_ids][]", muscle_group.id %>
</span>
<span class="col-xs-3">
<%= muscle_group.name %>
</span>
</div>
<% end %>
<div class="col-xs-12">
<%= muscle_group_form.label :secondary %>
</div>
<% MuscleGroup.all.each do |muscle_group| %>
<div class="col-xs-6">
<span class="col-xs-3">
<%= check_box_tag "exercise[muscle_group_ids][]", muscle_group.id %>
</span>
<span class="col-xs-3">
<%= muscle_group.name %>
</span>
</div>
<% end %>
<% end %>
<%= exercise_form.submit "Submit", class: "btn btn-lg btn-primary" %>
<% end %>
How do I set up the form for the exercise and controller actions? Am I overcomplicating this? Is there an easier way?
Any help would be greatly appreciated. Thanks!
Made a previous post about this but after a lot of testing and changing it's outdated.
I'm trying to tie users and activities together.(One user can have several activities. An activity can have several users). I'ts pretty much a multi-user agenda thing.
Whenever i create a new activity i can select users by checkbox which will be doing the activity.
I can't get it to work though; The users won't show up in my activity show. Printing #activity.users in my show results in #<ActiveRecord::Associations::CollectionProxy::ActiveRecord_Associations_CollectionProxy_User:0x43d2158> but looping it, or checking my activities.js shows nothing(The activities.js shows "users":[] in the activity. So I'm pretty certain they're not associated properly.
Here's some code:
The activities.js index method
def index
#activities = Activity.all
respond_to do |format|
format.html
format.js {render_json #activities.to_json(:include => [:pictogram ,:users]) }
end
end
The activities' form(Loops all users)
<%= form_for(#activity) do |f| %>
<% if #activity.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#activity.errors.count, "error") %> prohibited this activity from being saved:</h2>
<ul>
<% #activity.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :title %><br>
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :start_date %><br>
<%= f.date_select :start_date %>
</div>
<div class="field">
<%= f.label :end_date %><br>
<%= f.date_select :end_date %>
</div>
<div class="users">
<% for user in User.all %>
<label class="activity">
<%= check_box_tag "activity[user_ids][]", user.id %>
<%= user.name %>
</label>
<% end %>
</div>
<div class="pictograms">
<% for p in Pictogram.all %>
<% #f.fields_for :pictograms do |x| %>
<%= p %>
<% #end %>
<% end %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
The schema.rb
ActiveRecord::Schema.define(version: 20130911095113) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "activities", force: true do |t|
t.string "title"
t.date "start_date"
t.date "end_date"
t.integer "pictogram_id"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "activities", ["pictogram_id"], name: "index_activities_on_pictogram_id", using: :btree
create_table "activities_users", id: false, force: true do |t|
t.integer "activity_id"
t.integer "user_id"
end
add_index "activities_users", ["activity_id"], name: "index_activities_users_on_activity_id", using: :btree
add_index "activities_users", ["user_id"], name: "index_activities_users_on_user_id", using: :btree
create_table "pictograms", force: true do |t|
t.string "title"
t.string "url"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "users", force: true do |t|
t.string "name"
t.text "avatar"
t.date "birthdate"
t.datetime "created_at"
t.datetime "updated_at"
end
end
Activity.rb
class Activity < ActiveRecord::Base
belongs_to :pictogram
has_and_belongs_to_many :users
accepts_nested_attributes_for :pictogram, allow_destroy: false
accepts_nested_attributes_for :users, allow_destroy: false
end
User.rb
class User < ActiveRecord::Base
has_and_belongs_to_many :activities
validates_presence_of :name, :on => :create
validates_presence_of :birthdate, :on => :create
accepts_nested_attributes_for :activities, allow_destroy: false
end
And the activity params from my activities controller
def activity_params
params.require(:activity).permit(:title,
:start_date,
:end_date,
:users,
:pictogram)
end
Try sth like this:
class Activity < ActiveRecord::Base
belongs_to :pictogram
has_and_belongs_to_many :users
accepts_nested_attributes_for :pictogram, allow_destroy: false
def user_ids=(values)
self.users << User.find(values)
end
end
#controller
def activity_params
params.require(:activity).permit(:title,
:start_date,
:end_date,
{:user_ids =>[]},
:pictogram)
end
I suggest you try some minimalist debugging first,
User.create!(...) # create a valid user record
Activity.create!(...) # same as above
User.all.first.activities << Activity.all.first
User.all.first.activities.any?
See if this works, also keep an eye on your join_table and check that actual records are being persisted. Your schema looks good as well.
I think, none of them read about the strong_parameters with nested attributes :
You can easily define :users_attributes in permit parameters for nested_attributes.
activities controller :
def activity_params
params.require(:activity).permit(:title,
:start_date,
:end_date,
users_attributes: [:id])
end
This is the ideal way to do this. Thanks
I have a form from user
<%= form_for(#user) do |f| %>
<%= f.fields_for :businesses do |field| %>
<div class="field">
<%= field.label :address %>
<%= field.text_field :address %>
</div>
<div class="field">
<%= field.label :city %>
<%= field.text_field :city %>
</div>
<% end %>
<% end %>
It does not display my fields, but when i change businesses to business, then it shows, or if I remove the f from f.fields_for. But I don't think it properly saves into database.
my user model
class User < ActiveRecord::Base
has_many :businesses
accepts_nested_attributes_for :businesses
en
my business model
class Business < ActiveRecord::Base
attr_accessible :user_id, :address, :city
belongs_to :user
end
my bussiness migration
class CreateBusinesses < ActiveRecord::Migration
def change
create_table :businesses do |t|
t.integer :user_id
t.string :address
t.string :city
t.timestamps
end
end
end
Any suggestions as to what I'm doing wrong?
Thanks
You should build a business before it can display a form for it:
#user.businesses.build
Use that before using fields_for
Also check out this great gem for managing nested forms:
https://github.com/ryanb/nested_form
I have two models, Ingredients and Foods:
class Food < ActiveRecord::Base
belongs_to :user
has_many :ingredients
accepts_nested_attributes_for :ingredients
attr_accessible :name, :price
end
class Ingredient < ActiveRecord::Base
belongs_to :user
belongs_to :food
attr_accessible :ingredient_name, :quantity_used
end
The schemas for the two models are as follows:
create_table "foods", :force => true do |t|
t.string "name"
t.integer "user_id"
t.float "price"
t.string "ingredient_name"
end
create_table "ingredients", :force => true do |t|
t.string "ingredient_name"
t.integer "user_id"
t.integer "food_id"
t.integer "quantity_used"
end
I'm creating a form for Food which also creates/updates the Ingredient table as well. I have the form working, and the submit button updates the correct attributes, but I have other attributes in each table that I want to update as well. For example, in the Food Controller, I want to do something like ingredient.user_id = current_user.id. I understand I can access things through params[:food], but how do I access individual fields which aren't being updates by the form?
Right now, my form is:
<%= form_for(#food) do |f| %>
<div class="field">
<%= f.label :Name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :price %><br />
<%= f.number_field :price %>
</div>
<div>
<%= f.fields_for :ingredients do |builder| %>
<%= builder.label "Ingredient Used:" %>
<%= builder.text_field :ingredient_name %><br />
<%= builder.label "Quantity Used:" %>
<%= builder.text_field :quantity_used %><br />
<% end %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
How do I access this specific Food's ingredients in the Food#create action?
Thanks!
You might need to add :ingredients_attributes to attr_accessible in your Food model.
You can mess about with the params hash in the controller by iterating over the :ingredients_attributes or you can use assign_attributes.