Currently I'm stuck with my ruby on rails project. I'm using rails 3.2
I manage to create checkboxes for skills in the human form but I can't work out how to create a form input which can change the "for_work" boolean value in the human_skills table.
So my goals is when a user create a new or edit a human they can select the skills and determine if the skills is for work or not (a boolean value).
Thanks so much in advance!
Here is my Human form code
= semantic_form_for #human do |f|
= f.input :name
= f.input :skills , :as => :check_boxes,
Database design
skills - id, name
human_skills - id, skills_id, human_id, for_work
humans - id, name
Here is my model code:
class Human < ActiveRecord::Base
has_many :human_skills;
has_many :skills, :through => :human_skills
class HumanSkill< ActiveRecord::Base
belongs_to :human_skills;
belongs_to :human;
class Skill < ActiveRecord::Base
has_many :human_skills;
has_many :human, :through => :human_skills
Okay, so you need to adjust your models a little bit to allow human to create skills, and then use fields_for to let the form_for helper know it is on another model.
class Human < ActiveRecord::Base
has_many :human_skills;
has_many :skills, :through => :human_skills
accepts_nested_attributes_for :skills
class HumanSkill< ActiveRecord::Base
belongs_to :human_skills;
belongs_to :human;
class Skill < ActiveRecord::Base
has_many :human_skills;
has_many :human, :through => :human_skills
and the form
= semantic_form_for #human do |f|
= f.input :name
= fields_for #human.skills do |h_skills|
= h_skills.checkbox :skills
Resources to check out to answer your question: Accepts Nested Attributes = Accepts_nested_attributes_forFields For documentation:Fields_for
Nested Form video Railscast
Related
Im building a report system which uses a sort of meta question model. Questions are previusly saved in the database, and then depending of the type of report some questions are taken from the database.
Wanting to keep things DRY, i'm trying to figure out a way to pass the information of the Variable model to my report_header with no avail.
In the new action i have:
reportBody = #report_head.report_bodies.build(:variable_id => a.id)
#report_head.variables #modified, thx.
all i need is to pass the attributes from the Variable to report_head in a DRY way.
If you need to know my models:
class Variable < ActiveRecord::Base
attr_accessible :id,:break_point, :description, :name, :time_frequency, :v_type
has_many :report_bodies
has_many :report_heads, :through => :report_bodies
end
class ReportHead < ActiveRecord::Base
attr_accessible :email, :name , :report_bodies_attributes, :report_bodies, :variables_attributes
has_many :report_bodies
has_many :variables, :through => :report_bodies
accepts_nested_attributes_for :report_bodies
end
class ReportBody < ActiveRecord::Base
attr_accessible :report_head_id, :variable_value, :variable_id, :variables_attributes, :report_heads
belongs_to :report_head
belongs_to :variable
end
Update
I updated the model as suggested, and modified the way to call the variables. However im still confused about how to use it in the view, if i do something like:
<%= f.fields_for :variables do |variable| %>
<%= variable.text_field :name, :value => :name, :class => 'text_field' %>
<% end %>
it prints a string instead of the actual name.
You have define wrong name association, your association of ReportBody should be:
belongs_to :report_head
belongs_to :variable
This is not correct:
#report_head.report_bodies.build(:variable_id => a.id,:report_head_id =>#report_head.id)
chang it to:
#report_head.variables.build(:variable_id => a.id)
it's better, you don't have to set report_head_id. And this is wrong:
#report_head.report_bodies.variables
If you want to get all variables belong to #report_head, you just need using:
#report_head.variables
I need to assign students (users) to classes (studentclasses)
I have a simple many-to-many relationship using 3 tables:
studentclasses (lesson details)
users (user... student info)
studentclass_users (Join table containing user_id and studentclass_id)
I'm using has_many :through and my models look like the following:
studentclass.rb
class Studentclass < ActiveRecord::Base
has_many :studentclass_users
has_many :users, :through => :studentclass_users
end
user.rb
class User < ActiveRecord::Base
...more here...
has_many :studentclass_users
has_many :studentclasses, :through => :studentclass_users
end
studentclass_users.rb
class StudentclassUsers < ActiveRecord::Base
belongs_to :studentclass
belongs_to :user
end
For testing purposes, I'm just using a hidden field in my studentclass new view partial to tack on a user id when creating the class and it is as follows:
_new.html.erb
<%= hidden_field_tag "studentclass[user_ids][]", 29%>
And in my studentclass controller:
studentclasses_controller.rb
def new
#studentclass = Studentclass.new
end
def create
#studentclass = Studentclass.new(params[:studentclass])
#studentclass.save!
end
My params comes back:
Parameters: {"utf8"=>"✓", "authenticity_token"=>"MjBTf4rtcyo8inADrSxPZB3vLOKtlZRVFlQJJzfCqWs=", "studentclass"=>{"class_title"=>"hjhkj", "user_ids"=>["29"]}, "commit"=>"Save"}
which seems fine but I get the following error:
NameError (uninitialized constant ActiveRecord::HasManyThroughSourceAssociationMacroError):
I think this is something simple with naming maybe? Any help would be appreciated
So if I have the following relationship
class Item < ActiveRecord::Base
has_many :item_user_relationships
has_many :users, :through => :item_user_relationships
end
class User < ActiveRecord::Base
has_many :item_user_relationships
has_many :items, :through => :item_user_relationships
end
class ItemUserRelationship < ActiveRecord::Base
belongs_to :item
belongs_to :user
attr_accessible :role
end
What's the rails way to include the role attribute when listing all the Users of an Item?
#users = #item.users # I want to include the role as part of a user
Thanks!
UPDATE: I'm still having trouble with this. My goal is to get an array of User models that have their role included in the attributes.
I'm note sure if I understand you correctly, but maybe this is what you want?
#users = #item.users
#users.each do |user|
puts user.item_user_relationships.first.role
end
I've built a simple Friend model, which allows Users to have multiple friends. Here's what that looks like:
class Friend < ActiveRecord::Base
belongs_to :user
class User < ActiveRecord::Base
has_many :friends
Each friend record just has an id, user_id and friend_id. The user_id is the id of the user it belongs to and the friend_id is the id of user they are befriending.
Here's my problem
I'm not quite sure how to display a list of a particular user's friends. #user.friends will give me a list of all the friend records they have, but not the user accounts of those friends.
For instance, I am trying to build a show page for the friends controller:
class FriendsController < ApplicationController
def show
#user = current_user
end
SHOW.HTML.ERB
<% if #user.friends.count > 0 %>
<% #user.friends.each do |friend| %>
<div class="entry">
<%= friend.username %>
This does not work because friend in this case does not have username. I need to do something like this in my controller:
#friend = User.find_by_id(friend.friend_id)
But I'm not sure how I would call that in my view in the #user.friends loop. Any thoughts appreciated. Let me know if I need to be more clear.
UPDATE
I've updated my User model like so:
has_many :friends, :include => :user
has_many :friended_users, :through => :friends, :source => :user, :uniq => true
However, when I run #user.friended_users it's giving me the user_ids (which is the same as #user) rather than friend_ids.
How can I tweak that relationship so it's linking to the friend_id rather than user_id?
The more I think about it, I think I may not have set up the relationship properly in the first place. Maybe a User should has_many :users, through => 'friends', but that doesn't really make sense...
UPDATE
I've updated my models based on #twooface's input:
class User < ActiveRecord::Base
has_many :friendships
has_many :friends, :through => :friendships
class Friendship < ActiveRecord::Base
belongs_to :user
belongs_to :friend, :class_name => 'User'
class Friend < ActiveRecord::Base
has_many :friendships
has_many :users
I'm just not sure what my Friends table should look like. I assume it should have a primary key and a user_id? If I create a friendship and friend record, I can do friendship.user and friendship.friend and get the correct results, but user.friends gives me an empty hash...
I think your relations are built a bit wrong. Try something like this:
class User < ActiveRecord::Base
has_many :friends
has_many :friendships
has_many :friends, :through => :friendships
class Friendship < ActiveRecord::Base
belongs_to :user
belongs_to :friend, :class_name => 'User'
# This class has :user_id and :friend_id
Then everything will be simpler. Every user will have an array of friends that will be just users.
User.first.friends
Will return an array of Users that this User friends.
Hope this helps.
rails g model Article name:string
rails g model Category name:string
rails g model Tag name:string taggable_id:integer taggable_type:string category_id:integer
I have created my models as shown in the preceding code. Articles will be one of many models which can have tags. The category model will contain all categories which may be assigned. The tag model will be a polymorphic join-table which represents tagged relationships.
class Article < ActiveRecord::Base
has_many :tags, :as => :taggable
has_many :categories, :through => :taggable
end
class Category < ActiveRecord::Base
has_many :tags, :as => :taggable
has_many :articles, :through => :taggable
end
class Tag < ActiveRecord::Base
belongs_to :taggable, :polymorphic => true
belongs_to :category
end
I can't seem to get this to work, I can do it non polymorphic, but I must have something wrong with the polymorphic part. Any ideas?
Edit: Still not getting this right:
class Article < ActiveRecord::Base
has_many :taggables, :as => :tag
has_many :categories, :through => :taggables, :source => :tag, :source_type => "Article"
end
class Category < ActiveRecord::Base
has_many :taggables, :as => :tag
has_many :articles, :through => :taggables, :source => :tag, :source_type => "Article"
end
class Tag < ActiveRecord::Base
belongs_to :taggable, :polymorphic => true
belongs_to :category
end
To create a polymorphic has_many :through, you must first create your models. We will use'Article,' 'Category,' and 'Tag' where 'Tag' is the join-model and Article is one of many objects which can be "tagged" with a category.
First you create your 'Article' and 'Category' models. These are basic models which do not need any special attention, just yet:
rails g model Article name:string
rails g model Category name:string
Now, we will create our polymorphic join-table:
rails g model Tag taggable_id:integer taggable_type:string category_id:integer
The join-table joins together two tables, or in our case one table to many others via polymorphic behavior. It does this by storing the ID from two separate tables. This creates a link. Our 'Category' table will always be a 'Category' so we include 'category_id.' The tables it links to vary, so we add an item 'taggable_id' which holds the id of any taggable item. Then, we use 'taggable_type' to complete the link allowing the link to know what it is linked to, such as an article.
Now, we need to set up our models:
class Article < ActiveRecord::Base
has_many :tags, :as => :taggable, :dependent => :destroy
has_many :categories, :through => :tags
end
class Category < ActiveRecord::Base
has_many :tags, :dependent => :destroy
has_many :articles, :through => :tags, :source => :taggable, :source_type => 'Article'
end
class Tag < ActiveRecord::Base
belongs_to :taggable, :polymorphic => true
belongs_to :category
end
After this, setup your database using:
rake db:migrate
That's it! Now, you can setup your database with real data:
Category.create :name => "Food"
Article.create :name => "Picking the right restaurant."
Article.create :name => "The perfect cherry pie!"
Article.create :name => "Foods to avoid when in a hurry!"
Category.create :name => "Kitchen"
Article.create :name => "The buyers guide to great refrigeration units."
Article.create :name => "The best stove for your money."
Category.create :name => "Beverages"
Article.create :name => "How to: Make your own soda."
Article.create :name => "How to: Fermenting fruit."
Now you have a few categories and various articles. They are not categorized using tags, however. So, we will need to do that:
a = Tag.new
a.taggable = Article.find_by_name("Picking the right restaurant.")
a.category = Category.find_by_name("Food")
a.save
You could then repeat this for each, this will link your categories and articles. After doing this you will be able to access each article's categories and each categorie's articles:
Article.first.categories
Category.first.articles
Notes:
1)Whenever you want to delete an item that is linked by a link-model make sure to use "destroy." When you destroy a linked object, it will also destroy the link. This ensures that there are no bad or dead links. This is why we use ':dependent => :destroy'
2)When setting up our 'Article' model, which is one our 'taggable' models, it must be linked using :as. Since in the preceeding example we used 'taggable_type' and 'taggable_id' we use :as => :taggable. This helps rails know how to store the values in the database.
3)When linking categories to articles, we use:
has_many :articles, :through => :tags, :source => :taggable, :source_type => 'Article'
This tells the category model that it should have many :articles through :tags. The source is :taggable, for the same reason as above. The source-type is "Article" because a model will automatically set taggable_type to its own name.
You simply cannot make the join table polymorphic, at least Rails does not support this out of the box. The solution is (taken from Obie's Rails 3 way):
If you really need it, has_many :through is possible with polymorphic associations, but only by specifying exactly what type of polymorphic associations you want. To do so you must use the :source_type option. In most cases you will have to use the :source option, since the association name will not match the interface name used for the polymorphic association:
class User < ActiveRecord::Base
has_many :comments
has_many :commented_timesheets, :through => :comments, :source => :commentable,
:source_type => "Timesheet"
has_many :commented_billable_weeks, :through => :comments, :source => :commentable,
:source_type => "BillableWeek"
It's verbose and the whole scheme loses its elegance if you go this route, but it works:
User.first.commented_timesheets
I hope I helped!