How do I create a controller and action without a model? - ruby-on-rails

I have several models:
Email
Letter
Call
All three belong to a model Campaign. And a Campaign has_many Contacts
I envision being able to see a schedule for Today by going to domain/schedule/today
What I'd like it to do would be to show all the Events (Email, Letter, Call) that have to happen today for each campaign.
I tried the following, but have some challenges in putting it into a controller versus into a View. There are many emails in campaign.
Email.days is the number of days from the contact.start_date that an email should be sent to the Contact.
ScheduleController <
def index
campaigns.each do |campaign| #goes through each campaign
for contacts in campaign.contacts
Email.find(:all).reject { |email| email.contact.start_date + email.days <= Date.now }
end
end
end

You're actually asking the wrong question.. Controllers aren't linked to any model fundamentally, they really display whatever you want. You can have a FooController that displays all the Bars and a DogController that gives info about cats..
To solve your problem:
You're not 'sharing' anything with
your view for it to display.
You're also putting the logic in the
wrong place, and you're not actually
fetching the campaigns from the
database..
In your controller you need to fetch the data from the DB:
def index
#campaigns = Campaign.all #share the list of campaigns with the view
end
In your view you display the campaign info..
<% for campaign in #campaigns %>
<!-- display info about the campaign -->
<% for contacts in campaign.contacts %>
<!-- contact level info and so on.. -->
<% end %>
<% end %>
There's much more to it, but hopefully this gets you pointed in the right direction.

Related

Using Thumbs_up to display users who voted on a post

