Rails collection_select passing id - ruby-on-rails-4

I've read a bunch of questions but none of them are helping me with this problem. I am trying to create a form to make new forums but cannot get them to use the right category id.
<%= f.collection_select :category_id, Category.all, :id, :name %>
This creates a new forum but the id is not the category id from the drop down list. Here is the forums model
def new
#forum = Forum.new
end
def create
#forum = Forum.new(forum_params)
if #forum.save
redirect_to root_url
else
render 'new'
end
end
private
def forum_params
params.require(:forum).permit(:category_id, :name, :description )
end
end
Not quite sure what I am doing wrong here. Is it something to do with the foreign key? Any help would really be appreciated.
UPDATE
Forum Model
class Forum < ActiveRecord::Base
belongs_to :category
has_many :topics, dependent: :destroy
end
Category Model
class Category < ActiveRecord::Base
has_many :forums, dependent: :destroy
end

There is basically no category_id in the Forum model.
Here is a couple of things you can do to troubleshoot this. Run:
rails dbconsole
.schema
Check to see if you have category_id or not. If not, create a new migration for this.
Your initial code is correct. For some reason, I misread that your collection_select was already bound to the model.

Related

Ruby on Rails - Edit/Update creating new records instead of updating

I have seen the other links to this similar question but none of them seem to work in my case.
My update action is creating new records in mysql database
My app consists of 3 models
FashionModel
ModelProfile and
Measurement
They are defined as follows:
class FashionModel < ActiveRecord::Base
has_secure_password
has_one :model_profile
has_one :measurement
accepts_nested_attributes_for :model_profile
accepts_nested_attributes_for :measurement
end
class ModelProfile < ActiveRecord::Base
belongs_to :fashion_model
end
class Measurement < ActiveRecord::Base
belongs_to :fashion_model
end
The fashion_model_controller.rb is as follows:
class FashionModelsController < ApplicationController
def new
#fashion_model = FashionModel.new
end
def create
#fashion_model = FashionModel.new(fashion_models_sign_up_params)
if #fashion_model.save
flash[:success] = "Welcome to Meriad"
session[:fashion_model_id] = #fashion_model.id
redirect_to edit_fashion_model_path(#fashion_model)
else
render 'new'
end
end
def edit
#fashion_model = FashionModel.find(params[:id])
#fashion_model.build_model_profile
#fashion_model.build_measurement
end
def update
#fashion_model = FashionModel.find(params[:id])
if #fashion_model.update(fashion_models_edit_params)
flash[:success] = "Saved!"
redirect_to fashion_model_path(#fashion_model)
else
render 'edit'
end
end
def show
#fashion_model = FashionModel.find(params[:id])
end
end
The fashion_model_edit_params are
def fashion_models_edit_params
params.require(:fashion_model).permit(:first_name,
:last_name,
:email,
:password,
model_profile_attributes: [:id,
:location,
:bio, :gender,
:phone_number,
:rate,
:profile_image,
:birthdate],
measurement_attributes: [:id,
:feet,
:inches,
:bust,
:waist,
:hips,
:dress,
:shoes,
:hair,
:eyes])
end
I want something on these lines:
The fashion model signs up to the app through new.html.erb (which is stored in the fashion_models table)
The index.html.erb contains a list of all fashion_models with an option to edit information (update their profile)
The edit.html.erb contains fields from the model_profiles table as well as the measurements table, both of which have the foreign keys to the fashion_models table.
My fashion_models/new.html.erb template is pretty straightforward containing first_name, last_name, email, password.
My fashion_models/edit.html.erb template is something like:
<%= form_for #fashion_model do |f| %>
# fashion_model fields here
<%= f.fields_for :model_profile do |t| %>
# model_profile fields here
<% end %>
<%= f.fields_for :measurement do |t| %>
# measurement fields here
<% end %>
<% end %>
Now, whenever I edit a fashion_model/:id, the model_profile and measurement create a new record in the database rather than updating the existing record. Also, when I am on the Edit Profile page, none of the fields pre populate with the existing data. I have to manually enter all the data again.
First, I thought it was because of the build methods, but when I remove them, the fields_for do not display.
Appreciate any help!
You're probably making a mess with their routes.
It works like this:
form_for calls #fashion_model.new_record?
IF True: It will submit to POST /fashion_model, and create an object.
IF False: It will submit to PUT /fashion_model/:id, and update an object.
As you can see, it just depends if the object already exists in the database or not. So, check again, where you are using the form_for and which object you are passing it.
For questions with the routes, see: http://guides.rubyonrails.org/routing.html
So I finally figured out a way to do this. Hope it helps someone.
My problem was that I had 2 fields_for inside one form_for and I needed to update 2 models with to these forms.
I tired using callbacks like after_action :create_model_profile and after_action :create_measurement. And in both of these methods I tried to save fashion_model_id as the :id of the newly created fashion_model.
But since callbacks are considered as code smells, I wanted a better solution.
Instead of creating a form_for #fashion_models, I wrote a helper method as follows
# app/helpers/form_helper.rb
module FormHelper
def setup_fashion_model(fashion_model)
fashion_model.model_profile ||= ModelProfile.new
fashion_model.measurement ||= Measurement.new
fashion_model
end
end
and in my form_for I used something like
form_for(setup_fashion_model(#fashion_model)) do |f|
...
end
This created a new instance of ModelProfile and Measurement if it did not persist in the database.
It then of course solved the problem of pre populating the fields which contained data.
This was it. Simple solution, but I'd been there scratching my head.
Hope it helps.

Getting a count value between many different models and associations

I've been wondering what is the easiest way of getting a count value between several different models and associations.
I want to have something like this in my view
shop.receipts.articles.complaints.complaint_reviews.count
Here are my models and associations between them:
class Shop < ActiveRecord::Base
has_many :receipts
end
class Receipt < ActiveRecord::Base
has_many :articles, dependent: :destroy
belongs_to :shop
accepts_nested_attributes_for :articles, allow_destroy:true, :reject_if => :all_blank
end
class Article < ActiveRecord::Base
belongs_to :receipt
has_one :complaint
end
class Complaint < ActiveRecord::Base
belongs_to :article
has_many :complaint_reviews
end
class ComplaintReview < ActiveRecord::Base
belongs_to :complaint
end
I'm inferring that you want the count of all complaint_reviews that are associated with a particular shop.
In that case, the following is what you need:
shop = # get shop according to your criteria
ComplaintReview.
joins(complaint: {article: {receipt: :shop}}).
where(shops: {id: shop.id}).
count
I suppose you could save the shop joins, by applying the condition on the shop_id column of receipts; like so:
ComplaintReview.
joins(complaint: {article: :receipt}).
where(receipts: {shop_id: shop.id}).
count
Result should be the same for both if all receipts have a shop associated. But I'd opt for the first method.
The thing to keep in mind here is to 'start' with the model of which you ultimately want the count of.
Also, had there been any one-to-many relationships, you would have grouped the results by "complain_reviews.id" and then performed the count.
Ok so thanks to the code above I managed to come up with a working solution:
#shops_controller.rb:
def show
#count = ComplaintReview.
joins(complaint: {article: {receipt: :shop}}).
where(shops: {id: #shop.id}).
count
respond_with(#shop)
end
#shops/show.html.erb:
<%= #count %>
Thanks a lot for the help.

building nested resources for a form

I have a class User which has sub classes IndividualUser and BusinessUser (through STI). IndividualUser and BusinessUser have a many-to-many association and are linked through a join table called Employees.
Also, a User can have an Account.
I'm trying to set up a nested form, and am struggling to create the required objects.
My models:
class User
has_one :account
end
class IndividualUser < User
has_many :business_users, :through => :employees
has_many :employees
end
class BusinessUser < User
has_many :individual_users, :through => :employees
has_many :employees
end
class Employee < ActiveRecord::Base
belongs_to :business_user
belongs_to :individual_user
end
class Account
belongs_to :user
end
Now, in my controller, I am able to create a new account for an individual user:
# GET /individual_users/new
def new
#individual_user = IndividualUser.new
#individual_user.build_account
end
This works fine.
However, when I try to create a business_user, then individual_users, and then an account for each individual_user:
# GET /business_users/new
def new
#business_user = BusinessUser.new
#business_user.employees.build()
#business_user.employees.each do |employee|
#individual_user = employee.build_individual_user
#individual_user.build_account
end
end
I get the following error:
undefined method `build_account' for nil:NilClass
It appears as though #individual_user is not being created.
I'm not sure why I'm getting this error. Any ideas?
What's really strange, is that if I instead move the code to the view, it appears to work. i.e. in my view:
<% #business_user.employees.each do |employee| %>
<% employee.individual_user.build_scoot_account %>
<% employee.individual_user.scoot_account.id = 2 %>
<%= employee.individual_user.scoot_account.id %>
<% end %>
This displays "2".

ActiveRecord - Display columns from multiple associations

I have a user, user_profile and profile_type models. A user has_many user_profiles, a user_profile belongs_to a user and belongs_to a profile_type and a profile_type has_many user_profiles.
I have been reading on how to get this work but I am having problems figuring this out and any help would be much appreciated.
I know I could do this with SQL with a statement like this (freehand SQL, excuse mistakes), but I want to use ActiveRecord.
Select up.id, u.user_id, pt.connection_type
from user u
join user_profile up
on u.user_id = up.user_id
join profile_type pt
on pt.profile_type_id = up.profile_type_id
where u.username = "test"
I want to return nested user_profile objects for an associated user but I want the user_profile object to contain the profile_type.connection_type instead of the profile_type.profile_id.
Currently, if I do this,
user.user_profiles.all
add then iterate through the nested user_profiles that are returned, this is my output:
{
:id
:user_id
:profile_type_id
}
What I want is:
{
:id
:user_id
:profile_type.connection_type (instead of profile_type.profile_type_id)
}
User Model
class User < ActiveRecord::Base
has_many :user_profiles, autosave: true
has_many :account_settings, autosave: true
end
User_Profile Model
class UserProfile < ActiveRecord::Base
belongs_to :user
belongs_to :profile_type
end
User Profile Type Model
class ProfileType < ActiveRecord::Base
has_many :user_profiles
end
Try this:
user.account_settings.select("profile_type.*, profile_type.connection_type").all
I was able to figure out how to do this using Grape.
Since the association was already created, I can use Grape entities to expose what I needed out of the associations. It works seamlessly and I hope this helps anyone else who is having a similar problem.
To get what I was looking for, I needed to gather all user_profiles
userprofiles = user.user_profiles.all
Then, I presented this using Grape
present :user_profile_settings, userprofiles, with: API::V1::Entities::UserProfile
And, here is what my entities looked like:
class UserProfile < Grape::Entity
expose :profile_type, using: ProfileTypeEntity
end
class ProfileTypeEntity < Grape::Entity
expose :connection_type
end

Best way to update Has_many Joined Table

right now I have a jobs table with
has_many :applicants
has_many:users, through: :applicants
and a applicant table with
belongs_to :job
belongs_to :user
and a user table with
has_many :applicants
has_many:jobs, through: :applicants
So Users are connected through applicant table to Jobs table and vise versa.
I'm not sure I'm updating the model correctly. Right now it looks like this:
def addapply
#job = Job.find(params[:id])
applicant = Applicant.find_or_initialize_by(job_id: #job.id)
applicant.update(user_id: current_user.id)
redirect_to #job
end
But I got to thinking - would not this replace whatever association was there before?
I started looking around and found this in someone else's code:
def update
unless params[:user_relationships][:user_category_ids]
# Set default user category if not selected.
#user.user_category_relationships.build(
:category_id => '1',
:created_by_user_id => #current_user.id,
:name_id => #name.id
)
else
params[:user_relationships][:user_category_ids].each { |user_category_id|
#user.user_category_relationships.build(
:category_id => user_category_id,
:created_by_user_id => #current_user.id,
:name_id => #name.id
)
}
end
end
I'm not sure how that all works but perhaps I do need to iterate through them with a .each before I update.
I don't want to replace what is already there, I just want to add to it.
In Short what is the best way to update (or rather add to) a has_many :through joined table association?
Why not?
def addapply
#job = Job.find(params[:id])
applicant = Applicant.where(job_id: #job.id, user_id: current_user.id).first_or_create
redirect_to #job
end