Elixir Ecto: Using a Pivot Attribute in a Many To Many Relationship - many-to-many

I am currently having troubles figuring out how to use pivot attributes in an Ecto many-to-many relationship.
I found the following question but unfortunately nobody had an answer: https://stackoverflow.com/questions/37158184/elixir-ecto-pivot-many-to-many-table-attributes
Basically I need the same setup as mentioned in the question. Two models and I need to store data to the pivot entry.
Has anybody a solution for this problem?
Thanks in advance!

I am doing something like the following in one of my applications
def Foo do
schema "foos" do
field :name, :string
has_many :bars_foos
end
end
def Bar do
schema "bars" do
field :other, :integer
has_many :bars_foos
end
end
def BarFoo do
schema "bars_foos" do
field :size, :integer
belongs_to :bars
belongs_to :foos
end
end
This uses has_many and belongs_to instead of many_to_many, but it accomplishes something very similar. You can also still use the many_to_many with through if you need a direct link to the other dataset.

Related

Rails joining tables having has_many association

I have Student and Record table with a simple has_many :through association:
class Student < ActiveRecord::Base
has_many :records
end
I need to fetch all students details of MBA branch. I need to assign result to a variable #students and need to access record of a student using
#students.each do |student|
students.records.each do |record|
///
end
end
That is I need to access has_many related class datas also into an object. How to write query for that. I am newbee in rails. Please help .Thanks in advance
try this,
#student = Student.where("student.course = ?", "MBA").includes(:records)
Then do eaching on instance variable. This will save you from N+1 issue
It looks like you have a has_many relation instead of has_many :through. Have you looked through the rails guides? There they describe how to fetch data from the database. http://guides.rubyonrails.org/active_record_basics.html#read
Here is a more detailed reference on the has_many relation: http://guides.rubyonrails.org/association_basics.html#has-many-association-reference
Make sure you access student and not students in the loop.
#students.each do |student|
student.records.each do |record|
///
end
end
Where is the MBA branch coming from? Is that another table?
You probably will end up with something like #students = Student.where(branch_id: 1).
The ID 1 is just fictional but I'm guessing you have your branches in another table.

Rails: Creating a survey data structure with variable type answers

I'm creating a survey-answer data structure in my Rails app to collect user information. I'll be asking a mixture of multiple choice, number field and open ended questions so my (MySQL) data structure will need to cope with a variable data-type. How can I achieve this? My current plan is based on a previous answer here:
User model (the particpant)
Survey model (the survey)
Question model (the question asked)
Choice model (possible choice for question stored in 'text' column)
Answer model (the answer that links the choice to the participant user)
This works great for just multiple choice text answers with checkboxes, but what if I want an answer to be an integer field (e.g. "What is your age?") or an open ended text field (e.g. "What could be improved?")?
Different type fields
I imagine that a Choice or Answer model with multiple columns for each possible type (e.g. text, integer, datetime, etc.) would be bad as it would be incredibly sparse.
Would multiple Choice tables for each type be better? (e.g. Choice_Text, Choice_Integer etc)
But then how would the Answer model link to the right table?
Open ended unique answers
Should I store unique text answers in the Answer model as another data column, or in the Choice model as a new entry each time?
Any help would be much appreciated. Cheers!
So I ended up using a polymorphic association to link the different types of input, and dealt with open ended text answers by adding them to the Choice_Text table.
If anyone comes across this in the future, the data structure was as follows:
class Survey < ActiveRecord::Base
has_many :survey_questions
has_many :survey_attempts
end
class SurveyAttempt < ActiveRecord::Base
has_many :survey_answers
belongs_to :survey
belongs_to :user
end
class SurveyQuestion < ActiveRecord::Base
has_many :survey_choices
belongs_to :survey
end
class SurveyChoice < ActiveRecord::Base
has_many :survey_answers
belongs_to :survey_question
belongs_to :survey_choice_value, polymorphic: true
end
class SurveyChoiceString < ActiveRecord::Base
has_many :survey_choices, as: :survey_choice_value
has_many :survey_question, through: :survey_choices
end
class SurveyChoiceText < ActiveRecord::Base
has_many :survey_choices, as: :survey_choice_value
has_many :survey_question, through: :survey_choices
end
class SurveyChoiceInteger < ActiveRecord::Base
has_many :survey_choices, as: :survey_choice_value
has_many :survey_question, through: :survey_choices
end
class SurveyAnswer < ActiveRecord::Base
belongs_to :survey_choice
belongs_to :survey_attempt
end

