Validation to add only one biography for single person - ruby-on-rails

I have two model user and biography, both has one-to-one association and i want to user to add only one biography..here is the model:-
class Biography < ActiveRecord::Base
attr_accessible :biography, :date, :title, :individual_id
belongs_to :user
end
class User < ActiveRecord::Base
has_one :biography
end
How can i validate user so that he can add only one biography.
please help!

You already have check out this link. (source)
A belongs_to association sets up a one-to-one connection with another
model, such that each instance of the declaring model “belongs to” one
instance of the other model.
A has_one association also sets up a one-to-one connection with
another model, but with somewhat different semantics (and
consequences). This association indicates that each instance of a
model contains or possesses one instance of another model.
But if you wanted you could add a :before_save method that will check user.biography does not return something unexpected, but I don't think this is neccessary.
EDIT AFTER COMMENTS:
Try something like a before_filter...
before_filter :check_user, :only => [:new]
This will call the method before the controller action is called. Then you can create the method that will check the current_user has a biography and direct them to it. This is a starting point..
def check_user
current_user.nil? ? redirect_to(new_biography_path) : redirect_to(edit_biography_path)
end
Hope it helps.

Related

One relation for two models

I was trying to find answer on my question, but didn't success with it.
I have models Event, participants, participation_form, invitation, user.
Event has_many participants
User has_many invitations
User has_many participation_form
For Participant I want to have field like "based_on" and it will be references with invitation or participation_form.
I have one idea about it - make two fields and one model method that will be check which field contains value and return "based_on"
My question is - is there any way to reference one model to two models with pair of fields - class (model name) and value (id) so I will add another type if I need it in future.
You could use polymorphic associations for that: (http://guides.rubyonrails.org/association_basics.html#polymorphic-associations
Could you tell more about models relations so I can write some example? Why do you need Participant model?
As mentioned byKuba Ploskonka, you'll probably benefit from a polymorphic association here:
--
Setup
For Participant I want to have field like "based_on" and it will be references with invitation or participation_form.
As per your specifications, you'll want to use the following:
#app/models/participation.rb
Class Participation < ActiveRecord::Base
belongs_to :participle, polymorphic: true
end
#app/models/invitation.rb
Class Invitation < ActiveRecord::Base
has_many :participations, as: :participle
end
#app/models/participation_form.rb
Class ParticipationForm < ActiveRecord::Base
has_many :participations, as: :participle
end
This will give you the ability to save your objects as follows:
#app/controllers/invitations_controller.rb
Class InvitationsController < ApplicationController
def create
#invitation = Invitation.new invitation_params
#invitation.participations.build #-> will save a blank "Participation" object
#inviation.save
end
end

What type of relations to choose if I want to link 2 models with one

I have model Message. It may be posted by either Person or Organization from my DB.
I want to call update.contact, where contact is Organization or Person.
class Update < ActiveRecord::Base
has_one :contact
The decision I like to use is like
class Organization < ActiveRecord::Base
belongs_to :update, as: :contact
But this approach not available in Rails.
Should I use polymorphic association? How to organize the architecture for this case?
It sounds like Organization and Person might be two different variants of a same entity (a customer, user, whatever). So, why not create a common parent model for the two of them? Such a parent wouldn't necessarily need a table, and you might just define common methods inside of it. Update is more of an action rather than an object, which could be applied to a Contact object (typically in its controller). For the Contact class, polymorphic association can be used. So you might have:
class Parent < ActiveRecord::Base
# stuff Person and Organization share
end
class Person < Parent
has_one :contact, as: :owner
# Person methods etc.
end
class Organization < Parent
has_one :contact, as: :owner
# Organization stuff
end
class Contact
belongs_to :owner, polymorphic: true
def update
#...
end
# other stuff for Contact
end
Then you can write lines like:
Person.first.contact.update
or whatever you need to do with your objects.
In case your Organization and Person don't differ too much, you could just create a table for the parent class, and add the has_one etc. in there.

Correct ROR model callback for creation associated

I have associated models User and Channel in Rails 3 app. Channel is created at the moment of User creation
class User < ActiveRecord::Base
before_create do
self.channels.build
end
has_many :channels
end
class Channel < ActiveRecord::Base
belongs_to :user
validations block
...
end
Problem is that if validations for Channel will not pass User will be created at DB but Channel won't. In what callback place Channel creation to create User and Channel in one 'transaction'? Or, maybe, there is another right way?
Thanks in advance.
UPD1:
Channel autocreate on User create placed in model because in some cases objects created not invoking controllers.
You can use "accepts_nested_attributes_for"
class User < ActiveRecord::Base
has_many :channels
accepts_nested_attributes_for :channels
end
class Channel < ActiveRecord::Base
belongs_to :user
validations block
end
You think too much. This is very common case and has a convention.
Firstly at Pedro said, you need a validation of association in Channel model. This will prevent saving of channel without user_id.
Then, in controller's create action, you just make sure all params including user object is sent here for creation.
Use validates :channels, associated: true.
You should probably review your Channel validations because if it is not saving, you're doing something your app doesn't expect.

rails passing parameters to callback

I have two models
class Department < ActiveRecord::Base
has_many :checklists
attr_accessible :deadline
after_update :update_checklist
class Checklist < ActiveRecord::Base
belongs_to :department
attr_accessible :content, :category
Basically, the 'department' model has a virtual attribute called 'deadline', and it is in type of date. The actual value of 'deadline' is stored in another model 'checklist', in format of string.
Every time when 'deadline' is updated, I would like to check if there is an entry in 'checklist', and create (if not yet) or update (if already has an entry).
I was thinking this way
def deadline=(deadline)
#cl = Checklist.find_or_create_by_department_id_and_category(self.id, 'deadline')
#cl.update_attributes(:content => deadline.to_s)
#cl.save
end
def deadline
#deadline = self.checklists.find_by_category('deadline')
Date.parse(#deadline.to_s)
end
But the above virtual attribute is not working.
When searching for the answer, I found on rails cast that callback will be a better solution for this kind of situation. So I am trying to something like:
class Department < ActiveRecord::Base
after_update :update_checklist
def update_checklist
#cl = Checklist.find_or_create_by_department_id_and_category(self.id, 'deadline')
#cl.update_attributes(:content => ???)
end
I am not sure how to pass the value to the callback.
Please help me with this design. what is the standard way to handle this? Thank you in advance!
update_checklist is a method of Department. So within update_checklist, you can access any Department attributes, just like self.id, self.deadline is what you want.

Design considerations for creating associated records on Devise User object on registration

I'm using Devise, and for each User account created I want to generate a relationship where:
class User < ActiveRecord::Base
belongs_to :business
end
class Business < ActiveRecord::Base
has_many :users
has_one :apt_setting
has_many :hours, :as => :hourable
end
class ApptSetting < ActiveRecord::Base
belongs_to :business
end
So upon registration an associated Business object is created, and with each Business object an associated ApptSettings and BusinessHour object is created.
I currently have this implemented like this:
class Admin
before_create :create_associated_records
def create_associated_records
# create the associated business object
business = Business.create(:business_name => business_name, :subdomain => subdomain, :initial_plan => initial_plan)
# retrieve the id of the new business object
self.business_id = business.id
# create the associated records
BusinessHour.default_values(business_id)
ApptSetting.default_values(business_id)
end
end
class ApptSetting < ActiveRecord::Base
belongs_to :business
def self.default_values(business_id)
# ... create record with default values
end
end
class BusinessHour < Hour
belongs_to :hourable, :polymorphic => true
def self.default_values(business_id)
# ... create record with default values
end
end
This does work, but does it seem like the best design?
One alternative I'm considering is handling removing Admin -> create_associated_records, and instead do that work in Users::Accounts::RegistrationsController where I override the 'create' method. There I could build all the associated records, set :accepts_nested_attributes where appropriate, then call 'save' on the Business object, which should then cause all the associated records to be generated.
Thoughts on the best design, or any other ideas?
you don't need the default_values methods. In your create_associated_records you can change those calls to:
ApptSetting.create(:business_id => business_id)
Don't override the create method. before_create callbacks are a better way to go. In either case, If a business has many users, do you really want to create a new business every time a new user is created? How does a second user ever get added to a business? add something like,
def create_associated_records
return unless self.business_id.nil?
....
Also where are the business_name, subdomain, and initial_plan variables coming from in your method? Do you have them as attributes of the admin user? Seems like they should be only values of the business.
I think the biggest question here is, does a user really need a business in order to exist? Why can't the user just create their Business after they create their account?
** Edit: Being more clear / cleaner version using rails association methods:
class Admin
before_create :create_associated_records
private
def create_associated_records
return unless self.business_id.nil?
self.create_business
self.business.create_appt_setting
self.business.hours.create
end
end

Resources