RAILS - User has more than one category - ruby-on-rails

I have a rails app that I'm trying to make an association with USERS (there are many) and Categories (there are 3, which I seeded). Each category has a name and an ID...
When I try to get users to edit their category, the form comes up blank.
The code I'm using for users to select their category is as follows :
<%= form_for (#user) do |f| %>
<%= f.select :categories, #user.categories.all, {multiple: true} %>
(i have also tried Category.all.collect)
Here is what my SCHEMA looks like
create_table "categories", force: :cascade do |t|
t.string "catname"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id"
t.index ["user_id"], name: "index_categories_on_user_id"
end
create_table "specialties", force: :cascade do |t|
t.string "specname"
t.text "description"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "category_id"
end
create_table "users", force: :cascade do |t|
t.string "name"
t.string "email"
t.integer "category_id"
and here are my Models,
class User < ApplicationRecord
has_many :categories
class Category < ApplicationRecord
validates :catname, presence: true
has_many :specialties
belongs_to :user

You can try something like that.
<%= hidden_field_tag "user[category_ids][]", nil %>
<% Category.all.each do |category| %>
<%= check_box_tag "user[category_ids][]", category.id, #user.category_ids.include?(category.id), id: dom_id(category) %>
<%= label_tag dom_id(category), category.catname %> <br>
<% end %>
or
create a field categories in user, then:
<%= form.select :categories, Category.all.collect {|x| [x.name, x.id]}, {}, :multiple => true%>

Related

Rails- Checkbox not turning true

I've added a checkbox to my Rails project. When the user marks tradeablestatus while creating a book, it should write true, but it is happening false regardless.
books/_form.html.erb
<%= form_with(model: book, local: true) do |form| %>
<% if book.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(book.errors.count, "error") %> prohibited this book from being saved:</h2>
<ul>
<% book.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<p> If you want your book to be available, tick the status and if you want your book to be tradeable, tick the tradeablestatus. </p>
<div class="field">
<%= form.label :title %>
<%= form.text_field :title %>
</div>
<div class="field">
<%= form.label :author %>
<%= form.text_field :author %>
</div>
<div class="field">
<%= form.label :pagecount %>
<%= form.number_field :pagecount %>
</div>
<div class="field">
<%= form.label :status %>
<%= form.check_box :status %>
</div>
<div class="field">
<%= form.label :tradeablestatus %>
<%= form.check_box :tradeablestatus %>
</div>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
tradeablestatus migration (I added the tradeablestatus later as a migration. But I don't know if I should add this to book migration)
class AddTradeableStatusToBooks < ActiveRecord::Migration[6.0]
def change
add_column :books, :tradeablestatus, :boolean
end
end
schema.rb (I suspect it is caused by default: false, null: false)
ActiveRecord::Schema.define(version: 2020_10_28_092816) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "books", force: :cascade do |t|
t.string "title"
t.string "author"
t.integer "pagecount"
t.boolean "status"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.integer "user_id"
t.string "username"
t.boolean "tradeablestatus", default: false, null: false
end
create_table "comments", force: :cascade do |t|
t.string "title"
t.string "content"
t.bigint "user_id", null: false
t.bigint "book_id", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.boolean "status", default: false, null: false
t.index ["book_id"], name: "index_comments_on_book_id"
t.index ["user_id"], name: "index_comments_on_user_id"
end
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.string "username"
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
add_foreign_key "comments", "books"
add_foreign_key "comments", "users"
end
Hello) 👋 If u want to receive "true" or "false" on your back-end side u should check this first https://apidock.com/rails/ActionView/Helpers/FormHelper/check_box.
There are smth like check_box("puppy", "gooddog", {}, "yes", "no").
Yes and no means that if checkbox are checked then yes value goes to back-end side otherwise no goes to back-end side. U should replace this values with yours)
If problem will not go then post your controller code please)

How to show the name of category instead of its ID?

