How to save part_id in Association has and belongs to many? - ruby-on-rails

Model
class Assembly < ApplicationRecord
belongs_to :book
has_and_belongs_to_many :parts
end
Join table
class CreateJoinTableAssemblyPart < ActiveRecord::Migration[7.0]
def change
create_join_table :assemblies, :parts, id: false do |t|
t.index [:assembly_id, :part_id]
t.index [:part_id, :assembly_id]
end
end
end
Schema
create_table "assemblies_parts", id: false, force: :cascade do |t|
t.integer "assembly_id", null: false
t.integer "part_id", null: false
t.integer "assemblies"
t.integer "parts"
end
Controller
def create
#assembly = Assembly.new(assembly_params)
def assembly_params
params.require(:assembly).permit(:book_id, :part_id)
_Form.html
<div class="form-inputs">
<%= f.association :book %>
<%= f.association :parts %>
</div>
This way saves only the book_id
I need to save the part_id but it doesn't save and it doesn't even give an error

You need to whitelist the correct param key and an array of permitted scalar values - not a single value:
def assembly_params
params.require(:assembly)
.permit(:book_id, part_ids: [])
end
Check the logs for the correct param key to use.
Also remove the assemblies and parts columns from the assemblies_parts table. You don't need them and it just seems like an open invitation for bugs.

Related

How do I set/limit the input in a rails form to match another models table?

I'm quite new to programming and haven't been able to find any resources to help me with this. I have created two scaffolds Accounts and Cashbooks. I want users to be able to add an account (with a parameter of account_name) which will then be set as the parameters for the Cashbook account input. Ideally when adding a Cashbook transaction, I would want users to see a dropdown which will contain all the account_names of the Accounts which have been created.
Cashbook Model
class Cashbook < ActiveRecord::Base
belongs_to :account, foreign_key: :account_name
end
Cashbook Controller
def new
#cashbook = Cashbook.new
#cashbook.account(account_params[:account_name])
end
def create
#cashbook = Cashbook.new(cashbook_params)
#cashbook.account(account_params[:account_name])
def cashbook_params
params.require(:cashbook).permit(:date, :description, :account, :kind, :amount, :balance, :name)
params.require(:account).permit(:account_name)
end
Cashbook DB
class CreateAccounts < ActiveRecord::Migration
def change
create_table :accounts do |t|
t.string :account_name
t.boolean :operating_expense
t.boolean :cost_of_sales
t.boolean :sales
t.boolean :other_income
t.boolean :non_current_liability
t.boolean :non_current_asset
t.boolean :current_asset
t.boolean :current_liability
t.boolean :equity
t.integer :account_number
t.timestamps null: false
end
end
end
Account Model
class Account < ActiveRecord::Base
has_many :cashbook, foreign_key: :account_name
end
Account Controller
def new
#account = Account.new
end
def edit
end
def create
#account = Account.new(account_params)
end
def account_params
params.require(:account).permit(:account_name, :operating_expense, :cost_of_sales, :sales, :other_income, :non_current_liability, :non_current_asset, :current_asset, :current_liability, :equity, :account_number)
end
Cashbook db
class CreateCashbooks < ActiveRecord::Migration
def change
create_table :cashbooks do |t|
t.date :date
t.string :description
t.boolean :account
t.string :kind
t.integer :amount
t.timestamps null: false
end
end
end
You can use the collection_select form helper.
In your case, it could look something like
<%= collection_select(:cashbook, :account_name, Account.all, :account_name, :account_name) %>
Though you should also consider using the id column to associate models as per the Rails Associations Guide. If you change your models to use ids as the foreign key, you won't need to explicitly specify the foreign key in your has_many and belongs_to statements, and you can still create a select box that displays account names:
<%= collection_select(:cashbook, :account_id, Account.all, :id, :account_name) %>

Rails : Associating a record with a user who did not create that record