I'm using Thumbs_Up gem to let users vote on a post(called Topic). I've done the voting part but now I want to display the users who voted on that particular post. I'm very new to Ruby On Rails, and I'm stuck at the view part.
Here's my controller: app/controllers/topics_controller.rb
def vote_who
#topic = Topic.find(params[:id])
#vote_list=#topic.voters_who_voted_for
end
In my index.html.erb, I want to display the names of there users who voted on that post. This should be right next to the vote button. Kind of like this,
But how do I send back information from the controller?
Or is this approach completely wrong?
IMHO, it's more preferable to show all voters in the 'show' view of the each particular Topic (imagine you have 100 voters for one topic, what this table in index view will look like?).
This way you don't need any distinct action (due to Rails conventions 1 action == 1 view (in general)). Just put in your show action:
def show
#topic = Topic.find(params [:id])
#vote_list = #topic.voters_who_voted_for
end
Then in your view (show.html.erb) you need to do something like this:
<% #vote_list.each do |voter| %>
<%= voter.email %> #or login, or name, or any user's attribute you want to display in your list
<% end %>
Or even try to simplify this: leave show action in your TopicsController as it is (don't create any #vote_list variable, only find right Topic), and call voters_who_voted_for method inside your show view, e.g.:
<%= #topic.title %>
<%= #topic.body %>
<%= #topic.voters_who_voted_for %>

How to show content if current_user meets the requirements

How should I write a if condition in the view using Slim? I would like to show content if the current_user is a subscriber. I have a subscriptions table with a user_id and cancelled column. User has access to the website if their id can be found in the subscriptions table under user_id and the cancelled column is NULL. If cancelled has a 1 value then the user no longer has access.
If you have your relationship set up, something like this as an instance method in the user model should work.
def subscribed?
subscriptions.where(cancelled: nil).exists?
end
Then in the view, you can do something like:
<% if user.subscribed? %>
Here ya go
<% else %>
Go away
<% end %>
You could obviously just put the logic in the subscribed? method in the view, but this is a little cleaner, maybe.

Restricting a model to only view their own items in the has_many

So I'm trying to think about how to route my site and I need a little help. I have a business who can .build (as in business creates) buildings (sorry for the repetition haha) in a has_many. Each property has many something else.
I would like it so even though there will be more than one building, each business should only be able to view their own buildings, so if someone tries to alter a url, it would redirect home.
I have
resources :buildings
so as it is set up, anyone could just type in
host/buildings/whatever
I would like to redirect with an error if the building ID does not belong to the current_business (devise) it will redirect to their home page. each building has a business_id
Would I have to break the RESTful for this?
Thank you!
Assuming you have user_id in builduing resource:
buildings_controller.rb
def index
#buildings = current_user.buildings
end
def show
#building = current_user.buildings.find(params[:id])
end
buildings/index.html.erb
<% #buildings.each do |building| %>
<%= building.whatever_atribute %>
<% end %>
buildings/show.html.erb
<%= #building.whatever_atribute %>
With the above code when user will go to /buildings he will see only his buildings, and if he'll go to buildings/3 he will see this building if he owns it, in other case he will see a not found error that you can customize it with a redirect or display a styled page.

How should I use the IF statement in Ruby on Rails

I have two tables: Persons and Statuses and have created two classes Person and Status. I am using following code to show the error message "Only one status is allowed". The code is not working - I think there is some problem in my If statement.
<ul>
<% Person.all.each do |person| %>
<li>
<%= person.name %>
<% if status.size >= 1 %>
<em>Only one status is allowed</em>
<% end %>
</li>
<% end %>
</ul>
Table Persons
U_Id Name Place
1 James Florida
2 Mark California
3 Steve Newyork
Table Statuses
Id Status U_Id
1 Hi 1
2 OMG 2
3 Bye 3
4 Help me 2
Problem: Mark has posted 2 status his U_Id is 2, I want to show him a error message like Only one post is allowed. How this can be done?
Update:
Person class
class Person < ActiveRecord::Base
validates_presence_of :name
end
Your programming logic is incorrect. You are trying to impose a limit on the number of status messages a user can have, but it seems you are enforcing that limit too late, because you are printing an error message when the status is displayed rather than when it is submitted. The people viewing these messages are presumably other users and they hardly care if Mark violates your design constraints.
You have two options.
Limit the number of statuses one a user can have to one.
class User < ActiveRecord::Base
has_one :status
end
This will allow you to do:
steve = User.find(3)
steve.status
=> "Bye"
Only display the last one
Alternatively, you can allow unlimited statuses, but only display the latest one.
class User < ActiveRecord::Base
has_many :statuses
end
mark = User.find(2)
mark.statuses.last
=> "Help me"
On a side note... if users truly only have one status and the former statuses do not matter, then you should consider removing the status model and including the status as a string attribute on the user model. This will, in most cases, improve database performance.
I agree with Stas. status.size will not know what "status" is referring to. It seems like you are trying to refer to the status of each individual person, so you would need something like "person.status.size >= 1".
However, looking at your Person Class, it looks like you might not have the relationship set up yet. You need to include code in your Person class specifying that a Person has_many :statuses. So first do this and make sure that User.first.statuses works, then add the similar code to your views.
in user.rb I admit you have has_many : statuses
and in status.rb, belongs_to :user
<ul>
<% Person.all.each do |person| %>
<li>
<%= person.name %>
<% if person.statuses.size >= 1 %>
<em>Only one status is allowed</em>
<% end %>
</li>
<% end %>
</ul>
but if you want a person to have only one status, why don't you check this when a status is created? or better, when he is trying to access the new action for status check if he has a status and redirect him back with a message saying "You have a status,you can have only one."
After this you can easy use:
user has_one :status
statuses_controller check:
def new
if current_user.status.present?
redirect to :back, error: "Only one status for user"
else
#status = current_user.status.new
end
end
and when doing Person.all.each do |person| you can call directly person.status and it will be first and only one in db without needing to use an if statement. But this depends on how your app should work I guess.

ruby on rails get table row by two column conditions

For instance, I have two tables in database, Users and Microposts. The Users table stores all the users and has two columns, id and name; the Microposts table stores the posts made by the Users and has three columns: id, post_content and user_id (These two tables, of course, have the timestamp as each entry is created). So basically what I want is have a view page that displays the information stored in Users (id and name) plus the last post created by the corresponding user.
One way I'm thinking of doing is to have it being processed right at the user view page (located in, for example, app/views/Users/index.html.erb). Since I'm probably going to loop through the Users table like this
<% #Users.each do |user| %>
id = user.id
<!-- Do such and such -->
<% end %>
and while looping through the Users table, use the user.id to get the latest post made by the user.
Second way is to basically implement such that the Users table has another column that store the latest post information and updates each time when a transaction is made to the database. So then when implementing the latest post can just be accessed as an attribute.
However, I don't really know which way is better nor how to implement either way...
Any suggestion?
Thanks in advance!
Edit:
Sorry, there is a typo. It's "two tables and one database"
Similar to the other answers but I wanted to add an important little piece that I feel is commonly overlooked. Including the association on the first call to the database.
# not sure the scale of your project but I would paginate #users
# by using includes you prevent the N+1 issues
<% #users.includes(:microposts).each do |user| %>
id = user.id
user.microposts.last
<% end %>
For some documentation on this:
http://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations
class User
has_many :microposts
end
class Micropost
belong_to :user
end
# to get user's post
# for single user
#user.microposts
# for many users
#users.each do |user|
user.microposts.each do |post|
post.post_content
end
end
Your user has many microposts. So do the following on users view page i.e. app/views/Users/index.html.erb
<% #Users.each do |user| %>
id = user.id
last_post = user.microposts.last <!-- This will give you last post created by the user -->
<% end %>

Resources