Rails: has_many, through not showing in view/index - ruby-on-rails

I'm writing a simple time tracking app where the user has_many clients and where the client has_many projects.
I want a user to be able to view a list of their projects (for all clients). To implement this, I've set up a has_many, through relationship between the users and projects.
But for some reason I can't get the projects to show up in their index view. There's probably a really simple reason for this that I'm just not noticing, so apologies upfront if that's the case.
Here's the relevant code.
Project index controller:
def index
#projects = current_user.projects.paginate(:page => params[:page], :per_page => 6)
end
Project model:
class Project < ActiveRecord::Base
belongs_to :client
validates :name, presence: true, length: { maximum: 30 }
validates :fee, presence: true, numericality: { only_integer: true,
greater_than_or_equal_to: 0, less_than_or_equal_to: 100000 }
validates :client_id, presence: true
end
Client model:
class Client < ActiveRecord::Base
belongs_to :user
has_many :projects, dependent: :destroy
validates :user_id, presence: true
validates :name, presence: true, length: { maximum: 30 }
validate :user_id_is_valid
private
def user_id_is_valid
errors.add(:user_id, "is invalid") unless User.exists?(self.user_id)
end
end
Relevant part of the User model:
class User < ActiveRecord::Base
has_many :clients, dependent: :destroy
has_many :projects, through: :clients
index.html.erb:
<div id="projects-list">
<% if current_user.projects.any? %>
<h3>Projects</h3>
<ul class="project-list">
<% render #projects %>
</ul>
<%= will_paginate #projects %>
<% end %>
</div>
_project.html.erb:
<li>
<%= link_to "#{project.name}", '#' %>
</li>

It should be:
<%= render #projects %>
Not:
<% render #projects %>

Related

Rails 4 - select related records

On my application, I have an object for many-to-many relationships called "selection"
class Selection < ActiveRecord::Base
belongs_to :question
belongs_to :projecttype
end
and 2 objects to relate to each other
class Projecttype < ActiveRecord::Base
has_many :selections
has_many :questions, :through => :selections
validates :projecttype, uniqueness: true, length: { is: 3 }
validates :name, presence: true
mount_uploader :image, ImageUploader
end
And...
class Question < ActiveRecord::Base
has_many :selections
has_many :projecttypes, :through => :selections
validates :question, presence: true
validates :comment, presence: true, length: { minimum: 5}
validates :sequence, presence: true
end
Now in my edit form for the projecttype, I want to be able to select related questions (using check boxes).
<div class="row">
<div class="col-md-2"><%= f.label :selection %></div>
<div class="col-md-4"><%= f.select :selection, {}, {:multiple => true, :style => "width:100%; border:none" } %></div>
</div>
Have tried options_for_selection and _from_collection and don't anymore know what to do as I get many errors.
what should the f.select code be?
I'm a little rusty with Rails now, but it should be something like this.
<%= f.select :selection, Selection.all.collect {|x| x.name}, {}, :multiple => true %>
and don't forget to add
def post_params
params.require(:post).permit(:title, :body, category_ids: [])
end
to your selection.rb file

form validation with nested models in Rails

I have this problem. I need to validate the attributes of two models in the same form in Rails. One is the parent of the other.
The form is like this:
<%= semantic_form_for #professional do |pro| %>
<%= pro.inputs :id => "information" do %>
<%= pro.input :name, label: t("Artistic Name") %>
<%= pro.semantic_fields_for #user do |user| %>
<%= user.inputs :id => "register" do %>
<%= user.input :email, :placeholder=>"email#example.com" %>
<%= user.input :password, label: t('Password') %>
<%end%>
<% end %>
<% end %>
<% end %>
The models I am using are like this:
User:
class User < ActiveRecord::Base
belongs_to :role, polymorphic: true
validates :email, :password, presence: true
end
Professionals:
class Professional < ActiveRecord::Base
has_one :user, as: :role, dependent: :destroy
accepts_nested_attributes_for :user
validates :date_birthday, :gender, :height, :name, :description, :Weight, :address, :languages,:services, :category, :phonenumber, :fullname, :hair_color, :age, :orientation, presence: true
end
So, what is the problem?
When I clicked in the submit button the professional attributes are marked but not the users attributes.
Like this:
The fields marked in red belongs to the professional model but the fields email and password belongs to the user model aren't marked in red when it should be because they are empty.
What can i do? I need the warning message for the user is attributes too
Thanks in advances.
We've achieved what you need before.
We had to use inverse_of so that the object was a singular piece of data (rather than multiple pieces as is the case by default):
#app/models/user.rb
class User < ActiveRecord::Base
belongs_to :role, polymorphic: true, inverse_of: :user
validates :email, :password, presence: true
end
#app/models/professional.rb
class Professional < ActiveRecord::Base
has_one :user, as: :role, dependent: :destroy, inverse_of: :role
accepts_nested_attributes_for :user
end
This will help.
You also need to make sure you're passing these objects correctly (I see so many people not doing this).
You need to tell Professional to validate the associated User:
class Professional < ActiveRecord::Base
...
validates_associated :user

