Cannot manage associations in Ruby on Rails - ruby-on-rails

I have a Post model which is used to store content posted by guest users, and that content is managed by an Admin user. The admin has the rights to block or unblock a particular post.
What I want to do is this:
Display all unblocked Posts to the Guest Users.
Display all Posts to the admin user.
For the first requirement, I have a model BlockedPost which has a polymorphic association with Post model. The post that will be blocked by the admin will be maintained in the BlockedPost model.
For the second requirement I have to give admin the right to block or unblock any particular content. So in my posts/index.html.erb I have done this
<% #posts.each do |post| %>
<% post.content %>
<% if post.post_blocked? %>
<td><%= link_to 'Unblock', blocked_post_path(content.id),:method => :delete%></td>
<% else %>
<td><%= link_to 'Block', create_blocked_post_path(content.id) %></td>
<% end %>
<% end %>
The post_blocked? method above is defined in the Post model:
class Post < ActiveRecord::Base
def post_blocked?
!self.blocked_posts.nil?
end
end
This works but the problem is every time the post_blocked? method is called it makes a database call.
Is there any way to stop this behavior and get the status of all posts in one database call itself?

hmm... i think you should change your models a little, because they are unconfortable a bit and there isnt any fast way to get your posts from DB,
delete BlockedPost model
and add a column to Post model (in migration)
t.boolean :blocked, :default => true
I'd do it like this:
#blocked_posts = Post.where( :blocked => false)
#unblocked_posts = Post.where( :blocked => true )
or prepare scopes in your Post model
and then in your view just display 2 lists
<% #unblocked_posts.each do |upost| %>
<%= upost.content %>
<%= link_to 'Block that post', ... %>
<% end %>
<% #blocked_posts.each do |bpost| %>
<%= bpost.content %>
<%= link_to 'Unblock', ... %>
<% end %>

Related

ActiveRecord_Associations_CollectionProxy:0x0000000e490b98 in RoR

I'm creating a application using ruby on rails, but currently i'm suffering a problem like db relation, below my code:
Company
has_many :posts, :foreign_key => :company_id
Post
belongs_to :companies, :foreign_key => :company_id
controller
#post = current_user.companies.all
view
<% #post.each do |p| %>
<%= p.posts.post_title %>
<% end %>
Showing error above code.
If I debug like use <%= debug p.posts %> then showing all posts, which is under my companies but when I use <%= debug p.posts.post_title %> then showing ActiveRecord_Associations_CollectionProxy:0x0000000e490b98
Thanks
I think the problem here is that you are trying to call the method :post_title on p.posts, which is an ActiveRecord::Associations::CollectionProxy object.
In your example, p is a Company object, which has a method posts, which returns to you a CollectionProxy object that acts a lot like a list of posts. That list will not have a method post_title, but each element of that list will have a method post_title
So, instead of
<% #post.each do |p| %>
<%= p.posts.post_title %>
<% end %>
You will want something like:
<% #post.each do |company| %>
<% company.posts.each do |post| %>
<%= post.post_title %>
<% end %>
<% end %>
Two additional things to note:
1) The variable #post is inaccurately named. Inaccurate variable names will lead to confusion when trying to understand what is happening. current_user.companies.all returns a list of companies, and therefore, it should read:
#companies = current_user.companies.all
not
#post = current_user.companies.all
2) The actual error that is being shown to you likely says something like
Undefined Method 'post_title' for ActiveRecord_Associations_CollectionProxy:0x0000000e490b98
Not just
ActiveRecord_Associations_CollectionProxy:0x0000000e490b98
When debugging and asking for help, it's very important to note the entire message of the exception being raised.
Because companiy has_many :posts........ posts are objects you need a loop to show all posts e.g
p.posts.each do |post|

Devise - how to show user's post

