Association Clarification Rails - ruby-on-rails

This is probably so simple its stupid, but I'm having a brainfreeze moment and am just staring at the screen now going nowhere.
I have two models a member and a membership, each member can have one type of membership from a selection of many.
class Member < ActiveRecord::Base
attr_accessible :forename, :middlename, :surname, :house_no, :house_name, :street, :town, :postcode, :home_tel, :mobile_tel, :work_tel, :email
end
class Membership < ActiveRecord::Base
attr_accessible :membership_type
end
My membership model will have a few records pre populated so that a member can choose which type of membership they would like, ie Peak, Off Peak, Student
Am i correct in thinking that the member model will look like this
class Member < ActiveRecord::Base
**has_one :membership**(added this)
**accepts_nested_attributes_for :membership**
attr_accessible **:membership_attributes(Added This)**, :forename, :middlename, :surname, :house_no, :house_name, :street, :town, :postcode, :home_tel, :mobile_tel, :work_tel, :email
end
So i create a migration and add the membership_id column to the member model as the foreign key?
My Membership Model can look like this
class Membership < ActiveRecord::Base
**belongs_to :member** (Added This)
attr_accessible :membership_type
end
am i looking at this correctly here?
Thanks

So i create a migration and add the membership_id column as the
foreign key?
I think that in your migration you have to add a member_id column to the memberships table, as the foreign key.
(Active Record Associations has one)

Related

Reference same model twice with different foreign keys or create a many-to-many association

I have an app in Rails where I've create a model called User and another called Task.
The model User has an enum for roles, which means that I can have an User that is a client or a developer:
require 'bcrypt'
class User < ApplicationRecord
has_many :tasks
enum :role => [
:client,
:developer
]
has_secure_password
validates_uniqueness_of :document, :email
validates_presence_of :birthdate,
:credits,
:document,
:email,
:name,
:neighborhood,
:phone,
:street,
:street_number,
:zipcode
end
The model Task can be managed by an client or by a developer:
class Task < ApplicationRecord
enum :priority => [
:low,
:medium,
:high
]
validates_presence_of :description, :title
end
I'm pretty sure that it would be better if I split the table User in two other tables, called Client and Developer, for example, but their attributes are the same and in the future, I want to be able to quickly change the User with the role :client to the role :developer, without having to create a record in the table Developer and destroying the other in the table Client.
My question is: thinking in good practices, is it better to insert two fields in the model Task, one called client_id and the other called developer_id and use the Single-table inheritance or to creating a many-to-many relationship between the model Task and the model User, and just check the role of each user that is being reference in the Task?

how to obtain a subset of records for a grouped_collection_select in Rails