uninitialized constant User::Post (NameError)

I have the following problem, In UserController#show there has to be a list of posts, but it throws an error as shown in the screen shot:
The part of the code which is responsible to show user posts (show.html.erb)
<div class="span8">
<% if #user.posts.any? %>
<h3>Работы (<%= #user.posts.count %>)</h3>
<ol class="posts">
<%= render #posts %>
</ol>
<%= will_paginate #posts %>
<% end %>
</div>
posts.rb:
class Posts < ActiveRecord::Base
belongs_to :user
default_scope -> { order('created_at DESC') }
validates :description, presence: true, lenght: { minimum: 6 }
validates :user_id, presence: true
end
part of a code in user.rb
class User < ActiveRecord::Base
has_many :posts, dependent: :destroy
Your help, thanks in advance is very important.
Excuse for possible mistakes in the text
You should name your model in singular form:
class Post < ActiveRecord::Base

Rails ActiveRecord_Relation

I am currently developing a somewhat 'big' project. In this project I have many models, views, and controllers from which I have to mention the following:
Group.rb:
class Group < ActiveRecord::Base
has_many :users, through: :grouprel
has_many :grouprel, dependent: :destroy
validates :name, presence: true, length: {maximum: 25},
uniqueness: { case_sensitive: false }
validates :description, presence: true , length: {maximum: 140}
end
Grouprel.rb
class Grouprel < ActiveRecord::Base
belongs_to :user
belongs_to :group
validates :user_id, presence: true
validates :group_id, presence: true
end
User.rb
class User < ActiveRecord::Base
.....
has_many :groups, through: :grouprel, dependent: :destroy
has_many :grouprel, dependent: :destroy
.....
StaticPageController:
class StaticPagesController < ApplicationController
def home
if logged_in?
#tweet = current_user.tweets.build
#feed_items = current_user.feed.paginate(page: params[:page])
#groupi = Grouprel.where(user_id: current_user.id).pluck(:group_id)
#groupies = Group.where(id: #groupi).paginate(page: params[:page])
end
end
.....
end
Home.html.erb:
<% if logged_in? %>
.......
<section class="user_info">
<%= render 'shared/group_participation' %>
</section>
</aside>
.............
_group_participation.html.erb
<h5> Your groups: </h5>
<% if #groupies %>
<ol class="tweets">
<%= content_tag_for(:li, #groupies) do %>
<%= link_to #groupies.name, group_path(#groupies) %>
<% end %>
</ol>
<%= will_paginate #groupies %>
<% end %>
here I want to display every single group that a user is part of. The error I get when trying to get the #groupies in the StaticPagesController is %23<Group::ActiveRecord_Relation:0x007f86b00f6ed0> . I checked in my rails console , and it should return something.
What my limited knowledge about rails and ruby can tell is that this is a problem because the StaticPageController can't see the Grouprel.rb table. I tried to include controllers in herlpers. I even tried to define a method that returns 'groupies' in the application controller and then use that in the StaticPagesController. Could I get a hint of why I get that error returned ?
If my post has to contain any more specifications please do tell I will post them the second I see the request
You're not iterating over the groupies collection and are calling the name method on the collection itself. content_tag_for can iterate over the collection for you but you need to use the value it yields to the block:
<%= content_tag_for(:li, #groupies) do |group| %>
<%= link_to group.name, group_path(group) %>
<% end %>

Rails nested form not saving children

My User model has_many Responses. I'm trying to create a nested form to create a new user with three child responses. My code looks identical to the Rails cast, but although it will save the user it does not save their responses. Can anyone see what is wrong?
users_controller.rb
class UsersController < ApplicationController
def new
#user = User.new
3.times{#user.responses.build}
#responses = #user.responses
end
def create
#user = User.new(user_params)
if #user.save
redirect_to #user #todo: where do we want to redirect?
else
render 'new'
end
end
def show
#user = User.find(params[:id])
#responses = #user.responses
end
def index
#users = User.all
end
private
def user_params
params.require(:user).permit(:username, :email, :responses)
end
end
user.rb
class User < ActiveRecord::Base
attr_accessor :responses_attributes
has_many :responses, :dependent => :destroy
accepts_nested_attributes_for :responses#, :reject_if => lambda { |a| a[:content].blank? }, :allow_destroy => true
before_save { self.email = email.downcase }
validates :username, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, format: { with: VALID_EMAIL_REGEX } ,
uniqueness: {case_sensitive: false};
validates :responses, presence: true
end
response.rb
class Response < ActiveRecord::Base
belongs_to :user
validates_presence_of :user_id, :content
end
users/new.html.erb (the form)
<h1>This is a test form for adding Users with child Responses</h1>
<%= form_for #user do |f| %>
<%= render 'shared/error_messages' %>
<%= f.label :username %>
<%= f.text_field :username %>
<%= f.label :email %>
<%= f.text_field :email %>
<p>
<%= f.fields_for :responses do |builder| %>
<%= builder.label :content, "Response" %>
<%= builder.text_field :content %>
<% end %>
</p>
<%= f.submit "Submit" %>
<% end %>
Edit:
I have change the strong parameters in the Users controller to:
def user_params
params.require(:user).permit(:username, :email, responses_attributes: [:content])
end
And I have updated the User model to:
class User < ActiveRecord::Base
has_many :responses, :dependent => :destroy
accepts_nested_attributes_for :responses#, :reject_if => lambda { |a| a[:content].blank? }, :allow_destroy => true
before_save { self.email = email.downcase }
validates :username, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, format: { with: VALID_EMAIL_REGEX } ,
uniqueness: {case_sensitive: false};
validates_associated :responses, presence: true
end
Now it continues to fail my validations for the responses, and also fails my validations for username and email.
The problem is in your Response class:
validates_presence_of :user_id, :content
This validation requires the existence of user_id, which means the User has to be created before Response. To make it work you can try couple of things:
Change validates_presence_of :user_id to validates_presence_of :user to make it validate the User object instead of the user's id.
Use inverse_of option. See the Rails API doc.
Updated code.
user.rb
class User < ActiveRecord::Base
attr_accessible :responses_attributes
has_many :responses, :dependent => :destroy, :inverse_of => :user
accepts_nested_attributes_for :responses
# ...
end
response.rb
class Response < ActiveRecord::Base
belongs_to :user, :inverse_of => :responses
validates_presence_of :user, :content
end
Answer for RoR v3:
The problem is the following line in your User model:
attr_accessor :responses_attributes
Replace it with:
attr_accessible :responses_attributes
The answer to question Difference between attr_accessor and attr_accessible should help you understand the difference between the two.
Also your validation validates :responses, presence: true needs to be updated to use validates_associated:
validates_associated :responses, presence: true
Answer for RoR v4:
I hadn't noticed the use of Strong parameters ealier, apologies for this. A couple of changes should fix your issue:
Remove attr_accessor :responses_attributes from User model.
Replace validates :responses, presence: true with validates_associated :responses, presence: true
Define responses attributes in permit list.
Something like follows:
class User < ActiveRecord::Base
# attr_accessor :responses_attributes # Remove this line
has_many :responses, :dependent => :destroy
accepts_nested_attributes_for :responses#, :reject_if => lambda { |a| a[:content].blank? }, :allow_destroy => true
...
validates_associated :responses, presence: true # Update here
end
#Users Controller
class UsersController < ApplicationController
...
private
def user_params
params.require(:user).permit(:username, :email, :responses_attributes[:content])
end
end
Your code looks almost correct:
user.rb
class User < ActiveRecord::Base
has_many :responses, :dependent => :destroy
accepts_nested_attributes_for :responses
before_save { self.email = email.downcase }
validates :username, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, format: { with: VALID_EMAIL_REGEX } ,
uniqueness: {case_sensitive: false};
end
users_controller.rb
private
def user_params
params.require(:user).permit(:username, :email, responses_attributes: [:content])
end

Resources