I have 3 models in Rails: User, UserProfile and Post
Something like this:
class Post < ActiveRecord::Base
attr_accessible :content, :post_type
belongs_to :user
delegate :fullname, :to => :user, :prefix => "author"
end
class User < ActiveRecord::Base
has_many :posts
has_one :user_info
delegate :fullname, :to => :user_info
end
class UserInfo < ActiveRecord::Base
attr_accessible :avatar, :fullname, :birthday, :nickname, :gender, :about
belongs_to :user
end
Now I use knockout to manage posts at client-side so I have to make my object to json using posts.to_json. These JSON objects don't have attributes fullname. I tried with user.to_json, and these objects don't have that attribute either. So how can I make the delegate serialize to JSON?
Since fullname is a virtual attribute in the sense:
Rails 2:
posts.to_json(:method => %w(fullname))
user.to_json(:method => %w(fullname))
Rails 3:
posts.to_json(:methods => %w(fullname))
user.to_json(:methods => %w(fullname))
Related
I have 3 models:
class Brand
attr_accessible :obs, :site, :title
has_many :equipments
end
class Equipment
attr_accessible :brand_id, :category_id, :lending_id
belongs_to :brand
has_many :lendings
end
class Lending
attr_accessible :equipment_id
belongs_to :equipment
end
I'm trying to show the brand of an associated equipament:
Brand: <%= #lending.equipment.brand %>
that command show this: Brand:0xab7f2c8
As you can see, there's no association between brand and lending models and for me its strange if i do that. I want to use the equipment/brand association to retrieve the :title information and show it on my lending view.
Can anyone help me?
You can either use a delegate in Lending:
delegate :brand, :to => :equipment, allow_nil: true
Or you can setup a has-one-through association in Lending:
has_one :branch, :through => :equipment
Either way, you can now call branch directly from a Lending instance, and work on it (almost) as if it were a regular association.
Use delegate
class Lending
attr_accessible :equipment_id
belongs_to :equipment
delegate :brand, :to => :equipment, :allow_nil => true
end
now you can use
<%= #lending.brand.title%>
I have a user model which has a polymorphic relationship to teachers, students, and admin. These three types of users each belong to a school. I would like to have it so the username of the user is unique within a school. How would I write the validations to accomplish this?
Here is what my models look like:
class User < ActiveRecord::Base
belongs_to :profileable, :polymorphic => true
delegate :school, :to => :profileable
end
class Student < ActiveRecord::Base
belongs_to :school
has_one :user, :as => :profileable
delegate :name, :username, :to => :user
end
class Teacher < ActiveRecord::Base
belongs_to :school
has_one :user, :as => :profileable
delegate :name, :username, :to => :user
end
class Admin < ActiveRecord::Base
belongs_to :school
has_one :user, :as => :profileable
delegate :name, :username, :to => :user
end
I'm quite sure you will need to use a custom validator for this. The delegated attribute will not be usable in the User model. What you could do is also include the school_id in the User method and set it using before_validate every time. Then you'd be able to use the "simple" uniqueness validator:
validates :username, :uniqueness => {:scope => :school_id}
However, a custom validator joining the school_id of the profileable parent would probably be a cleaner way to go.
I have an User model
class User < ActiveRecord::Base
attr_accessible :email, :name
has_many :client_workouts
end
And a ClientWorkout model
class ClientWorkout < ActiveRecord::Base
attr_accessible :client_id, :trainer_id, :workout_id
belongs_to :client, :class_name => User, :foreign_key => 'client_id'
belongs_to :trainer, :class_name => User, :foreign_key => 'trainer_id'
end
I first want to know what or if I'm doing something wrong when writing the associations. Ideally I want to be able to call a query where I find the user's clients workouts where the user's id matches with client_id or trainer_id. So...
user.client_workouts.trainer???
This will not work as rails assumes that the ClientWorkout have a user_id column. I don't think there is any way to make a has_many relation that matches two columns... Instead you could create a method like this:
class User < ActiveRecord::Base
attr_accessible :email, :name
has_many :client_workouts, :foreign_key => "client_id"
has_many :trainer_workouts, :foreign_key => "trainer_id"
def client_and_trainer_workouts
ClientWorkouts.where("client_id = ? OR trainer_id = ?", id, id)
end
end
Otherwise you could create a scope on the ClientWorkout model like this:
class ClientWorkout < ActiveRecord::Base
attr_accessible :client_id, :trainer_id, :workout_id
belongs_to :client, :class_name => User, :foreign_key => 'client_id'
belongs_to :trainer, :class_name => User, :foreign_key => 'trainer_id'
scope :workouts_for_user,
lambda {|user| where("client_id = ? OR trainer_id = ?", user.id, user.id) }
end
You could also do both, and let the method on the use call the scope on the ClientWorkout.
Ok I'm really feeling I'm missing the rails way on this one.
Following my last question rails parameters in form_for, I can correctly update the message contents but am struggling with updating the recipients
My Draft model
class Draft < ActiveRecord::Base
belongs_to :message
belongs_to :draft_recipient, :class_name => "User"
delegate :created_at, :subject, :user, :body, :draft_recipients, :to => :message
...
My Message Model
class Message < ActiveRecord::Base
belongs_to :user
has_many :recipients, :through => :message_copies
has_many :draft_recipients, :through => :drafts
has_many :message_copies
has_many :drafts, :class_name => "Draft", :foreign_key => :message_id
attr_accessor :to #array of people to send to
attr_accessible :subject, :body, :to, :recipients, :author, :user
...
In my controller I want to do something like
new_draft_recipients = params[:draft][:draft_recipients].split(",")
#draft.update_attributes(:draft_recipients => new_draft_recipients)
which obviously doesn't work. When I try update each record comparing old (from the database )and new recipients (passed through the form), the algorithm gets ridiculously complicated. I feel what is missing is proper associations, but I don't manage to understand which. I know this is really simple. Thanks for your help
I have Rails polymorphic model and I want to apply different validations according to associated class.
The class name is in the _type column for instance in the following setup:
class Comment
belongs_to :commentable, :polymorphic => true
end
class Post
has_many :comments, :as => :commentable
end
the comment class is going to have the commentable_id and commentable_type fields. commentable_type is the class name and commentable_id is the foreign key. If you wanted to to a validation through comment for post-specific comments, you could do something like this:
validate :post_comments_are_long_enough
def post_comments_are_long_enough
if self.commentable_type == "Post" && self.body.size < 10
#errors.add_to_base "Comment should be 10 characters"
end
end
OR, and I think I like this better:
validates_length_of :body, :mimimum => 10, :if => :is_post?
def is_post?
self.commentable_type == "Post"
end
if you have several validations, I would recommend this syntax instead:
with_options :if => :is_post? do |o|
o.validates_length_of :body, :minimum => 10
o.validates_length_of :body, :maximum => 100
end
The validates_associated method is what you need.
You just have to link this method to the polymorphic model and it will check if the associated models are valid.
class Comment < ActiveRecord::Base
belongs_to :commentable, :polymorphic => true
validates_associated :commentable
end
class Post < ActiveRecord::Base
has_many :comments, as: commentable
validates_length_of :body, :minimum => 10
validates_length_of :body, :maximum => 100
end