I am trying to have the category name show up in the Post's show.html.erb.
This is the current code for it:
<p>
<strong>Title:</strong>
<%= #post.title %>
</p>
<p>
<strong>Text:</strong>
<%= #post.text %>
</p>
<p>
<strong>Category:</strong>
<%= #post.category_id %>
</p>
<h2>Comments</h2>
<%= render #post.comments %>
<h2>Add a comment</h2>
<%= render 'comments/form' %>
<%= link_to 'Back', posts_path %>
How do I deal with this part: <%= #post.category_id %> so it can show the name of the category instead?
The current schema is:
create_table "categories", force: :cascade do |t|
t.string "name"
t.text "description"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "comments", force: :cascade do |t|
t.string "name"
t.text "body"
t.integer "post_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["post_id"], name: "index_comments_on_post_id", using: :btree
end
create_table "posts", force: :cascade do |t|
t.string "title"
t.text "text"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "category_id"
t.index ["category_id"], name: "index_posts_on_category_id", using: :btree
end
add_foreign_key "comments", "posts"
add_foreign_key "posts", "categories"
end
Current models are:
Post:
class Post < ApplicationRecord
has_many :comments
belongs_to :category
validates :title, presence: true
validates :text, presence: true
end
Categories:
class Category < ApplicationRecord
has_many :posts
end
Comment:
class Comment < ApplicationRecord
belongs_to :post
end
You should access #post's category's name:
#post.category.name
Because you are using association belongs_to in Post model, you can get the category name in your view this way:
<%= #post.category.name %>

Rails - Form HABTM

I am new to Rails but I am stuck. I would like to create a form that will add data to two tables (books and books_authors). My view looks like:
<%= form_for :book, url: book_path do |f| %>
<p>
<%= f.label :title %> :<br/>
<%= f.text_field :title %><br/>
<ul>
<% #authors.each do |x| %>
<li> <%= f.check_box {...} %> <%= x.name + " " + x.surname%></li>
<% end %>
</ul>
</p>
<p><%= f.submit %></p>
and my create method in controller books_controller.rb looks like:
def create
#book = Book.new(params.require(:book).permit(:title))
#book.save
params[:authors].each do |author_id|
book.authors << Author.find(author_id)
end
redirect_to root_path
end
and my schema:
ActiveRecord::Schema.define(version: 20150709110928) do
create_table "author_books", id: false, force: :cascade do |t|
t.integer "author_id"
t.integer "book_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "author_books", ["author_id"], name:
"index_author_books_on_author_id"
add_index "author_books", ["book_id"],
name:"index_author_books_on_book_id"
create_table "authors", force: :cascade do |t|
t.string "name"
t.string "surname"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "books", force: :cascade do |t|
t.string "title"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
end
I need params for :authors but I dont know how to nest it inside the form
I n your _form
<% #authors.each do |author| %>
<%= check_box_tag "author_ids[]", author.id %>
<%= author.name %> // I assume that your author has a name which can be used as a label
<% end %>
in your controller,
def create
// you will get the authors in params[:author_ids]
#book = Book.new(params.require(:book).permit(:title, :author_ids => [])) // its a dirty code
// skip other codes
end
fresh code for controller
define a private method and put
def book_params
params.require(:book).permit(:title, :author_ids => [])
end
and in
def create
#book = Book.new(book_params)
end

How to add multiple images in rails site