I have a user model and a patient model. Patients are not users of the application. Users are essentially staff members who are creating patient records. In some situations, the user who creates the patient's record is also that patient's physician. In other cases, the patient's physician could be a separate user.
I want to save the user id of the patient's physician to the patient model rather than the user who happened to create the patient. The implementation I am imagining is that I will have a dropdown field in the form for the user to select the patient's physician, including the option to select themselves. How can I do this? Am I even thinking about this the right way? Here is my current implementation:
class Patient < ApplicationRecord
belongs_to :user
class User < ApplicationRecord
has_many :patients
Patients Controller
class PatientsController < ApplicationController
def new
#patient = current_user.patients.build
end
def create
#patient = current_user.patients.build(patient_params)
if #patient.save
flash[:success] = "Patient Created!"
redirect_to new_referral_request_path(patient_id: #patient.id)
else
Rails.logger.info(#patient.errors.inspect)
render 'patients/new'
end
end
private
def patient_params
params.require(:patient).permit(:age, :user_id, insurance_ids: [], gender_ids: [], concern_ids: [], race_ids: [])
end
end
patient's schema:
create_table "patients", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "age"
t.string "user_id"
t.index ["user_id"], name: "index_patients_on_user_id"
end
I have two roles: one for staff and one for clinician. Staff users would be the ones creating patients. A staff user who creates a patient record may or may not be that particular patient's physician.
class User < ApplicationRecord
self.inheritance_column = :role
enum role: { Staff: 0, Clinician: 1}
Just add physician relation to Patient model:
class Patient < ApplicationRecord
belongs_to :user
belongs_to :physician, class_name: 'User'
end
Then modify schema:
create_table "patients", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "age"
t.string "user_id"
t.integer "physician_id"
t.index ["user_id"], name: "index_patients_on_user_id"
t.index ["physician_id"], name: "index_patients_on_physician_id"
end
Hint: use integer for your ids fields, if your ids are numeric.
(Of course, its better to do this through migration, see this post if you don't know how).
Then permit physician_id in params:
def patient_params
params.require(:patient).permit(:age, :user_id, :physician_id, insurance_ids: [], gender_ids: [], concern_ids: [], race_ids: [])
end
And finally add dropdown list in the form:
<%= form_for(#patient) do |f| %>
<%= f.select :physician_id, User.all.map { |u| [u.name, u.id] } %>
...other fields...
<% end %>
Now you can call both patient.user and patient.physician (which can be equal).

Instance Variable Definition in Controller Issue: Rails 5

I have a single user table with two roles defined using enums and Single Table Inheritance with two matching user sub classes for Staff and Clinician. Because I need a lot of information about clinicians that I don't need about Staff, I've created a clinician_profiles table and am using after_create :create_clinician_profile in the user model to create a stub for the clinician profile.
I am trying to build a page for clinicians to complete their profiles and am having trouble getting the instance variable defined in the controller so it pulls the appropriate clinician's profile into the view to render the form. I am getting the following error. Note that the user's id I'm logged in as is 104.
ActiveRecord::RecordNotFound in ClinicianProfilesController#edit
Couldn't find ClinicianProfile with 'id'=104
I feel like I'm close but don't know what I'm doing wrong. Any help would be greatly appreciated for a rookie!
I'm landing on the page using this link in the header:
<li><%= link_to "Manage My Profile", edit_clinician_profile_path(current_user) %></li>
Here are relevant parts of my user model:
class User < ApplicationRecord
self.inheritance_column = :role
enum role: { Staff: 0, Clinician: 1}
belongs_to :university
has_many :referral_requests
class Staff < User
validates :university_id, presence: true
end
class Clinician < User
has_many :lists
has_many :universities, through: :lists
has_one :clinician_profile
after_create :create_clinician_profile
end
Here's my ClinicianProfile model:
class ClinicianProfile < ApplicationRecord
has_many :clinician_profile_languages
has_many :languages, through: :clinician_profile_languages
has_many :clinician_profile_races
has_many :races, through: :clinician_profile_races
belongs_to :clinician
end
clinician_profiles schema
create_table "clinician_profiles", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "firstname"
t.string "lastname"
t.string "address1"
t.string "address2"
t.string "city"
t.string "state"
t.string "zip"
t.boolean "accepting_patients"
t.integer "rate"
t.string "license_number"
t.string "license_state"
t.string "school"
t.integer "year_graduated"
t.string "accepts_insurance"
t.boolean "sliding_scale"
t.text "bio"
t.boolean "verified"
t.integer "years_licensed"
t.integer "years_of_experience"
t.integer "clinician_id"
end
ClinicianProfilesController
class ClinicianProfilesController < ApplicationController
def edit
#clinician_profile = ClinicianProfile.find(params[:id])
end
def index
end
def show
end
def create
end
end
Here's the beginning of my view (edit.html.erb in /views/clinician_profiles)
<%= form_for(#clinician_profile) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
def edit
#clinician_profile = ClinicianProfile.find(params[:id])
redirect_to :index and return unless #clinician_profile
end

Setting columns to references in rails 4

In my web app, I have nodes and links. A link has two nodes. One node is a source node, and the other node is a target node. Basically, I want source and target columns in the database that hold references to nodes. I am trying to figure out how to implement this.
Here is the migration for the nodes model:
class CreateNodes < ActiveRecord::Migration
def change
create_table :nodes do |t|
t.string :name
t.integer :group
t.references :link, index: true
t.timestamps
end
end
end
Here is the node model:
class Nodes < ActiveRecord::Base
belongs_to :link
end
I am trying to figure out how to set up the migration for the links model. Here is what I have so far:
class CreateLinks < ActiveRecord::Migration
def change
create_table :links do |t|
t.integer :value
t.boolean :checked
t.timestamps
end
end
end
Here is what I have in my model:
class Links < ActiveRecord::Base
has_many :nodes
end
Would the correct migration look like this?
class CreateLinks < ActiveRecord::Migration
def change
create_table :links do |t|
t.integer :value
t.boolean :checked
t.references :source
t. references :target
t.timestamps
end
end
end
t.references :smith is basically a shortcut for t.integer :smth_id so if your Nodes belong to Links, then yes that construction seems correct.
not sure where your links#source and links#target point to though.

Rails - Single User Multiple "Roles?"

Having an invoice model which belongs to user, and a user table that associates a user as a particular role or multiple roles:
class CreateInvoices < ActiveRecord::Migration
def self.up
create_table :invoices do |t|
t.string :po_number
t.datetime :invoice_date
t.datetime :date_received
t.datetime :date_approved
t.text :clerk_note
t.integer :clerk_id
t.integer :approver_id
t.text :approver_note
end
end
class Invoice < ActiveRecord::Base
belongs_to :user
end
class CreateUsers < ActiveRecord::Migration
def self.up
create_table :users do |t|
t.string :first_name
t.string :last_name
t.string :username
t.string :email
t.boolean :account_clerk
t.boolean :approver
t.boolean :admin
end
end
class User < ActiveRecord::Base
has_many :invoices
end
In the invoice record, how do I assign an clerk_id and approver_id depending on the role set in the user model? Each invoice will have a clerk and approver, but both are users.
Likewise, how do I assign the clerk_note to the clerk_id and the approver_note to the approver_id? I'm assuming in this case, I can just refer to current_user, since the user logged in will be the one making the note, right?
I'm not sure what this is called, so in my Googling, I didn't know what to look for... thanks in advance for your help.
To answer your original question using your current models you can just create your view to display different fields based on the role of the user (this assumes the logged in user is in an instance variable named #user).
<% if (#user.approver) then %>
<%= f.text_area :approver_note %>
<% else %>
<%= f.text_area :clerk_note %>
<% end %>
Then in your controller you can set the value of clerk id or approver id again depending on the logged in user.
if (#user.approver) then
#invoice.approver_id = #user.id
else
#invoice.clerk_id = #user.id
end

Resources