Ruby on Rails 4, Dynamically create table for each user - ruby-on-rails

I'm new to Rails and I'm creating an Application where users can log in, and it dynamically generates a Table where they can make entries. I've managed to make the login but I don't realize how to create a table which is associated to a user.
My users_controller.rb class:
class UsersController < ApplicationController
before_action :set_user, only: [:show, :edit, :update, :destroy]
# GET /users
# GET /users.json
def index
#users = User.order(:name)
end
# GET /users/1
# GET /users/1.json
def show
end
# GET /users/new
def new
#user = User.new
end
# GET /users/1/edit
def edit
end
# POST /users
# POST /users.json
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
format.html { redirect_to login_url, notice: "User #{#user.name} was successfully created." }
format.json { render action: 'show', status: :created, location: #user }
#HERE I WOULD LIKE TO CREATE A TABLE ASSOSSIATED TO THE USER
#rapport_table = User.rapport_table.create
else
format.html { render action: 'new' }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /users/1
# PATCH/PUT /users/1.json
def update
respond_to do |format|
if #user.update(user_params)
format.html { redirect_to users_url, notice: "User #{#user.name} was successfully updated." }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# DELETE /users/1
# DELETE /users/1.json
def destroy
#user.destroy
respond_to do |format|
format.html { redirect_to users_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_user
#user = User.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def user_params
params.require(:user).permit(:name, :password, :password_confirmation)
end
end
rapport_table.rb
class RapportTable < ActiveRecord::Base
belongs_to :user
end
12341324123_create_rapport_tables.rb
class CreateRapportTables < ActiveRecord::Migration
def self.up
create_table :rapport_tables do |t|
t.date :date
t.text :description
t.integer :time
t.timestamps
end
end
def self.down
drop_table :rapport_tables
end
end
show.html.erb
<p id="notice"><%= notice %></p>
<p>
<strong>Name:</strong>
<%= #user.name %>
</p>
<%= link_to 'Edit', edit_user_path(#user) %> |
<%= link_to 'Back', users_path %>

You never, ever want to create tables inside a database in a runtime. Instead, you'll need to create some more models:
class RaportTable < ActiveRecord::Base
belongs_to :user
has_many :columns
has_many :rows
end
class Column < ActiveRecord::Base
# attr_accessible :name, :order
belongs_to :raport_table
has_many :cells
end
class Row < ActiveRecord::Base
# attr_accessible :row_number
belongs_to :raport_table
has_many :cells
end
class Cell < ActiveRecord::Base
# attr_accessible :value
belongs_to :column
belongs_to :row
end
This should be sufficient to start with.

Related

Creating items with scaffolding not showing attributes after creation - Rails/Devise

I'm relatively new to Rails. I'm trying to create an application that can allow users to create video game items and store them under their own users. I'm using the latest version of Rails and Devise.
Using scaffolding as a base, I created the Videogame model/controller within my application. After linking the video game models to the user who created them, it seems that any attributes that are entered into the creation form are not saving, or at the very least just not showing up on the videogames/index page. After trying to search around on Google and StackOverflow, I couldn't find any similar questions/guides to work with.
Any ideas on how to fix this? Any help for a Rails newbie would be greatly appreciated.
Below I've posted all files that may be relevant. Please let me know if anything else is needed. To see the whole project, see http://github.com/bmmart2/collection-manager
Image after item creation
Index page of two created items
Here is my controller:
class VideogamesController < ApplicationController
before_action :set_videogame, only: [:show, :edit, :update, :destroy]
# GET /videogames
# GET /videogames.json
def index
if user_signed_in?
#videogame = current_user.videogames.all
else
redirect_to :root
end
end
# GET /videogames/1
# GET /videogames/1.json
def show
end
# GET /videogames/new
def new
#videogame = current_user.videogames.new
end
# GET /videogames/1/edit
def edit
end
# POST /videogames
# POST /videogames.json
def create
#videogame = current_user.videogames.create(videogame_params)
respond_to do |format|
if #videogame.save
format.html { redirect_to #videogame, notice: 'Videogame was successfully created.' }
format.json { render :show, status: :created, location: #videogame }
else
format.html { render :new }
format.json { render json: #videogame.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /videogames/1
# PATCH/PUT /videogames/1.json
def update
respond_to do |format|
if #videogame.update(videogame_params)
format.html { redirect_to #videogame, notice: 'Videogame was successfully updated.' }
format.json { render :show, status: :ok, location: #videogame }
else
format.html { render :edit }
format.json { render json: #videogame.errors, status: :unprocessable_entity }
end
end
end
# DELETE /videogames/1
# DELETE /videogames/1.json
def destroy
#videogame.destroy
respond_to do |format|
format.html { redirect_to videogames_url, notice: 'Videogame was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_videogame
#videogame = Videogame.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def videogame_params
params.require(:videogame).permit(:title, :publisher, :platform, :year, :condition, :upc)
end
end
Videogame model:
class Videogame < ApplicationRecord
belongs_to :user
attr_accessor :title, :platform, :upc, :condition, :publisher, :year
end
Videogame db migration file:
class CreateVideogames < ActiveRecord::Migration[5.2]
def change
create_table :videogames do |t|
t.string :title
t.string :publisher
t.integer :condition
t.string :platform
t.string :year
t.string :upc
t.timestamps
end
add_index :videogames, :user_id
end
end
add_user_refs_to_videogame migration:
class AddUserRefsToVideogame < ActiveRecord::Migration[5.2]
def change
add_reference :videogames, :user, foreign_key: true
end
end
Edit: show view for video game
<p id="notice"><%= notice %></p>
<p>
<strong>Title:</strong>
<%= #videogame.title %>
</p>
<p>
<strong>Publisher:</strong>
<%= #videogame.publisher %>
</p>
<p>
<strong>Platform:</strong>
<%= #videogame.platform %>
</p>
<p>
<strong>Year:</strong>
<%= #videogame.year %>
</p>
<p>
<strong>Condition:</strong>
<%= #videogame.condition %>
</p>
<p>
<strong>Upc:</strong>
<%= #videogame.upc %>
</p>
<%= link_to 'Edit', edit_videogame_path(#videogame) %> |
<%= link_to 'Back', videogames_path %>
I believe the attr_accessor line in your videogame.rb file is causing the problem. Try deleting it and see if that fixes the problem.

Problems with adding images to user

When I push submit button in _form, Image should be created and linked to the user, but something went wrong. I use the same Image model for Ads and there almost the same code works right. Maybe the problem can somehow be connected with the inconsistency of devise user controllers and my user controller?
Users controller
class UsersController < ApplicationController
before_action :set_user, only: [:show, :edit, :update, :destroy]
def index
end
def show
end
def new
#user = User.new
#user.images.build
end
def edit
authorize! :update, #user
#user.images.build
end
def create
#user = current_user
respond_to do |format|
if #user.save
format.html { redirect_to board_url }
format.json { render :show, status: :created, location: #user }
else
format.html { render :new }
format.json { render json: #user.errors, status: :unprocessable_entity}
end
end
end
def update
respond_to do |format|
if #user.update(user_params)
format.html { redirect_to board_url }
format.json { render :show, status: :ok, location: #user }
else
format.html { render :edit }
format.json { render json: #user.errors, status: :unprocessable_entity}
end
end
end
def destroy
authorize! :update, #user
#user.destroy
respond_to do |format|
format.html { redirect_to board_url }
format.json { head :no_content }
end
end
private
def set_user
#user = User.find(params[:id])
end
def user_params
params.require(:user).permit(:email, images_attributes: [:id, :name])
end
end
_form
<%= form_with(model: user, local: true) do |form| %>
<%= form.fields_for :images do |image| %>
<div class="image_fields">
<div class="field">
<%= image.label t('.img_name') %><br>
<%= image.text_field :name %>
</div>
</div>
<% end %>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
class Image
class Image < ApplicationRecord
belongs_to :ad
belongs_to :user
validates :name, presence: true
...
class User
class User < ApplicationRecord
has_many :ads
has_many :images, dependent: :destroy
accepts_nested_attributes_for :images,
reject_if: proc { |attributes| attributes['name'].blank? },
allow_destroy: true
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
Migrations
class AddUserIdToImages < ActiveRecord::Migration[5.1]
def change
add_column :images, :user_id, :integer
end
end
class CreateImages < ActiveRecord::Migration[5.1]
def change
create_table :images do |t|
t.string :name
t.references :ad, foreign_key: true
t.timestamps
end
end
end
Please provide error message and backtrace.
I assume it is because "ad" reference is blank for the user.
And according to your code:
t.references :ad, foreign_key: true
So I think the issue is in database constraint
And the simplest solution is to change it to
add_column :images, :ad_id, :integer
Without foreign key.
Or for your case, you can add polimorhic association
Also, a question not related to the topic, but want to ask about
respond_to do |format|
if #user.save
format.html { redirect_to board_url }
format.json { render :show, status: :created, location: #user }
else
format.html { render :new }
format.json { render json: #user.errors, status: :unprocessable_entity}
end
end
Why are you saving inside respond_to method?
So in rails depth, there is a method:
def respond_to(&block)
...
block.call
...
end
And your #user.save will be called there. Are you sure you want it?

Unpermitted parameter using fields_for Rails

I got such message in console when trying to use fields_for in Rails:
Parameters: .... "task"=>{"task_name"=>"111", "tag"=>{"tag_text"=>"222"}}, "commit"=>"Save"}
Unpermitted parameter: tag
My models with has_many and belongs_to:
class Task < ActiveRecord::Base
has_many :tags
accepts_nested_attributes_for :tags
end
class Tag < ActiveRecord::Base
belongs_to :task
end
Form helper for new/edit page:
<%= form_for(#task) do |f| %>
<%= f.text_field :task_name %>
<%= f.fields_for([#task, #task.tags.build]) do |t| %>
<%= t.text_field :tag_text %>
<% end %>
<%= f.submit 'Save' %>
<% end %>
My Task Controller (I used scaffold to generate it, and its mostly default)
class TasksController < ApplicationController
before_action :set_task, only: [:show, :edit, :update, :destroy]
def index
#tasks = Task.all
end
def show
end
def new
#task = Task.new
#task.tags.build
end
def edit
#task.tags.build
end
def create
#task = Task.new(task_params)
respond_to do |format|
if #task.save
format.html { redirect_to #task, notice: 'Task was successfully created.' }
format.json { render :edit, status: :created, location: #task }
else
format.html { render :new }
format.json { render json: #task.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #task.update(task_params)
format.html { redirect_to edit_task_path, notice: 'Task was successfully updated.' }
format.json { render :edit, status: :ok, location: #task }
else
format.html { render :edit }
format.json { render json: #task.errors, status: :unprocessable_entity }
end
end
end
def destroy
#task.destroy
respond_to do |format|
format.html { redirect_to tasks_url, notice: 'Task was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_task
#task = Task.find(params[:id])
end
def task_params
params.require(:task).permit(:task_name, :task_sum, :status_id, :user_id, :target_release_id, tag_attributes: [:tag_text, :task_id])
end
end
I think the problem is in the way you use fields_for. Try to make this way:
<%= f.fields_for :tags do |t| %>
That way the param tags_attributes will be send and every thing should be fine.
EDIT
Also, if you are using Rails 5, you need to set the belongs_to as optional so the accepts_nested_attributes_for can work properly. So:
class Tag < ActiveRecord::Base
belongs_to :task, optional: true
end
And the parameters sanitization in your tasks_controller.rb you do not need tag_id under tags_attributes:
def task_params:
params.require(:task).permit(:task_name, tags_attributes: [:tag_text])
end
EDIT
I think I found your problem. Try to put tags_attributes instead of tag_attributes in your task_paramsmethod.

Can't associate product and category correctly

everybody. I'm trying to associate every product with his category. But there are some errors.
So, at first.
Here is my product and category migrations:
class CreateProducts < ActiveRecord::Migration
def change
create_table :products do |t|
t.belongs_to :categoty, index: true
t.string :title
t.string :category
t.text :description
t.string :image_url
t.decimal :price, precision: 8, scale: 2
t.timestamps
end
end
end
class CreateCategories < ActiveRecord::Migration
def change
create_table :categories do |t|
t.references :product
t.string :name
t.timestamps null: false
end
end
end
Both of them have associations in models (belongs_to for product and has_many for category).
And I have made the form to link products with this category:
<div class="field">
<%= f.collection_select :category, Category.all, :id, :name %>
</div>
And when I'm trying to save the product there is the error:
Category(#XXXX) expected, got String(#XXXX).
So, what am I doing wrong?
Also, here is my controller.
class ProductsController < ApplicationController
before_action :set_product, only: [:show, :edit, :update, :destroy]
# GET /products
# GET /products.json
def index
#products = Product.all
end
# GET /products/1
# GET /products/1.json
def show
end
# GET /products/new
def new
#product = Product.new
end
# GET /products/1/edit
def edit
end
# POST /products
# POST /products.json
def create
#product = Product.new(product_params)
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
# PATCH/PUT /products/1
# PATCH/PUT /products/1.json
def update
respond_to do |format|
if #product.update(product_params)
format.html { redirect_to #product, notice: 'Product was successfully updated.' }
format.json { render :show, status: :ok, location: #product }
else
format.html { render :edit }
format.json { render json: #product.errors, status: :unprocessable_entity }
end
end
end
# DELETE /products/1
# DELETE /products/1.json
def destroy
#product.destroy
respond_to do |format|
format.html { redirect_to products_url, notice: 'Product was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_product
#product = Product.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def product_params
params.require(:product).permit(:title, :category, :description, :image_url, :price)
end
end
In your database migration file you have the field categoty and you are using category_id in controller. Just need to change the field to category in database to make sure it is associated to the correct model.

collection_select with multiple models rails 4

I have Products and Books. I'm trying to connect Books to a Product with collection_select
Here's part of my product form:
<%= f.label :book_id %><br>
<%= f.collection_select(:book_id, Book.all, :id, :title, {}, multiple: :true) %>
Book Model:
class Book < ActiveRecord::Base
belongs_to :product
end
Product Model:
class Product < ActiveRecord::Base
has_many :books
end
Migrations:
class AddBookToProducts < ActiveRecord::Migration
def change
add_column :products, :book_id, :integer
add_index :products, :book_id
end
end
class AddProductToBooks < ActiveRecord::Migration
def change
add_column :books, :product_id, :string
add_index :books, :product_id
end
end
BooksController:
def new
#book = Book.new
authorize #book
end
def create
#book = Book.new(book_params)
#book.user = current_user
...
ProductsController:
class ProductsController < ApplicationController
require "stripe"
before_action :set_product, only: [:show, :edit, :update, :destroy]
# GET /products
# GET /products.json
def index
#products = Product.all.page params[:page]
authorize #products
end
# GET /products/1
# GET /products/1.json
def show
#stripe_btn_data = {
key: "#{ Rails.configuration.stripe[:publishable_key] }",
description: #product.title,
amount: (#product.price * 100),
}
authorize #product
end
# GET /products/new
def new
#product = Product.new
#books = Book.all
authorize #product
end
# GET /products/1/edit
def edit
authorize #product
end
# POST /products
# POST /products.json
def create
#product = Product.new(product_params)
authorize #product
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
# PATCH/PUT /products/1
# PATCH/PUT /products/1.json
def update
authorize #product
respond_to do |format|
if #product.update(product_params)
format.html { redirect_to #product, notice: 'Product was successfully updated.' }
format.json { render :show, status: :ok, location: #product }
else
format.html { render :edit }
format.json { render json: #product.errors, status: :unprocessable_entity }
end
end
end
# DELETE /products/1
# DELETE /products/1.json
def destroy
#product.destroy
authorize #product
respond_to do |format|
format.html { redirect_to products_url, notice: 'Product was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_product
#product = Product.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def product_params
params.require(:product).permit(:title, :body, :price, :active, :state, :hardcopy_book, :online_only, :online_hardcopy, :expiration, :monthly, :annual, :user_id, :book, :book_id, :id)
end
end
Parameters show the :book_id but it does not insert the book_id into products.
Here's how I am showing the selected books on the product/show
<strong>Book:</strong>
<ul>
<% #product.books.each do |book| %>
<li><%= link_to book.tile, (book) %><li>
<% end %>
</ul>
What am I missing?
Firstly, your migration is wrong, we only need one migration and here it is:
class AddBookToProducts < ActiveRecord::Migration
def change
add_column :books, :product_id, :string
add_index :books, :product_id
end
end
Because Book belongs to Product and Product has many Book so add one column product_id to Books table is enough.
Secondly, edit your Product form to: (please note the change from book_id to book_ids)
<%= f.label :book_id %><br>
<%= f.collection_select(:book_ids, Book.all, :id, :title, {}, multiple: :true) %>
Then add book_ids to Strong parameter in ProductsController
def product_params
params.require(:product).permit(:title, :body, :price, :active, :state, :hardcopy_book, :online_only, :online_hardcopy, :expiration, :monthly, :annual, :user_id, :book, :id, :book_ids => [])
end

Resources