I am trying to add several images to my site and am not quite sure how the routing works.
Here is my index.html.erb page
<%= render 'pages/home' unless user_signed_in? %>
<div id="properties" class="transitions-enabled">
<% #properties.each do |property| %>
<div class="box panel panel-default">
<%= link_to image_tag(property.image.url(:medium)), property_path(property) %>
<div class="panel-body">
<%= property.description %><br>
<strong><%= property.user.name if property.user %></strong>
<!-- <% if property.user == current_user %>
<div class="actions">
<%= link_to 'Edit', edit_property_path(property) %>
<%= link_to 'Destroy', property, method: :delete, data: { confirm: 'Are you sure?' } %>
</div> -->
<% end %>
</div>
</div>
<% end %>
</div>
And I think it's after this line <%= link_to image_tag(property.image.url(:medium)), property_path(property) %> that I want to add another image.
Here is my _formfield.html.erb file where I ask for two images
<div class="form-group">
<%= f.label :image %><br>
<%= f.file_field :image, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :street_image %><br>
<%= f.file_field :street_image, class: "form-control" %>
</div>
How do I show the :streetimage properly?
And this is my property model:
class Property < ActiveRecord::Base
belongs_to :user
has_attached_file :image, :styles => { :medium => "300x300", :thumb => "100x100"}
validates_attachment_content_type :image, :content_type => ["image/jpg", "image/jpeg", "image/png"]
validates :image, presence: true
validates :description, presence: true
end
And here's my schema
ActiveRecord::Schema.define(version: 20150429054455) do
create_table "properties", force: :cascade do |t|
t.string "description"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id"
t.string "image_file_name"
t.string "image_content_type"
t.integer "image_file_size"
t.datetime "image_updated_at"
t.string "name"
t.string "street"
t.integer "zip"
t.string "state"
t.string "company"
t.string "city"
t.integer "price"
t.integer "space"
t.string "street_image_file_name"
t.string "street_image_content_type"
t.integer "street_image_file_size"
t.datetime "street_image_updated_at"
end
add_index "properties", ["user_id"], name: "index_properties_on_user_id"
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
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"
t.datetime "updated_at"
t.string "name"
end
add_index "users", ["email"], name: "index_users_on_email", unique: true
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
It's working now. Looks like I had the wrong variable set and didn't run rake db:migrate before

How to refer to a symbols' active record relationship inside a fields_for

Inside a fields_for block how can i reference the value of a relationship field.
For instance:
app/models/cart.rb
class Cart < ActiveRecord::Base
attr_accessible :lineitems_attributes
has_many :lineitems, dependent: :destroy
accepts_nested_attributes_for :lineitems
def total_price
lineitems.to_a.sum { |item| item.total_price }
end
end
app/models/lineitem.rb
class Lineitem < ActiveRecord::Base
attr_accessible :cart_id, :quantity, :package_id, :part_id
belongs_to :cart
belongs_to :package
belongs_to :part
def total_price
if package_id?
return package.price * quantity
end
if part_id?
return part.price * quantity
end
end
end
app/models/package.rb
class Package < ActiveRecord::Base
attr_accessible :description, :img_src, :name, :price
has_many :lineitems
end
app/views/cart/_form.html.erb
<%= form_for #cart do |f| %>
<%= c.fields_for :lineitems do |i| %>
<%= render 'lineitem_fields', :f => i %>
<% end %>
<%= c.submit %>
<% end %>
app/views/cart/_lineitem_fields.html.erb
<%= f.text_field :quantity %>
<% if :package_id? %>
<%= f.text_field :package_id %>
<% else %>
<%= f.text_field :part_id %>
<% end %>
<%= link_to 'Remove',
lineitem_path(:id),
:method => :delete,
:confirm => t('.confirm', :default => t("helpers.links.confirm",
:default => 'Are you sure?')) %>
relative pieces of schema
create_table "carts", :force => true do |t|
t.integer "branch_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "lineitems", :force => true do |t|
t.integer "cart_id"
t.integer "part_id"
t.integer "package_id"
t.integer "quantity", :default => 1
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "parts", :force => true do |t|
t.string "description"
t.string "partNumber"
t.decimal "price"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "packages", :force => true do |t|
t.string "description"
t.string "name"
t.string "img_src"
t.decimal "price"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
The above form works but...
Question 1: How to show the package.name instead of :package_id
Question 2: How to display total_price of each lineitem in the form. It is a method how would that work?
Question 3: Is there a best practice to displaying a form in an invoice looking manner where maybe the quantity is a text field but the remainder of the columns are just text or labels?
The end game scenario is this form will be a last chance to edit the quantities of the cart (or remove lineitems) before submitting an order. Obviously in the real world you want to display the quantities, package name, description and price but I can't seem to figure out how to display those values inside the form since they are in another model by relationship and not specific to lineitems.
Thanks for the help.
You are looking for the ActionView::Helpers::ActiveModelInstanceTag#object method. This gives you access to ActiveRecord everywhere inside the form.
1
<% if f.object.package_id? %>
<%= text_field_tag :package_name, f.object.package.name %>
<%= f.hidden_field :package_id %>
<% else %>
2 <%= f.object.total_price %>
3 Perhaps try the :readonly => true option on all input tags except the quantity?

Resources