I use Devise gem for authentication.
In database I have users table and posts table in my database schema (and Post controller).
In post controller I want to find all posts assigned to specific user. I have user_id in posts table.
How to get all user's posts or how to check if specific post is assigned for SIGNED IN user.
I thought about something like this (of course is only pseudocode:
current_user.id == Post.where(params:[post_id]).user_id
So how to get current user id in Devise and how to check the current user id is the same like eg. user_id assigned to viewing post (I want to add 'edit' function when current user is post owner) and how to find all post which current user is owner.
Associations
Firstly, your user_id column in your posts table is what's known as a foreign_key
Foreign keys are used in relational database systems to give you the ability to call associative data from a single record. Simply, it means that you'll be able to use the ActiveRecord associations to call the data you require, rather than having to call it individually:
#app/models/user.rb
class User < ActiveRecord::Base
has_many :posts
end
#app/models/post.rb
class Post < ActiveRecord::Base
belongs_to :user
end
This will give you the ability to use the following call:
#app/controllers/posts_controller.rb
class PostsController < ApplicationController
def index
#posts = current_user.posts
end
end
You'll be best served looking up the has_many association:
Fix
In regards to showing your posts for your users, you need to be sure that you have the correct "flow" set up. What I mean is you need some condition to know whether your user is signed in & that #posts is set:
#app/views/posts/index.html.erb
<% if #posts.present? %>
<% #posts.each do |post| %>
<%= post.title %>
<% end %>
<% end %>
Maybe this is the first time you use Devise. You can access current_user inside controllers or views. I imagine you could do something like this
In controller (posts_controller.rb):
#posts = current_user.posts
In view (posts/show.html.erb, I guess):
if current_user.id = #post.current_user
#render something here
end
Get all post which current user is owner.
#posts = Post.where(:user_id => current_user.id)
and on your view
<%-# commented : checking if #posts is empty -%>
<% if #posts.empty? %>
<span>Sorry, post is empty </span>
<% else %>
<%= #posts.each do |p| %>
<% if p.user_id == current_user.id %>
<% link_to "edit", edit_path(p) %>
<% end %>
<% end %>
<% end %>
There are many ways you could get current_user posts. I'll go the long way.
we need
an action
an action view and a partial
a route
a link_to
* action *
def my_posts
#posts = current_user.posts.all.order(created_at: 'DESC')
end
* view *
my_posts.html.erb
<% if #posts.present? %>
<%= render 'posts' posts: #posts %>
<% else %>
<h1>You don't have any posts yet! create one</h1>
<% end %>
_posts.html.erb
<%posts.each do |post| %>
<%= post.title %>
<% end %>
index.html.erb
<%= render 'posts' posts: #posts %>
route
get 'post' => 'posts#my_posts', as: :my_posts
link_to
<%= link_to 'My posts', my_posts_path %>
I may be late but someone can find it useful :)

Rails Form element to convey two values

