I am new to ruby on rails. I am originally a PHP/mysql programmer. I can not seem to understand how you connect any posts to the user and display them (e.g. a post is successfully created with the user ID and then the users ID is queried to get his or her name.)
I am using devise for authentication.
Controller
def create
poll = current_user.polls.build(params[:poll])
poll.onefourty = poll.onefourty[0..140]
poll.created_at = Time.now
poll.save!
if #poll.save
redirect_to root_path
else
redirect_to root_path
end
end
Form
<%= form_for Poll.new, :html => { :multipart => true } do |f| %>
<div id="form">
<div class="text_input" style="height: 65px;"><%= f.text_area :onefourty %><div class="label" style="height: 63px; line-height: 63px;">Question</div></div>
<div class="text_input"><%= f.text_field :option1 %><div class="label">Option One</div></div>
<div class="text_input"><%= f.text_field :option2 %><div class="label">Option Two</div></div>
<div class="text_input"><%= f.text_field :option3 %><div class="label">Option Three</div></div>
<div class="text_input"><%= f.text_field :option4 %><div class="label">Option Four</div></div>
<div id="submit">
<div id="left">
</div>
<%= f.submit :id => "next", :value => "" %>
</div>
</div>
<% end %>
Migrations:
create_table "polls", :force => true do |t|
t.text "onefourty"
t.string "option1"
t.string "option2"
t.string "option3"
t.string "option4"
t.string "option5"
t.string "option6"
t.datetime "created_at"
t.datetime "updated_at"
t.string "photo1_file_name"
t.string "photo1_content_type"
t.integer "photo1_file_size"
t.datetime "photo1_updated_at"
t.string "photo2_file_name"
t.string "photo2_content_type"
t.integer "photo2_file_size"
t.datetime "photo2_updated_at"
t.string "photo3_file_name"
t.string "photo3_content_type"
t.integer "photo3_file_size"
t.datetime "photo3_updated_at"
t.string "photo4_file_name"
t.string "photo4_content_type"
t.integer "photo4_file_size"
t.datetime "photo4_updated_at"
end
create_table "users", :force => true do |t|
t.string "email", :default => "", :null => false
t.string "encrypted_password", :limit => 128, :default => "", :null => false
t.string "password_salt", :default => "", :null => false
t.string "confirmation_token"
t.datetime "confirmed_at"
t.datetime "confirmation_sent_at"
t.string "reset_password_token"
t.string "remember_token"
t.datetime "remember_created_at"
t.integer "sign_in_count", :default => 0
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at"
t.datetime "updated_at"
t.string "username"
t.string "firstname"
t.string "lastname"
t.string "avatar_file_name"
t.string "avatar_content_type"
t.integer "avatar_file_size"
t.datetime "avatar_updated_at"
end
Assuming you have the following structure:
# app/model/user.rb
class User < ActiveRecord::Base
has_many :polls
#...
end
# app/model/poll.rb
class Poll < ActiveRecord::Base
belongs_to :user
#...
end
And if you're successfully creating polls, which it appears you probably are, then in any view - you could query and display the current user's polls with:
# app/views/polls/index.html.erb
<%- if current_user -%>
<%- current_user.polls.each do |poll| -%>
<h2><%= poll.onefourty %></h2>
<ul>
<li><%= poll.option1 %></li>
<li><%= poll.option2 %></li>
<li><%= poll.option3 %></li>
<li><%= poll.option4 %></li>
<li><%= poll.option5 %></li>
<li><%= poll.option6 %></li>
</ul>
<%- end -%>
<%- else -%>
<em>Not logged in</em>
<%- end -%>
Related
I want to save a record to a Bookings table that has foreign keys from Schedules and Users table.
Here is the schema:
create_table "bookings", force: :cascade do |t|
t.integer "seats"
t.integer "base_price"
t.integer "total_price"
t.string "status"
t.integer "schedules_id", null: false
t.integer "users_id", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["schedules_id"], name: "index_bookings_on_schedules_id"
t.index ["users_id"], name: "index_bookings_on_users_id"
end
create_table "schedules", force: :cascade do |t|
t.string "departure", null: false
t.string "destination", null: false
t.integer "seats_available", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.integer "price"
t.datetime "date_time"
end
create_table "users", force: :cascade do |t|
t.string "email", null: false
t.string "password_digest", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.string "firstname", null: false
t.string "lastname", null: false
end
Schedule and User has_many :bookings and Booking belongs_to :schedules and :users.
My view in bookings/new.html.erb
<%= form_for(#book, url: booking_path, local: true) do |f| %>
<% #books.each do |data| %>
<%= data.departure %>
<%= data.destination %>
<%= data.formatted_date_time %>
<%= data.seats_available %>
<%= data.price %>
<%= f.hidden_field :base_price, value: data.price %>
<%= f.hidden_field :seats %>
<%= f.hidden_field :total_price %>
<%= f.submit "Book" %>
<% end %>
<% end %>
I'm not sure this is the best way to do it but this is my attempt. Assume the hidden fields has a way to get the data, because I cut out the code that does it since I can see the params being passed in the Command Prompt.
My routes:
get 'booking', to: 'bookings#new'
post 'booking', to: 'bookings#create'
My BookingsController:
def new
#books = Schedule.where(id: params[:book_id])
#book = Booking.new
end
def create
#book = Booking.new(booking_params)
if #book.save
flash[:success] = 'success'
redirect_to root_path
end
end
private
def booking_params
params.require(:booking).permit(:base_price, :seats, :total_price)
end
In the command prompt it does display the parameters { "booking"=>{"base_price"=>"80", "seats"=>"2", "total_price"=>"160"}, "commit"=>"Book"}. The problem is that after that it now loads bookings/create.html.erb without saving the params. It somehow doesn't do the if #book.save part. Also I don't know how I can put the foreign keys or the :status variable or do I even need to. I appreciate the help!
I'm attempting to add custom fields like first name, last name, avatar_url, and bio to my Spree user.
I added the fields to the table successfully:
class AddFieldsToSpreeUser < ActiveRecord::Migration[6.0]
def change
add_column :spree_users, :first_name, :string
add_column :spree_users, :last_name, :string
add_column :spree_users, :bio, :text
add_column :spree_users, :avatar_url, :string
end
end
I checked and the schema was updated according to plan:
create_table "spree_users", id: :serial, force: :cascade do |t|
t.string "encrypted_password", limit: 128
t.string "password_salt", limit: 128
t.string "email"
t.string "remember_token"
t.string "persistence_token"
t.string "reset_password_token"
t.string "perishable_token"
t.integer "sign_in_count", default: 0, null: false
t.integer "failed_attempts", default: 0, null: false
t.datetime "last_request_at"
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.string "login"
t.integer "ship_address_id"
t.integer "bill_address_id"
t.string "authentication_token"
t.string "unlock_token"
t.datetime "locked_at"
t.datetime "reset_password_sent_at"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "spree_api_key", limit: 48
t.datetime "remember_created_at"
t.datetime "deleted_at"
t.string "confirmation_token"
t.datetime "confirmed_at"
t.datetime "confirmation_sent_at"
t.string "first_name"
t.string "last_name"
t.text "bio"
t.string "avatar_url"
t.index ["bill_address_id"], name: "index_spree_users_on_bill_address_id"
t.index ["deleted_at"], name: "index_spree_users_on_deleted_at"
t.index ["email"], name: "email_idx_unique", unique: true
t.index ["ship_address_id"], name: "index_spree_users_on_ship_address_id"
t.index ["spree_api_key"], name: "index_spree_users_on_spree_api_key"
end
I added the new attributes to the Spree initializer:
Spree::PermittedAttributes.user_attributes << [:first_name]
Spree::PermittedAttributes.user_attributes << [:last_name]
Spree::PermittedAttributes.user_attributes << [:bio]
Spree::PermittedAttributes.user_attributes << [:avatar_url]
When I try to create a new user in rails c the new attributes come up as part of the model.
I have the following form to attempt to update the user:
<%= simple_form_for current_spree_user, url: spree.spree_user_registration_path(current_spree_user) do |f| %>
<%= f.object.errors.full_messages.join(", ") if f.object.errors.any? %>
<div class="row text-left">
<div class="col-sm-6 py-3">
<%= f.label "First Name" %>
<%= f.text_field :first_name, class: "form-control", required: true, autofocus: true, input_html: { autocomplete: "fname" } %>
</div> <!-- col -->
<div class="col-sm-6 py-3">
<%= f.label "Last Name" %>
<%= f.text_field :last_name, class: "form-control", input_html: { autocomplete: "lname" } %>
</div> <!-- col -->
<div class="col-12 py-3">
<%= f.label "Author Bio" %>
<%= f.text_area :bio, class: "form-control" %>
</div> <!-- col -->
<div class="col-12 py-3">
<%= f.label "Profile Image URL" %>
<%= f.text_field :avatar_url, class: "form-control", input_html: { autocomplete: "lname" } %>
</div> <!-- col -->
</div> <!-- row -->
<div class="form-actions text-center">
<%= f.button :submit, "Let's Go", class: "btn blue" %>
</div>
<% end %>
When I hit submit, I get a routing error:
ActionController::UnknownFormat
I have tried specifying method: :patch but it gets the same result. Can anyone see where I'm going wrong here?
I am very new to rails and active record so I'm probably doing something wrong, but... using the schema below, I want to create a list of courses in the outer do loop, then list each student enrolled in the course with the inner do loop. I m not sure if this approach will work, but this error keeps popping up:
ActionView::Template::Error (undefined method `enrollments' for #):
it seems that the association is made. what am i doing wrong?
Professor show page:
<div class="col-md-8">
<h2 class="card-title"><%= #professor.name %></h2>
<% #courses_taught.each do |course| %>
<div class="card mb-4 card-header">
<img class="card-img-top" src="http://placehold.it/750x300" alt="Card image cap">
<h3 class="card-text"><%= course.title %></h3>
</div>
<div class="card-body">
<% course.sections.enrollments.students.each do |student| %>
<p><% student.name %></p>
<% end %>
</div>
<% end %>
</div>
models:
enrollment
class Enrollment < ApplicationRecord
belongs_to :section
belongs_to :student
end
Student:
class Student < ApplicationRecord
has_many :enrollments
end
Professor:
class Section < ApplicationRecord
has_many :enrollments
belongs_to :professor
belongs_to :course
validates_uniqueness_of :professor_id, scope: :course_id
scope :by_professor_id, ->(prof_id) { where('professor_id = ?', prof_id) }
end
Course:
class Course < ApplicationRecord
enum status: { planning: 0, offered: 1 }
scope :offered, -> { where(status: 1) }
scope :planning, -> { where(status: 0) }
belongs_to :department
has_many :sections
has_many :professors, through: :sections
validates :title, :number, :status, :description, presence: true
validates :description, length: { in: 10..500 }
validates :title, :number, uniqueness: { case_sensitive: false }
def self.search(term)
if term
where('title LIKE ?', "%#{term}%").order('title DESC')
else
order('title ASC')
end
end
def self.taught_by(professor_id)
Course
.joins(:sections)
.joins(:professors)
.where(sections: { professor_id: professor_id })
.select('distinct courses.*')
end
end
Schema:
ActiveRecord::Schema.define(version: 20171013201907) do
create_table "courses", force: :cascade do |t|
t.string "title"
t.text "description"
t.string "number"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "status", default: 0
t.integer "department_id"
t.index ["department_id"], name: "index_courses_on_department_id"
end
create_table "departments", force: :cascade do |t|
t.string "name"
t.text "description"
t.text "main_image"
t.text "thumb_image"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "enrollments", force: :cascade do |t|
t.integer "section_id"
t.integer "student_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["section_id"], name: "index_enrollments_on_section_id"
t.index ["student_id"], name: "index_enrollments_on_student_id"
end
create_table "professors", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "status", default: 0
t.integer "department_id"
t.text "bio"
t.index ["department_id"], name: "index_professors_on_department_id"
end
create_table "sections", force: :cascade do |t|
t.integer "number"
t.integer "max_enrollment"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "professor_id"
t.integer "course_id"
t.string "room"
t.index ["course_id"], name: "index_sections_on_course_id"
t.index ["professor_id", "course_id"], name: "index_sections_on_professor_id_and_course_id", unique: true
t.index ["professor_id"], name: "index_sections_on_professor_id"
end
create_table "students", force: :cascade do |t|
t.string "name"
t.decimal "gpa"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "name"
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "roles"
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
end
enrollment belongs_to user, there is no need to use each on single record rather it will throw error. You can use below code.
<% course.sections.each do |section| %>
<% section.enrollments.each do |enrollment| %>
<p><% enrollment.student.name %></p>
<% end %>
<% end %>
Sean's answer is almost correct but since enrollments belongs_to student
you would use the singular form enrollment.student. but more simply you can just call student from inside enrollments block.
<div class="col-md-8">
<h2 class="card-title"><%= #professor.name %></h2>
<% #courses_taught.each do |course| %>
<div class="card mb-4 card-header">
<img class="card-img-top" src="http://placehold.it/750x300" alt="Card image cap">
<h3 class="card-text"><%= course.title %></h3>
</div>
<div class="card-body">
<% course.sections.each do |section| %>
<% section.enrollments.each do |enrollment| %>
<p><% enrollment.student.name %></p>
<% end %>
<% end %>
</div>
<% end %>
</div>
<div class="col-md-8">
<h2 class="card-title"><%= #professor.name %></h2>
<% #courses_taught.each do |course| %>
<div class="card mb-4 card-header">
<img class="card-img-top" src="http://placehold.it/750x300" alt="Card image cap">
<h3 class="card-text"><%= course.title %></h3>
</div>
<div class="card-body">
<% course.sections.each do |section| %>
<% section.enrollments.each do |enrollment| %>
<p><% enrollment.student.name %></p>
<% end %>
<% end %>
</div>
<% end %>
</div>
I am using rails 4, and I want to show monthly ticket generated through pie charts. Can anybody help?
Schema:
create_table "tickets", force: :cascade do |t|
t.integer "store_id"
t.integer "vendor_id"
t.datetime "ticket_date"
t.datetime "deadline"
t.text "description"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "ticket_no"
t.string "vendor_name"
t.string "user_id"
t.integer "issue_id"
t.integer "category_id"
t.boolean "completed", default: false
end
My ticket.rb contains:
def self.category_count(user,category)
if user.vendor.nil?
category.tickets.where('store_id = ?', user.store.id)
else
category.tickets.where('vendor_id = ?', user.vendor.id)
end
end
def self.ticket_count(user,ticket)
if user.vendor.nil?
ticket.tickets.where('store_id = ?', user.store.id)
else
ticket.tickets.where('vendor_id = ?', user.vendor.id)
end
end
view:
tickets:
index.html.erb file is:
<% data = {} %>
<% for category in Category.all %>
<% data[:"#{category.name}"] = Ticket.category_count(current_user,category).count %>
<% end %>
<%= pie_chart(data) %>
I would probably start by moving this into a view helper method such as:
def pie_chart_data(user)
Hash[*Category.all.map { |c| [c.name, Ticket.category_count(user, c).count] }]
end
You could then call this in your view
<%= pie_chart(pie_chart_data(current_user)) %>
I'm using a gem called mailboxer to allow users to send messages among each other:
Here is what I have in my conversations controller:
class ConversationsController < ApplicationController
...
private
def mailbox
#mailbox ||= current_user.mailbox
end
def conversation
#conversation ||= mailbox.conversations.find(params[:id])
end
def conversation_params(*keys)
fetch_params(:conversation, *keys)
end
def message_params(*keys)
fetch_params(:message, *keys)
end
def fetch_params(key, *subkeys)
params[key].instance_eval do
case subkeys.size
when 0 then self
when 1 then self[subkeys.first]
else subkeys.map{|k| self[k] }
end
end
end
end
And this is what I have in my conversations show view:
<p> <%= conversation.subject %> </p>
<%= content_tag_for(:p, conversation.receipts_for(current_user)) do |receipt| %>
<% message = receipt.message %>
<p>
<%= message.body %>
</p>
<% end %>
<%= render 'messages/form', conversation: conversation %>
Which works, but the messages are all scrambled. How do I order the messages of the conversation by when they were created?
My schema pertaining to mailboxer:
create_table "receipts", force: true do |t|
t.integer "receiver_id"
t.string "receiver_type"
t.integer "notification_id", null: false
t.boolean "is_read", default: false
t.boolean "trashed", default: false
t.boolean "deleted", default: false
t.string "mailbox_type", limit: 25
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "receipts", ["notification_id"], name: "index_receipts_on_notification_id"
create_table "conversations", force: true do |t|
t.string "subject", default: ""
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "notifications", force: true do |t|
t.string "type"
t.text "body"
t.string "subject", default: ""
t.integer "sender_id"
t.string "sender_type"
t.integer "conversation_id"
t.boolean "draft", default: false
t.datetime "updated_at", null: false
t.datetime "created_at", null: false
t.integer "notified_object_id"
t.string "notified_object_type"
t.string "notification_code"
t.string "attachment"
t.boolean "global", default: false
t.datetime "expires"
end
add_index "notifications", ["conversation_id"], name: "index_notifications_on_conversation_id"
I think you just need to order the receipts like this:
<%= content_tag_for(:p, conversation.receipts_for(current_user).order(:created_at)) do |receipt| %>