Im stuck (still very new to Rails), and cant figure out why its not working:
I have:
class Message < ActiveRecord::Base
attr_accessible :updated_at
has_many :categories_messages
has_many :categories, through: :categories_messages
end
class CategoriesMessage < ActiveRecord::Base
attr_accessible :category_id, :message_id
belongs_to :category
belongs_to :message
end
class Category < ActiveRecord::Base
attr_accessible :name
has_many :categories_messages
has_many :message, through: :categories_messages
end
#messagesPer = Category.all.includes(:messages).group('categories.id').order("COUNT(messages.id) DESC")
<% #messagesPer.each_with_index do |message, i| %>
<tr>
<td><%= i+1 %></td>
<td><%= message.name %></td>
<% if message.categories_messages.exists? %>
<td><%= message.messages.last.updated_at.to_s.to_date %></td>
<td><%= message.messages.first.updated_at.to_s.to_date %></td>
<td><%= message.messages.count %></td>
<% else %>
<td>0</td>
<td>0</td>
<% end %>
</tr>
<% end %>
So i want it to show :
the name of Category, date the last message was created , date first message was created, and all messages in that category.
ALl works fine, apart from the fact that it only shows the date when the first message was created, but never the last (still shows first date on the last).
What am i doing wrong?
UPDATE:
if i put
#messagesPer = Category.all.includes(:messages).group('categories.id')
it does show the right date for last and first messages but as soon as i add order it breaks...
I might be helpful to include the error information you get after adding an order clause to the query.
However, I can spot some odd things in the code. The CategoriesMessage model seems to be there simply to satisfy the condition that a category can have many messages and vice versa. You don't need a model for this many-to-many relationship though, Rails will handle this automatically for you.
Your models should be looking like this:
class Message < ActiveRecord::Base
attr_accessible :updated_at
has_and_belongs_to_many :categories
end
class Category < ActiveRecord::Base
attr_accessible :name
has_and_belongs_to_many :messages
end
And in your database you have these tables: messages, categories,categories_messages, where the last one is the join table which only contains columns for amessage_idand acategory_id`.
Then you can simply do something like this in your code:
category.messages.each { |message| puts message.updated_at }
Also see this Ruby on Rails tutorial article for more information. If this doesn't work for you, please post the exact error you get.
Related
I created three models, one named Student, another one Cclass, and the last named Enrollment.
I have a many to many relationship where many students can have many classes and vice-versa. I wanted to fix this many to many relationship, so I created a new model named enrollment - it is supposed to display both the students in the database and the classes like this:
------ Class ------------------ Student
1. Class_name ------ 1. Student_name
At least something like that, but I am not able to display the information from both of the tables in the Enrollment's class.
This is my student.rb
class Student < ApplicationRecord
attr_accessor :FirstName
has_many :enrollments
has_many :cclasses, through: :enrollments
end
This is my class.rb
class Cclass < ApplicationRecord
attr_accessor :Name
has_many :enrollments
has_many :students, through: :enrollments
end
This is my enrollment.rb
class Enrollment < ApplicationRecord
belongs_to :student
belongs_to :cclass
end
This is my enrollments_controller.rb
class EnrollmentsController < ApplicationController
def index
#enrollment = Enrollment.all
end
def show
#enrollment = Enrollment.find(params[:Student_id, :Cclass_id])
end
def new
#enrollment.new
end
def update
end
def create
end
def edit
end
def destroy
end
private
def enrollment_params
params.require(:enrollment).permit(:Student_id, :Cclass_id)
end
end
This is my index.html.erb for my enrollment model
<h1> Enrollment's Index </h1>
<table>
<tbody>
<thead> Student and Classes Enrolled
<th> Student </th>
<th> Classes </th>
<% Array(#enrollment).each do |e| %>
<td><%= link_to e.student.FirstName %> </td>
<td><%= link_to e.cclass.Name %> </td>
<% end %>
</thead>
</tbody>
</table>
I do not know how to reference the First Name of the student and the name of the class. Thank you.
I see a couple of things you can improve first make sure to use snake_case for symbols, methods, and variables. Also, use lower case as uppercase makes reference to classes and constants. Please see below:
Student Class:
class Student < ApplicationRecord
attr_accessor :first_name
has_many :enrollments
has_many :cclasses, through: :enrollments
Cclass class:
class Cclass < ApplicationRecord
attr_accessor :name
has_many :enrollments
has_many :students, through: :enrollments
In your enrollment controller#index you're calling the method .all and assigning it to a variable named #enrollment that is not reflecting the real value of the data that is storing. Since Enrollment.all return value is an array-type object that contains all the enrollments in your DB. So with that in mind.
Enrollment controller:
class EnrollmentsController < ApplicationController
def index
#enrollments = Enrollment.all
end
def show
#enrollment = Enrollment.find(params[:student_id, :cclass_id])
end
def new
#enrollment.new
end
def update
end
def create
end
def edit
end
def destroy
end
private
def enrollment_params
params.require(:enrollment).permit(:student_id, :cclass_id)
end
end
Finally, for your index.html.erb file you have this line of code
<% Array(#enrollment).each do |e| %>
You don't need to call Array since you #enrollments variable that you've assigned in your controller action is already array-type object that responds to the method each.
<h1> Enrollment's Index </h1>
<table>
<tbody>
<thead> Student and Classes Enrolled
<th> Student </th>
<th> Classes </th>
<% #enrollments.each do |e| %>
<td><%= link_to e.student.first_name %> </td>
<td><%= link_to e.cclass.name %> </td>
<% end %>
</thead>
</tbody>
</table>
If you have any questions let me know
for some reason this page wont opening using ruby on rails 5. Its giving me a undefined method `name' for nil:NilClass error.
The code was working perfectly the last time i opened it. can anyone please help? It would be very much appreciated.
here the the view page.
<h1> Your sale history page </h1>
<table class="table table-bordered table-hover table-striped">
<tr>
<th>Image</th>
<th>Title</th>
<th>Label</th>
<th>Condition</th>
<th>Customer</th>
<th>Price</th>
<th>Date Sold</th>
</tr>
<% #orders.each do |order| %>
<tr>
<td><%= image_tag order.record.image.url(:thumb)%></td>
<td><%= order.record.Title %></td>
<td><%= order.record.Label %></td>
<td><%= order.record.Condition %></td>
<td><%= order.buyer.name %></td>
<td><%= order.record.Selling_Price %> </td>
<%#THE BELOW CODE IS FOR RUBY DATE. FOUND ON rubydoc%>
<td><%= order.created_at.strftime("%-d %B, %Y") %></td>
<td>
</tr>
<%end%>
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
#the below code validates that the name present
validates :name, presence: true
#the below code tells rails that a user has many records. and that if a user is deleted so is the record
has_many :records, dependent: :destroy
has_many :sales, class_name:"Order", foreign_key: "buyer_id"
has_many :reviews, dependent: :destroy
end
class Order < ApplicationRecord
#the below validates the form fields
validates :address,:town_or_city,:state_or_county,:post_or_zip_code,:country, presence: true
belongs_to :record
# the below code tells rails that the relationship is two sided. a user can be a buyer or a seller
belongs_to :buyer, class_name:"User"
belongs_to :seller, class_name:"User"
end
Ok I guess you need quick fix put
<td><%= order.try(&:buyer).try(&:name) %></td>
this will make sure you do not get error if ther is no buyer than see witch order is without buyer
Does order table have buyer_id on all records?
Maybe, there are records where buyer_id is null.
Or order can't get buyer because there isn't matching id.
I found below link useful to know more about 'try' usage and why 'try' is better over rescue nil option in the above scenario.
https://rubyinrails.com/2015/08/27/rescue-nil-in-ruby-on-rails
I'm a new guy to ruby on rails and working on my first in-depth application. It has four tables: Questions, Options, Answers and Users. There's a list of questions and a user can vote for a unique option (stored in the Answers join table), I'm trying to get my head around table associations.
This is how I've setup my individual RB files:
class Question < ActiveRecord::Base
has_many :options
has_many :answers, :through => :options
end
class Option < ActiveRecord::Base
belongs_to :question
has_many :answers
end
class Answer < ActiveRecord::Base
belongs_to :user
belongs_to :question
belongs_to :option
end
class User < ActiveRecord::Base
has_many :answers
has_many :questions, :through => :answers
end
My questions controller is setup like this to include the options table:
#questions = Question.includes(:options).all
and the table body in my index.html.erb file:
<tbody>
<% #questions.each do |question| %>
<tr class="<%= cycle('lineOdd', 'lineEven') %>">
<td><%= question.question_text %></td>
<td><%= link_to 'Show', question %></td>
<td><%= link_to 'Edit', edit_question_path(question) %></td>
<td><%= link_to 'Destroy', question, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% question.options.each do |option_text| %>
<tr class="backgroundColor1">
<td class="optionCell"> <%= option_text.option_text %> </td>
</tr>
<% end %>
<% end %>
</tbody>
In the Question class I've used 'has_many :answers, :through => :options' - is this the correct way to go about this and how would I output the total number of votes in a table row below the associated option.
Do I need to add to or change the question controller code?
This is my first post, sorry if I'm not informative enough!
Thanks
Lets start by fixing up the relations a bit:
class Question < ActiveRecord::Base
has_many :options
has_many :answers
has_many :users, through: :answers
end
There is nothing technically wrong with has_many :answers, :through => :options but since there is a direct relation through answers.question_id we don't need to go through the options table for the relation.
Displaying the count
If we simply did:
<td class="optionCell"><%= option.answers.count %></td>
This would create a nasty n+1 query to fetch the count of the answers for each option. So what we want to do is create a counter cache which stores a tally on the options table.
Lets start by creating a migration to add the column:
rails g migration AddAnswerCounterCacheToOptions answers_count:integer
rake db:migrate
Then we tell ActiveRecord to update the tally when we create associated records, this looks a bit strange since the counter_cache: true declaration is on the belongs_to side while the column is on the other but thats just how AR works.
class Option < ActiveRecord::Base
belongs_to :question
has_many :answers
end
class Answer < ActiveRecord::Base
belongs_to :user
belongs_to :question
belongs_to :option, counter_cache: true
end
There is a little snag here. Since we may already have records we need to make sure they have correct counters. You can do this from the console but in the long run it is a good idea to create a rake task.
Option.find_each { |option| Option.reset_counters(option.id, :answers) }
This might take a bit of time since it needs to pull each Option and update the count.
Now we can display the tally like so:
<% question.options.each do |option| %>
<tr class="backgroundColor1">
<td class="optionCell"><%= option.option_text %></td>
<td class="optionCell"><%= option.answers.size %></td>
</tr>
<% end %>
.size is smart enough to use our counter cache column, but will fall back to querying the count which is a good thing for tests.
I have following structure:
class User < ActiveRecord::Base
has_many :Hobbies, :dependent => :destroy
accepts_nested_attributes_for :hobbies, :reject_if => lambda { |a| a[:content].blank? }, :allow_destroy => true
end
class Hobby < ActiveRecord::Base
belongs_to :User
end
In my Users_controller.rb
def index
#data = User.all(:joins => :hobbies)
end
In index.html.erb
<% for item in #data %>
<tr>
<td><%= item.id %></td> #from table Users
<td><%= item.hobby_name %></td> #from table Hobbies
</tr>
<% end %>
And this gives me an error undefined method `hobby_name' for # User:0x103cf7480>
I thought that I have that associations right, but this error makes confused... Can you help me someone, please, where could be a problem?
You must specify the relation, your object doesn't have an attribute called hobby_name, it has an association to multiple hobbies, and each hobby has an attribute called hobby_name
So:
<% item.hobbies.each do |h| %>
<%= h.hobby_name %>
<% end %>
I have 2 models, car and registrations.
class Car < ActiveRecord::Base
belongs_to :Registration
end
class Registration < ActiveRecord::Base
has_many :cars, :dependent => :destroy
accepts_nested_attributes_for :cars, :reject_if => lambda { |a| a[:content].blank? }, :allow_destroy => true
end
In CarsController:
def index
#cars = Car.all
#cars2 = Car.all(:joins => :Registration)
end
In view:
<% #cars.each do |car| %>
<tr>
<td><%= car.twitter %></td>
<td><%= car.facebook %></td>
<td>
<% #cars2.Registration.each do |h| %> #here is my problem
<%= h.email %>
<% end %>
</td>
</tr>
<% end %>
This is my statement of cars. I am trying to print for every car owner's email. The email is in table Registration (model registration). I don't know how to make a query to database, that I want to get email from table Registrations, when column registration_id in table Cars == id column of table Registrations...
So I would like to ask you, if you have a tip, how to do...
You have got your associations in capital letters. It should be in small like this
class Car < ActiveRecord::Base
belongs_to :registration
end
Also you dont have to assign 2 variables in the controller
def index
#cars = Car.includes(:registration)
end
and in the view
<% #cars.each do |car| %>
<tr>
<td><%= car.twitter %></td>
<td><%= car.facebook %></td>
<td>
<%= car.registration.email %> #here is my problem
</td>
</tr>
<% end %>
Use this instead to fetch the email:
<%= car.registration.email %>
If you want eager loading, then use the following line in your controller instead:
#cars = Car.includes(:registration)
There's no need for #cars2.