I'm trying to obtain a subset of records for a grouped_collection_select, in the schema I have a Brand and a Model, and we handle different lines of products, when we request a product, we specify the line that we are going to request, so, we can have the Brands, and the models of that line, so the models are defined as follows:
Model for Brand
class Brand < ActiveRecord::Base
validates :brand_key, uniqueness: true, presence:true
has_many :models
accepts_nested_attributes_for :models, allow_destroy: true
end
Model for Modelx
class Modelx < ActiveRecord::Base
belongs_to :brand
belongs_to :line
validates :model_key, uniqueness: true, presence:true
end
Model for Line
class Line < ActiveRecord::Base
validates :line_key, uniqueness: true, presence:true, length: {in: 1..6}
has_many :line_features, -> { order(:sort_order) }
has_many :modelx
accepts_nested_attributes_for :line_features, allow_destroy: true
end
Model for Product
class Product < ActiveRecord::Base
belongs_to :vendor
belongs_to :line
belongs_to :brand
belongs_to :modelx
belongs_to :operating_status
has_many :line_features, -> { order(:sort_order)}
store_accessor :line_features
end
Controller for Product (new)
def new
#brands=brand.where(id: Modelx.select(:brand_id).where(line_id: params[:line_id]))
#modelxs=Modelx.where(line_id: params[:line_id])
...
end
excerpt from partial form
<%= f.collection_select( :brand_id, #brands, :id, :brand,{:prompt =>'Brands'}) %>
<%= f.grouped_collection_select(:modelx_id, #brands, :modelx, :brand, :id, :modelox) %>
Now, the problem that I'm facing is that when I display a model I need to present only the models available for that brand and line, but, the request is bringing all the models for the brand as it's supposed to be and I don't know how to discriminate those lines that are not needed.
Any help, hint or suggestion is highly appreciated.
Update to question
I don't know if this is a workaround or a solution to the question, but, it was the only way that I found to get to a solution for the requirement, for that reason I'm posting as an update instead of answering the question for whom it may help.
Reviewed the documentation once again and find out that the method :modelx referred by <%= f.grouped_collection_select(:modelx_id, #brands, :modelx, :brand, :id, :modelox) %> was requesting all the models as noted in apidock, this method was the solution for the problem.
Created a method in the brand model according to the subset depicted above, due to the fact that the grouping was made by brand, here the excerpt
Model for Brand (Excerpt)
...
def modelx_ltvi
Modelx.where("line_id = ? and brand_id =?",$line_id, self.id)
end
Special Note: Due to my inexperience, I was not able to pass the value of the :line_id from the form, so, I put it in a global variable.
Modified the form partial
Excerpt from partial form
...
<% $line_id=#product.line_id %>
...
<%= f.grouped_collection_select(:modelx_id,
#brands, :modelx_ltvi, :brand,
:id, :modelx) %>
<% end %>
And that makes the hamster run.
Filter your models by the brands you just found, something like:
#brands=Brand.where(id: Modelx.select(:brand_id).where(line_id: params[:line_id]))
#modelxs=Modelx.where(line_id: params[:line_id], brand_id: #brands.map(&:id))
#selected_model_names = #modelxs.map(&:name).sort.uniq

Single Table Inheritance rails has_many

I have a model called Course which needs to be associated with exams and assignments. I want to able to write code like this:
>>c = Course.new
>>assignment1 = c.assignments << Assignment.new
>>exam1 = c.exams << Exam.new
c.assessments should now include both exam1 and assignment1
How I think this should be accomplished (using single table inheritance from the Assessment model):
class Course < ActiveRecord::Base
has_many :assessments
attr_accessible :title, :name, :startDate, :endDate, :color
end
class Assessment < ActiveRecord::Base
belongs_to :course
attr_accessible :end_at, :name, :start_at, :type, :weight
end
class Assignment < Assessment
end
class Exam < Assessment
end
I've tried my best to find out how to do this but i cant seem to figure it out. Any help would be appreciated.
Course has only assesments associations so you should be able to write code like this:
c = Course.new
c.assesments << Assignment.new
c.assesments << Exam.new
Also make sure that assesments table has type column with datatype string.

Composite primary keys in ruby on rails

I am trying to use http://compositekeys.rubyforge.org/ in order to have composite primary keys in my activerecord models.
I already added gem 'composite_primary_keys', '=3.1.0' to my Gemfile.
Now I am trying to setup my first modelclass as follows.
class StringProperty < ActiveRecord::Base
self.primary_keys :entity_id, :property_id
set_table_name "problem.string_property"
attr_accessible :entity_id, :property_id, :value
end
But all I get is:
What am I doing wrong? :(
The following will work I think.
require 'composite_primary_keys'
class StringProperty < ActiveRecord::Base
self.primary_keys = :entity_id, :property_id
set_table_name "problem.string_property"
attr_accessible :entity_id, :property_id, :value
end
If it is only for unique constraint purposes use:
class Field < ActiveRecord::Base
validates :input, uniqueness: { scope: :user_id,
message: "one input per user" }
end
source: http://guides.rubyonrails.org/active_record_validations.html

Virtual attributes and mass-assignment

developers! I can't understand next situation
For Example I have model
class Pg::City < ActiveRecord::Base
belongs_to :country
#virtual accessors
attr_accessor :population
#attr_accessible :city, :isdisabled, :country_id
end
I can use code like this:
c = Pg::City.new({:population=>1000})
puts c.population
1000
But if I uncomment attr_accessible code above throw warning
WARNING: Can't mass-assign protected attributes: population
How can I use virtual attributes for mass-assigmnment together with model attributes?
Thanks!
Using attr_accessor to add a variable does not automatically add it to attr_accessible. If you are going to use attr_accessible, then you will need to add :population to the list:
attr_accessor :population
attr_accessible :city, :isdisabled, :country_id, :population

Resources