Rails query on different models in a multi-level association chain

I have a multi-level model structure, and I am trying to create a query where I can search for either an attribute on the main parent model, or the last model in the associatioon change. My structure looks like the following:
class Parent
attr_accessible :pname
has_one :child
end
class Child
has_many :infos
end
class Info
has_one :setting
end
class Setting
has_many :subsettings
end
class Subsetting
attr_accessible :sname
end
What I am trying to do is create a where query, where i can pull all parents where either the "pname = X" or "sname = X". However, I am unsure of how to create the associations that deep: Is there a way I can do it cleanly using active record, or is it better to create a mysql query directly?
I'm typing this freehand, so it's possible this won't be 100%, but you should be able to do something like the following...
class Parent
has_one :child
has_many :infos, through: :child
has_many :settings, through: infos
has_many :subsettings, through: :settings
...
end
Then you should be able to call...
Parent.joins(:subsettings).where("parent.pname = ? OR subsetting.sname =?", x)
Two things to note about the .where() call:
Because you are querying against multiple joined tables, you need to preface the column with the table name.
The table name is singular, not plural. That's why subsetting and not subsettings.

Unable to make sense of database data in Rails console

I'm trying to gather a set of data for current_user so in my controller code I have:
#user_workouts = current_user.planned_workouts
with planned_workouts being the join table b/w the user and the workouts. When I test that in console:
#user_workouts.count
I get 4.
When I do:
PlannedWorkout.count
I get 4.
But when I try using a .each loop for my #user_workouts:
#user_workouts.each do |user_workout|
puts user_workout
end
I get far more than 4, I get something like ~25, how is that possible when I tested above how many planned_workouts there are in the table and for the user themselves? I also tried deleting all of the planned_workouts so that the table is empty and created 4 new ones, and still the same outcome. Can it have anything to do with the fact that I'm using add_index in the schema?
EDIT:
My model associations:
User.rb
has_many :planned_workouts
has_many :workouts, through: :planned_workouts
Workout.rb
has_many :planned_workouts
has_many :users, through: :planned_workouts
PlannedWorkout.rb
belongs_to :workout
belongs_to :user

Save model id as foreign key through has_one / belongs_to

I'll briefly explain my situation: I have a model called "tax" which belongs_to a "user" and of which a "user" has_one.
In my users table I have a column called "tax_id" which I want to store the id of the tax model when a user creates one.
Currently, in my tax model the create function looks something like this:
class Tax < ActiveRecord:Base
belongs_to :user
tax = Tax.new(income: income, taxes: taxes, rrsp: rrsp)
tax.save
and then in the taxes_controller file, the create function looks like this:
def create
#tax = Tax.new(secure_params)
#tax.user = User.find(current_user.id)
if #tax.save
redirect_to show_tax_path(current_user.tax)
else
render :new
end
end
(secure_params) being the strong parameters for the field inputs set in a private definition.
Now, someone mentioned that I may have better luck if I use build but unfortunately I couldn't get it to work at all, something to do with how I'm using current_user (devise). Currently, my setup works just fine, other than saving the tax model id in the user model column "tax_id" like I said.
I'm wondering if I perhaps need to add a foreign ID key to either the belongs_to or has_one statement, even though I was under the impression that the "link" should be made automatically as long as the column was named "[model]_id"
try using
user.build_tax
I think this might help you out.
The build syntax for has_many association:
user.taxes.build
The build syntax for has_one association:
user.build_tax # this will work
user.tax.build # this will throw error