No idea why this is showing the entire table. Should only be showing the list and not the table (timestamp, id, etc).
Screenshot of output.
show.html.erb
<h1><%= #application.name %></h1>
<h4><%= #application.description %></h4>
<h3>Questions</h3>
<ul>
<%= #application.tests.each do |test| %>
<li>
<%= test.question %>
</li>
<% end %>
</ul>
schema.rb
create_table "tests", force: :cascade do |t|
t.string "question"
t.integer "application_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["application_id"], name: "index_tests_on_application_id", using: :btree
end
new to this whole "coding" thing
The problem is in the #application.tests.each you are printing the return, change:
<%= #application.tests.each do |test| %>
For
<% #application.tests.each do |test| %>
<% %> and <%= %> both execute Ruby code.
<% %> will execute Ruby code, but will not render the return value into html. <%= %> will execute Ruby code, and will render the return value into html.
So use like this :-
<% #application.tests.each do |test| %>
<li>
<%= test.question %>
</li>
<% end %>
Related
I created Devise Users table and Type table. I added the type_id column to the users table through migration.
Below are the links in home.html.erb:
<%= link_to 'Basic Sign up', new_user_registration_path(type: #basic_type), class: 'btn btn-success'%>
<%= link_to 'Pro Sign up', new_user_registration_path(type: #pro_type), class: 'button' %>
Below is the pages_controller.rb
class PagesController < ApplicationController
def home
#basic_type = Type.find(1)
#pro_type = Type.find(2)
end
def about
end
end
Below are the models:
type.rb
class Type < ActiveRecord::Base
has_many :users
end
user.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable
belongs_to :type
end
This is my migration file of type:
class CreateTypes < ActiveRecord::Migration
def change
create_table :types do |t|
t.string :name
t.timestamps
end
end
end
This is the migration file adding types to user:
class AddTypeToUser < ActiveRecord::Migration
def change
add_column :users, :type_id, :integer
end
end
Users table in schema.rb:
create_table "users", force: :cascade do |t|
t.string "email", limit: 255, default: "", null: false
t.string "encrypted_password", limit: 255, default: "", null: false
t.string "reset_password_token", limit: 255
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", limit: 4, default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip", limit: 255
t.string "last_sign_in_ip", limit: 255
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "type_id", limit: 4
end
These are my registration forms:
_basic_form.html.erb:
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: {id: 'basic_type'}) do |f| %>
<%= devise_error_messages! %>
<%= hidden_field_tag 'type', params[:type] %>
<div class="field form-group">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, class: 'form-control' %>
</div>
<div class="field form-group">
<%= f.label :password %>
<% if #validatable %>
<em>(<%= #minimum_password_length %> characters minimum)</em>
<% end %><br />
<%= f.password_field :password, autocomplete: "off", class: 'form-control' %>
</div>
<div class="field form-group">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "off", class: 'form-control' %>
</div>
<div class="actions form-group">
<%= f.submit "Sign up", class: 'btn btn-success' %>
</div>
<% end %>
_pro_form.html.erb:
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<%= hidden_field_tag 'type', params[:type] %>
<div class="field form-group">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, class: 'form-control' %>
</div>
<div class="field form-group">
<%= f.label :password %>
<% if #validatable %>
<em>(<%= #minimum_password_length %> characters minimum)</em>
<% end %><br />
<%= f.password_field :password, autocomplete: "off", class: 'form-control' %>
</div>
<div class="field form-group">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "off", class: 'form-control' %>
</div>
<div class="actions form-group">
<%= f.submit "Sign up", class: 'btn btn-success', id: 'form-submit-btn' %>
</div>
<% end %>
new.html.erb:
<div class="row">
<div class="col-md-6 col-md-offset-3 text-center">
<% if params[:type] == '2'%>
<h1>Pro Account</h1>
<p>Sign up for the pro account!</p>
<% else %>
<h1>Basic Account</h1>
<p>Sign up for free and get basic access to our community.</p>
<% end %>
</div>
<div class="col-md-6 col-md-offset-3">
<div class="well">
<h2>Sign up</h2>
<% if params[:type] == '2'%>
<%= render "pro_form"%>
<% else %>
<%= render "basic_form"%>
<% end %>
<div class="actions form-group btn btn-default">
<%= render "devise/shared/links" %>
</div>
</div>
</div>
</div>
When I am signing up as basic or as pro in URL it is showing:
http://localhost:3000/users/sign_up?type=1
OR
http://localhost:3000/users/sign_up?type=2
But in database in the type_id column it is showing as nil.
Short Version: I'm getting this error:
undefined method `map' for nil:NilClass
and the error highlights this code as the problem code:
def sizes
read_attribute(:sizes).map { |s| Size.new(s) }
end
Why and how do I stop that from happening?
Longer Version: (I based using the json column on this post)
The thing I'm not sure I'm accounting for in my attempt is that in this article they're describing how to do all of this using Postgres and I'm using MySQL.
I'm trying to take data from a form and split two of the pieces into a JSON format on one column. Here is the relevant portion of my schema:
create_table "products", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
t.string "name"
t.text "description", limit: 65535
t.integer "category_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.json "sizes"
t.index ["category_id"], name: "index_products_on_category_id", using: :btree
end
The JSON column will have amount(read sizes) and a cost associated to it. This is all about pizza and the many different sizes and associated prices based on size. Entering the data should look like this, I'm ignoring the category_id for now.
Product.create(name: "Neapolitan", sizes: { "small":9.95, "medium":10.95, "large":11.95, "xlarge":13.50, "xxlarge":29.95})
The above code works just I expect it to when I use rails console. The problem has something to do with my model and view/form. Basically, I keep asking myself, "why is 'nil' a problem here, nothing is set yet, that's the point of a form? Everything should be 'nil' "
Here is my Product.rb
class Product < ApplicationRecord
belongs_to :category
VARIANTS = ['small', 'medium', 'large', 'xlarge', 'xxlarge'].freeze
def sizes
read_attribute(:sizes).map { |s| Size.new(s) }
end
def sizes_attributes=(attributes)
sizes = []
attributes.each do |index, attrs|
next if '1' == attrs.delete("_destroy")
sizes << attrs
end
write_attributes(:sizes, sizes)
end
def build_size
s = self.sizes.dup
s << Size.new({amount: '', cost: 0})
self.sizes = s
end
class Size
attr_accessor :amount, :cost
def initialize(hash)
#amount =hash[:amount]
#cost =hash[:cost]
end
def persisted?() false; end
def new_record?() false; end
def mark_for_destruction?() false; end
def _destroy() false; end
end
end
amount acts as the key and the cost acts as the value. VARIANTS is where I'll pull my selection of locked in sizes.
Here are my forms:
_form.rb
<%= simple_form_for(#product) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :name %>
<%= f.input :description %>
<%= f.input :category_id %>
<div class="form-group">
<%# f.collection_select :sizes, Product::VARIANTS, :to_s, :to_s %>
</div>
<div class="form-group">
<%= f.label :sizes %>
<%= f.fields_for :sizes do |size_form| %>
<%= render "size_fields", f: size_form %>
<% end %>
</div>
<div class="form-actions">
<%= f.submit class: "btn btn-success" %>
</div>
</div>
<% end %>
_size_fields.rb
<fieldset>
<%= f.label :amount %>
<%= f.collection_select :amount, Product::VARIANTS, :to_s, :to_s %>
<%= f.label :cost %>
<%= f.text_field :cost %>
<%= f.hidden_field :_destroy %>
<%= link_to "remove", "#", class: "remove_fields" %>
</fieldset>
products_controller.rb
# GET /products/new
def new
#product = Product.new
#categories = Category.all
#product.build_size
end
...
# POST /products
# POST /products.json
def create
#product = Product.new(product_params)
#categories = Category.all
respond_to do |format|
if #product.save
format.html { redirect_to #product, notice: 'Product was successfully created.' }
format.json { render :show, status: :created, location: #product }
else
format.html { render :new }
format.json { render json: #product.errors, status: :unprocessable_entity }
end
end
end
...
def product_params
params.require(:product).permit(:name, :description, :category_id, sizes_attributes: [:amount, :cost, :_destroy] )
end
What am I getting wrong? How do I fix it?
I did make a attribute called address before . But I didn't use it in the sign up form . When I input all text field in sign up form , it flashes the error
The form contains 1 error.
Address can't be blank
Any other places I should check with ?
Controller
def new
#tutor = Tutor.new
end
def create
#tutor = Tutor.new(tutor_params)
if #tutor.save
log_in #tutor
flash[:success] = "Congratulations! Your registration is successful!"
redirect_to #tutor
else
render 'tutors/new'
end
end
# Handle sign-up failure, to redirect the tutor to the registeration form again
def tutor_params
params.require(:tutor).permit(:name, :email, :password, :password_confirmation,:gender
,:education_level,:institution,:exprience,:district,:subject,:student_level)
end
Sign Up page
<%= form_for(#tutor) do |f| %>
<%= render 'shared/error_messages' %>
<%= f.label :name %>
<%= f.text_field :name, class: 'form-control' %>
<%= f.label :email %>
<%= f.text_field :email, class: 'form-control' %>
<%= f.label :password %>
<%= f.password_field :password, class: 'form-control' %>
<%= f.label :password_confirmation, "Confirm Password" %>
<%= f.password_field :password_confirmation, class: 'form-control' %>
<%= f.label :gender %>
<%= f.select(:gender, ['Male', 'Female'] , class: 'form-control' )%>
<%= f.label :tutor_education_level %>
<%= f.select(:education_level, ['Bachelor', 'Master', 'Doctor'] , class: 'form-control' )%>
<%= f.label :tutor_institution %>
<%= f.text_field :institution, class: 'form-control' %>
<%= f.label :tutorial_experience %>
<%= f.text_field :experience, class: 'form-control' %>
<%= f.label :tutor_preferred_district %>
<%= f.text_field :district, class: 'form-control' %>
<%= f.label :tutor_preferred_subject %>
<%= f.text_field :subject, class: 'form-control' %>
<%= f.label :tutor_required_student_level %>
<%= f.select(:student_level, ['P1-P3', 'P4-P6', 'S1-S3', 'S4-S6'] , class: 'form-control' )%>
<%= f.submit "Create tutor's account", class: "btn btn-primary" %>
<% end %>
_error_messages.html.erb
<% if #tutor.errors.any? %>
<div id="error_explanation">
<div class="alert alert-danger">
The form contains <%= pluralize(#tutor.errors.count, "error") %>.
</div>
<ul>
<% #tutor.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
db/schema.rb(uupdate)
create_table "tutors", force: :cascade do |t|
t.string "name"
t.string "email"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "password_digest"
t.string "address"
t.string "remember_token"
t.string "gender"
t.string "education_level"
t.string "institution"
t.integer "experience"
t.string "district"
t.string "subject"
t.string "student_level"
end
add_index "tutors", ["email"], name: "index_tutors_on_email", unique: true
add_index "tutors", ["remember_token"], name: "index_tutors_on_remember_token"
end
tutor.rb (update2)
`class Tutor < ActiveRecord::Base
before_save {self.email = email.downcase}
before_save :create_remember_token
validates :name, 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 :password, presence: true, length: { minimum: 6 }
validates :password_confirmation, presence: true
has_secure_password
validates :address, presence: true, length: {maximum: 100}
def create_remember_token
self.remember_token = SecureRandom.urlsafe_base64
end
end
`
Change
validates :address, presence: true, length: {maximum: 100}
to
validates :address, length: {maximum: 100}
in your model tutor.rb
You are validating for the presence of address field in your model while creating a tutor, but you are not passing address params.
If you want to delete existing address field from db,
In your terminal, do
rails g migration remove_address_from_tutors
Add the following code in your newly created migration file
class RemoveAddressFromTutors < ActiveRecord::Migration
def change
remove_column :tutors, :address
end
end
and then do rake db:migrate in your terminal
def create
#tutor = Tutor.new(tutor_params)
if #tutor.save
log_in #tutor
flash[:success] = "Congratulations! Your registration is successful!"
redirect_to #tutor
else
flash[:tutor] = #tutor
redirect_to new_tutor_path
end
end
Also make sure your validates_presence_of :address in your tutor model.
I have a Post model and Tag model with many to many relationships.
Post Model:
class Post < ActiveRecord::Base
has_and_belongs_to_many :tags
end
Tag model:
class Tag < ActiveRecord::Base
has_and_belongs_to_many :posts
end
I also have a join table for posts_tags :
class JoinPostsAndTags < ActiveRecord::Migration
def change
create_table :posts_tags do |t|
t.integer :tag_id
t.integer :post_id
t.timestamps null: false
end
end
end
Now, I need to provide multiple selection for selecting tags for a post.
Below is the post form.html.erb
<%= form_for #post do |f| %>
<% if #post.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#post.errors.count, "error") %> prohibited this post from being saved:</h2>
<ul>
<% #post.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :Name %><br>
<%= f.text_field :Name %>
</div>
<div class="field">
<%= f.label :Email %><br>
<%= f.text_field :Email %>
</div>
<div class="field">
<%= f.label :Message %><br>
<%= f.text_area :Message %>
</div>
<% #tags= Tag.all %>
<% if #tags %>
<% #tags.each do |tag| %>
<div>
<%= check_box_tag "post[tag_ids][]", tag.id, #post.tags.include?(tag) %>
<%= tag.name %>
</div>
<% end %>
<% end %>
<br><br>
<%= link_to 'Create Tag', tags_path %>
<br><br>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
It is not adding the selected tags to the post. I need to add the selected tags to the post. How can I do it.
But, in rails console if I use post= Post.first tag= Tag.first post.tags<<tag it adds the tag to the post.
I don't have any special code in post controller to handle this. Please help me.
Add {tag_ids:[]} to your params permit arguments in your PostsController, like so:
def post_params
params.require(:post).permit(:name, :email, :message, {tag_ids:[]})
end
I have a strange problem with my web app.
I am trying to build a simple reservation system for a game like "Escape the room". For now I made my own calendar looking a railscast (Calendars revised) for having the dates.
For the possible hours I made a new model and a new table in the database
t.integer "id"
t.datetime "start_time"
t.datetime "end_time"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
In the view I have something like this:
<%= calendar #date do |date| %>
<%= date.day %>
<table class="table">
<tbody>
<% #hours.each_slice(2) do |hour| %>
<tr>
<% hour.each do |h| %>
<td>
<%= link_to h.start_time.strftime('%H:%M'), new_escape_path(date: date, start_time: h.start_time.strftime('%H:%M'), end_time: h.end_time.strftime('%H:%M')) %>
</td>
<% end %>
</tr>
<% end %>
</tbody>
</table>
<% end %>
And I write these parameters into the database passing them in a form where user can complete other fields manually:
<%= text_field_tag :date, params[:date] %><br>
<%= text_field_tag :start_time, params[:start_time] %> do
<%= text_field_tag :end_time, params[:end_time] %>
The problem is that in the view I want to show only the hours which are not reserved yet, which means that they are not in the escapes table.
When in the console I write
Escape.all
I have something like:
#<Escape id: 1, date: "2015-08-11 00:00:00", start_time: "2015-08-10 08:30:00", end_time: nil, user_id: nil, created_at: "2015-08-10 15:26:14", updated_at: "2015-08-10 15:26:14">
but when I write
Escape.all.where(date: "2015-08-11 00:00:00")
it returns an empty record
#<ActiveRecord::Relation []>
I tried also to insert something like this in the view, but it's not working:
<% if Escape.where(["date = ? and start_time = ?", "#{date}", "#{h}"])%>
<%= h.start_time.strftime('%H:%M') %>
<% else %>
<%= link_to h.start_time.strftime('%H:%M'), new_escape_path(date: date, start_time: h.start_time.strftime('%H:%M'), end_time: h.end_time.strftime('%H:%M')) %>
<% end %>
Do you have any ideas? What am I doing wrong?