I have a form that takes bookings for an event for people. The form displays events vertically, and a name & checkbox for each of the possible people next to each event.
How should I best convey the two pieces of information that i need per checkbox? that is, the event_id and the person_id
I'm not totally sure wether I got you right. This is the model I assume you're talking about:
# event.rb
class Event
has_many :people
scope :possible_people, -> { #whatever .. }
end
# person.rb
class Person
belongs_to :event
end
# events_controller.rb
class EventsController
def index
#events = Event.all
end
end
And this might be a possible solution to change an events relation to people:
# index.html.erb
<ul id="events">
<% #events.each do |event| %>
<li class="event">
<%= form_for #event do |form| %>
<% event.possible_people.each do |person| %>
<%= check_box_tag "event[person_ids][]", person.id, #event.people.include?(person) %>
<% end %>
<%= f.submit_tag 'Save Event' %>
<% end %>
</li>
<% end %>
</ul>
The important part is <%= check_box_tag "event[person_ids][]", person.id, #event.people.include?(person) %> where you actually change the the relation of a specific person to the event.
Good luck ;)
Well, you can try out something like below line, I am assuming you have a multiselect checkboxes and i am passing a Hash of event_id => plate_id as value to checkbox.
<%= check_box_tag 'booking[event_people_ids][]', {booking.event_id => booking.plate_id} %>
You will get the value in params as:
booking => {event_people_ids =>["{"72"=>"3"}}
I ended up doing this:
<%= check_box_tag "booking[]", "#{event.id}-#{person.id}" %>
and then in then to process them:
params[:booking].each do |booking|
booking = booking.split('-')
a = {
:booking_id => #booking.id,
:person_id => booking[1],
:event_id => booking[0]
}
Appointment.create(a)
end
I was hoping for a more railish way to do it but this works.

Adding "Featured Posts" to my blog

I am trying to add a featured post feature to my Ruby on Rails Blog. So far I have added a featured_post column to my post table and it passes a 1 if the check box is selected and 0 if not.
Now I am attempting to pull out these posts by doing the following:
/views/posts/index.html.erb
<% #featured_post.each do |post| %>
<%= post.title %>
<% end %>
And in the posts_controller.rb I am doing the following in the index action:
#featured_post = Post.all
Obviously this brings in all the post titles which is not what I want. I am assuming I have to add something to the controller to all for this but not sure what that is.
In your post model, write this
named_scope :featured,:conditions => {:featured_post => true }
write this in your controller
#featured_posts = Post.featured
and in view use this,
<% #featured_posts.each do |post| %>
<%= post.title %>
<% end %>
now you should get all the featured posts.

How add logic to Views? Ruby on Rails

Right now I'm building a project management app in rails, here is some background info:
Right now i have 2 models, one is User and the other one is Client. Clients and Users have a one-to-one relationship (client -> has_one and user -> belongs_to which means that the foreign key it's in the users table)
So what I'm trying to do it's once you add a client you can actually add credentials (add an user) to that client, in order to do so all the clients are being displayed with a link next to that client's name meaning that you can actually create credentials for that client.
What i can't figure it out how to do is, that if you actually have credentials in the database (meaning that there's a record in the users table with your client id) then don't display that link.
Here's what i thought that would work
<% for client in #client%>
<h5>
<h4><%= client.id %></h4>
<%= client.name %>
<% for user in #user %>
<% if user.client_id = client.id %>
Credentials
<%end%>
<% end %>
</h5>
<% end %>
And here's the controller:
def index
#client = Client.find_all_by_admin(0)
#user = User.find(:all)
end
but instead it just puts the link the amount of times per records in the user table. Any help?
You can do the following
# controller
def index
#clients = Client.find_all_by_admin(0, :include => :user)
end
# view
<% #clients.each do |client| %>
<h5>
<h4><%= client.id %></h4>
<%= link_to client.name, {:action => 'show', :id => client.id} %>
<% if client.user.blank? %>
<%= link_to "Credentials",
{:controller => 'user', :action => 'new', :client_id => client.id} %>
<% end %>
</h5>
<% end %>
Edit
Better solution, getting in the controller only the clients who doesn't have a user yet:
# model
class Client < ActiveRecord::Base
has_one :user
named_scope :without_user,
:conditions => "id NOT IN ( SELECT client_id FROM users )"
end
# controller
#clients = Client.without_user.find_all_by_admin(0)
# view
<% #clients.each do |client| %>
<h5>
<h4><%= client.id %></h4>
<%= link_to client.name, {:action => 'show', :id => client.id} %>
<%= link_to "Credentials",
{:controller => 'user', :action => 'new', :client_id => client.id} %>
</h5>
<% end %>
Just to add to j.'s answer, you really should use link_to view helper instead of hardcoding URLs.
I haven't worked with Rails in sometime, but two things:
There are helpers to make your urls, it's easy to make mistakes. (Not that I see one, but just to let you know about them...)
Views should not have logic. As much as you can get away put it in the controller. Or even better in the model.
It's a good practice to not use "User.find :all", as your app grows this will kill you.
It's better to have a method in the model that gets just the info you will use. Databases are better in this case to filter.

Resources