I want to create app for my own usage.
I want to encourage my kids to eat more vegetables and fruits by creating a game. Game should have players, snacks and date. Every time, when game is created it should randomly assign selected in game snacks to selected in game players. When player eat randomly assigned snack, they gain points assigned to each snack and when player collect x points, they can exchange it for award. Each player has many games and could have many snacks in each game and each snack could belong to many games and to many players in each game.
I'm self learning beginner at rails, so if you have idea's how to modify it all, I'll be thankful for suggestions.
After few suggestions by random people, I got implement it all as below.
So I'm stack at creating game, because I don't know how to after creating the game assign selected snacks to players because their id's are not saved and I don't know how to modify it. Probably I could change association's to be a mirror's like players associaton's but I'm not quite sure is it a good way.
Processing by GamesController#create as TURBO_STREAM
Parameters: {"authenticity_token"=>"[FILTERED]", "game"=>{"game_date(1i)"=>"2022", "game_date(2i)"=>"5", "game_date(3i)"=>"18", "player_ids"=>["1"], "snack_ids"=>["1"]}, "commit"=>"Create Game"}
Unpermitted parameter: :snack_ids. Context: { controller: GamesController, action: create, request: #<ActionDispatch::Request:0x00007fad6c1eed50>, params: {"authenticity_token"=>"[FILTERED]", "game"=>{"game_date(1i)"=>"2022", "game_date(2i)"=>"5", "game_date(3i)"=>"18", "player_ids"=>["1"], "snack_ids"=>["1"]}, "commit"=>"Create Game", "controller"=>"games", "action"=>"create"} }
Player Load (0.6ms) SELECT "players".* FROM "players" WHERE "players"."id" = ? [["id", 1]]
↳ app/controllers/games_controller.rb:27:in `create'
TRANSACTION (0.1ms) begin transaction
↳ app/controllers/games_controller.rb:30:in `block in create'
Player Exists? (0.5ms) SELECT 1 AS one FROM "players" WHERE "players"."name" = ? AND "players"."id" != ? LIMIT ? [["name", "Tata"], ["id", 1], ["LIMIT", 1]]
↳ app/controllers/games_controller.rb:30:in `block in create'
Game Create (1.4ms) INSERT INTO "games" ("game_date", "created_at", "updated_at") VALUES (?, ?, ?) [["game_date", "2022-05-18"], ["created_at", "2022-05-18 11:04:41.815456"], ["updated_at", "2022-05-18 11:04:41.815456"]]
↳ app/controllers/games_controller.rb:30:in `block in create'
PlayerGame Create (0.9ms) INSERT INTO "player_games" ("player_id", "game_id", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["player_id", 1], ["game_id", 10], ["created_at", "2022-05-18 11:04:41.820295"], ["updated_at", "2022-05-18 11:04:41.820295"]]
↳ app/controllers/games_controller.rb:30:in `block in create'
TRANSACTION (8.8ms) commit transaction
↳ app/controllers/games_controller.rb:30:in `block in create'
Redirected to http://localhost:3000/games/10
Completed 302 Found in 38ms (ActiveRecord: 13.3ms | Allocations: 9505)
Started GET "/games/10" for 127.0.0.1 at 2022-05-18 13:04:41 +0200
Processing by GamesController#show as TURBO_STREAM
Parameters: {"id"=>"10"}
Game Load (0.6ms) SELECT "games".* FROM "games" WHERE "games"."id" = ? LIMIT ? [["id", 10], ["LIMIT", 1]]
↳ app/controllers/games_controller.rb:66:in `set_game'
Rendering layout layouts/application.html.erb
Rendering games/show.html.erb within layouts/application
Rendered games/_game.html.erb (Duration: 1.3ms | Allocations: 222)
Rendered games/show.html.erb within layouts/application (Duration: 13.1ms | Allocations: 1433)
Rendered layout layouts/application.html.erb (Duration: 36.0ms | Allocations: 3738)
Completed 200 OK in 53ms (Views: 40.6ms | ActiveRecord: 0.6ms | Allocations: 5405)
Models associations looks like that :
class Game < ApplicationRecord
validates :game_date, comparison: { greater_than_or_equal_to: Date.today }
# after_create :assign_snacks_to_players
has_many :player_games
has_many :players, through: :player_games
has_many :snack_games
has_many :snacks, through: :snack_games
accepts_nested_attributes_for :snacks
end
class Player < ApplicationRecord
validates :name, length: {minimum: 3, maximum: 20}, uniqueness: true
validates :points, presence: true
validates :active, inclusion: { in: [true, false] }
has_many :player_games
has_many :games, through: :player_games
has_many :snack_games
has_many :snacks, through: :snack_games
end
class Snack < ApplicationRecord
validates :name, length: {minimum: 3, maximum: 20}, uniqueness: true
validates :points, presence: true
validates :active, inclusion: { in: [true, false] }
has_many :snack_games
has_many :games, through: :snack_games
end
class PlayerGame < ApplicationRecord
belongs_to :game
belongs_to :player
end
class SnackGame < ApplicationRecord
belongs_to :snack
belongs_to :game
belongs_to :player
end
Schema :
# This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
#
# This file is the source Rails uses to define your schema when running `bin/rails
# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
# be faster and is potentially less error prone than running all of your
# migrations from scratch. Old migrations may fail to apply correctly if those
# migrations use external dependencies or application code.
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[7.0].define(version: 2022_05_11_213227) do
create_table "games", force: :cascade do |t|
t.date "game_date", default: "2022-05-17", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "player_games", force: :cascade do |t|
t.integer "player_id", null: false
t.integer "game_id", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["game_id"], name: "index_player_games_on_game_id"
t.index ["player_id"], name: "index_player_games_on_player_id"
end
create_table "players", force: :cascade do |t|
t.string "name", null: false
t.integer "points", default: 0, null: false
t.boolean "active", default: true, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "snack_games", force: :cascade do |t|
t.integer "snack_id", null: false
t.integer "game_id", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "player_id", null: false
t.index ["game_id"], name: "index_snack_games_on_game_id"
t.index ["player_id"], name: "index_snack_games_on_player_id"
t.index ["snack_id"], name: "index_snack_games_on_snack_id"
end
create_table "snacks", force: :cascade do |t|
t.string "name", null: false
t.integer "points", default: 0, null: false
t.boolean "active", default: true, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_foreign_key "player_games", "games"
add_foreign_key "player_games", "players"
add_foreign_key "snack_games", "games"
add_foreign_key "snack_games", "players"
add_foreign_key "snack_games", "snacks"
end
I think player and snack controller's are not necessary so I include only games_controller
class GamesController < ApplicationController
before_action :set_game, only: %i[ show edit update destroy ]
# Find solution to assign players and snacks after create game not only from view but also from terminal
# GET /games or /games.json
def index
#games = Game.all
end
# GET /games/1 or /games/1.json
def show
end
# GET /games/new
def new
#game = Game.new
end
# GET /games/1/edit
def edit
end
# POST /games or /games.json
def create
#game = Game.new(game_params)
respond_to do |format|
if #game.save
format.html { redirect_to game_url(#game), notice: "Game was successfully created." }
format.json { render :show, status: :created, location: #game }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: #game.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /games/1 or /games/1.json
def update
respond_to do |format|
if #game.update(game_params)
format.html { redirect_to game_url(#game), notice: "Game was successfully updated." }
format.json { render :show, status: :ok, location: #game }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: #game.errors, status: :unprocessable_entity }
end
end
end
# DELETE /games/1 or /games/1.json
def destroy
#game.destroy
respond_to do |format|
format.html { redirect_to games_url, notice: "Game was successfully destroyed." }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_game
#game = Game.find(params[:id])
end
# Only allow a list of trusted parameters through.
def game_params
params.require(:game).permit(:game_date, player_ids: [], player_attributes: [:name])
end
end
and here is a form, but not correct with :snack_ids
<%= form_with(model: game) do |form| %>
<% if game.errors.any? %>
<div style="color: red">
<h2><%= pluralize(game.errors.count, "error") %> prohibited this game from being saved:</h2>
<ul>
<% game.errors.each do |error| %>
<li><%= error.full_message %></li>
<% end %>
</ul>
</div>
<% end %>
<div>
<%= form.label :game_date, style: "display: block" %>
<%= form.date_select :game_date %>
</div>
<div>
<%= form.collection_check_boxes :player_ids, Player.where(active: true), :id, :name, include_hidden: false %>
</div>
<div>
<%= form.collection_check_boxes :snack_ids, Snack.where(active: true), :id, :name, include_hidden: false %>
</div>
<div>
<%= form.submit %>
</div>
<% end %>
I know I could associate snack with player by creating in IRB for game SnackGame with player id and snack id but I dont know how to handle it in form and model
Related
I am trying to build a basic User/Post app on Ruby on Rails and everything was working smoothly, but then I added the devise gem to create the login/sign up for me and now I am not able to create a post. Once the user signs in they are redirected to http://localhost:3000/posts. There they can click "add new plant" (its posts about plants) and it takes them to the http://localhost:3000/posts/new page. Here the form is up and running, the user can fill in the title and description and hit the create post button, but then it just stays on this page and nothing happens. The post doesnt even get saved. If anyone could please give me some insight on how I can attempt to fix this, I would really appreciate it! The posts were being created normally before I added the users table with devise.
Started POST "/posts" for ::1 at 2020-07-26 12:24:01 -0400
Processing by PostsController#create as HTML
Parameters: {"authenticity_token"=>"Fm7HPgNsIJkKYzgOm/ApVCZfZJJuVQOLMP7eZvz1zFLok1QZdPxGC3f0p1Z1sRdUofCMlL5RU8wXwv31FIkj0w==", "post"=>{"title"=>"Lavender ", "description"=>"testing hello "}, "commit"=>"Create Post"}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ? [["id", 1], ["LIMIT", 1]]
Rendering posts/new.html.erb within layouts/application
Rendered posts/_form.html.erb (Duration: 13.2ms | Allocations: 5423)
Rendered posts/new.html.erb within layouts/application (Duration: 13.6ms | Allocations: 5487)
[Webpacker] Everything's up-to-date. Nothing to do
Completed 200 OK in 37ms (Views: 29.1ms | ActiveRecord: 0.2ms | Allocations: 11827)
that is the what shows up when I hit the create post button. Here is my schema:
ActiveRecord::Schema.define(version: 2020_07_26_023022) do
create_table "posts", force: :cascade do |t|
t.string "title"
t.text "description"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.integer "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.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
Here is my posts controller:
class PostsController < ApplicationController
before_action :find_post, only: [:show, :edit, :update, :destroy]
def index
#posts = Post.all.order("created_at DESC")
end
def show
end
def new
#post = Post.new
end
def create
#post = Post.new(post_params)
if #post.save
redirect_to #post
else
render 'new'
end
end
def edit
end
def update
if #post.update(post_params)
redirect_to #post
else
rend 'new'
end
end
def destroy
#post.destroy
redirect_to posts_path
end
private
def find_post
#post = Post.find(params[:id])
end
def post_params
params.require(:post).permit(:title, :description, :user_id)
end
end
Maybe this can help You...:
In controller:
def create
#post = Post.new(post_params)
#post.user = current_user # here You setting the user
if #post.save
redirect_to #post
else
puts #post.errors # this should print errors to the console
render 'new'
end
end
In models
module User
has_many :posts
...
end
module Post
belongs_to :user
...
end
Seems like some validation is failing for the Post. I'll advise to do something like this in your controller:
def create
#post = current_user.posts.build(post_params)
if #post.save!
redirect_to #post
else
render 'new'
end
end
save! will immediately fail if the issue is indeed in the validation and you'll be able to debug it further.
OR
I see in the logs that request is complete. It might be possible that posts are actually getting created? Did you check your Database?
Just started learning ruby on rails, and i created a simple shopping cart application but when i click "add to cart", i get a rollback transaction from my server. I believe the error has something to do with my orderitem controller but not sure how to fix this issue here my code.
rails server
Started POST "/order_items" for 127.0.0.1 at 2017-10-25 10:47:44 -0400
Processing by OrderItemsController#create as JS
Parameters: {"utf8"=>"✓", "order_item"=>{"product_id"=>"13", "quantity"=>"1"}, "commit"=>"Add to cart"}
(0.0ms) begin transaction
Product Load (0.5ms) SELECT "products".* FROM "products" WHERE "products"."id" = ? LIMIT ? [["id", 13], ["LIMIT", 1]]
(0.0ms) rollback transaction
Rendering order_items/create.js.erb
Rendered order_items/create.js.erb (0.5ms)
Completed 200 OK in 1028ms (Views: 605.5ms | ActiveRecord: 0.5ms)
order_items_controller.rb
class OrderItemsController < ApplicationController
def create
#order = current_order
#order_item = #order.order_items.new(order_item_params)
#order.save
session[:order_id] = #order.id
end
def update
#order = current_order
#order_item = #order.order_items.new(order_item_params)
#order_item.update_attributes(order_item_params)
#order_items = #order.order_items
end
def destroy
#order = current_order
#order_item = #order.order_items.find(params[:id])
#order_item.destroy
#order_items = #order.order_items
end
private
def order_item_params
params.require(:order_item).permit(:product_id, :quantity)
end
end
create.js.erb
<% if #order.errors.any? || #order_item.errors.any? %>
alert("Invalid")
<% else %>
$(".cart").html("<%= escape_javascript(render 'layouts/cart') %>")
<% end %>
schema.rb
ActiveRecord::Schema.define(version: 20171019015705) do
create_table "order_items", force: :cascade do |t|
t.integer "product_id"
t.integer "order_id"
t.integer "quantity"
t.float "total_price"
t.float "unit_price"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "orders", force: :cascade do |t|
t.float "subtotal"
t.float "total"
t.float "shipping"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id"
end
create_table "products", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.float "price"
t.text "description"
t.string "picture"
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.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.string "username"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
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
orderItem.rb
class OrderItem < ApplicationRecord
belongs_to :order
belongs_to :product
before_save :set_unit_price
before_save :set_total_price
def unit_price
if persisted?
self[:unit_price]
else
product.price
end
end
def total_price
unit_price * quantity
end
private
def set_unit_price
self[:unit_price] = unit_price
end
def set_total_price
self[:total_price] = quantity * set_unit_price
end
end
order.rb
class Order < ApplicationRecord
has_many :order_items
belongs_to :user
before_save :set_subtotal
def subtotal
order_items.collect {|order_item| order_item.valid? ? (order_item.unit_price*order_item.quantity) : 0}.sum
end
private
def set_subtotal
self[:subtotal] = subtotal
end
end
user.rb
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :orders
def to_param
username
end
end
carts_controller.rb
class CartsController < ApplicationController
before_action :authenticate_user!
def show
#order_items = current_order.order_items
end
end
Rails Server now
Started GET "/products" for 127.0.0.1 at 2017-10-25 11:21:11 -0400
Processing by ProductsController#index as HTML
Rendering products/index.html.erb within layouts/application
Product Load (0.0ms) SELECT "products".* FROM "products"
Rendered products/index.html.erb within layouts/application (16.0ms)
User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ? [["id", 1], ["LIMIT", 1]]
Rendered layouts/_cart.html.erb (1.0ms)
Rendered layouts/_nav.html.erb (34.3ms)
Completed 200 OK in 604ms (Views: 571.1ms | ActiveRecord: 0.5ms)
#order_item = #order.order_items.new(order_item_params)
is creating an item only in memory. there is nothing wrong with that.but i think you need to change the new to create as so
#order_item = #order.order_items.create(order_item_params)
I am building a feature in an app where a user can upload a resume as "pdf" with carrierwave. It should only be possible to upload one file but I can not make the record unique on the database level nor I can use unique as a validation on the model file because carrierwave does not allow it.
To solve this issue I have decided that I want to at least redirect from the new action to the show action(existing "download_file") if any record exists so the user will be not able to upload a second file into the database.
I guess my issue is that the new action finds a destroyed resume record with the id: 1 and thats why the form will not be rendered and I would not get redirected to the existing record.
How can I accomplish this? What am I missing?
resumes_contrller.rb
class ResumesController < ApplicationController
around_filter :catch_not_found
before_action :find_resume, only: [ :show, :edit, :update, :destroy]
def show
end
def new
if Resume.exists?
redirect_to Resume.find(params[:id])
else
#resume = Resume.new
end
end
def create
#resume = Resume.new resume_params
if #resume.save
redirect_to #resume
else
render :new
end
end
def edit
end
def update
if #resume.update resume_params
redirect_to #resume, notice: "Your resume was successfully saved!"
else
render 'edit'
end
end
def destroy
#resume.destroy
redirect_to new_resume_path, notice: "Your resume was successfully deleted!"
end
private
def resume_params
params.require(:resume).permit( :download_file, :remove_download_file)
end
def find_resume
#resume = Resume.find(params[:id])
end
def catch_not_found
yield
rescue ActiveRecord::RecordNotFound
redirect_to(root_url, :notice => 'Record not found')
end
end
schema.rb
ActiveRecord::Schema.define(version: 20170821213418) do
create_table "resumes", force: :cascade do |t|
t.string "download_file"
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 "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
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
development.log
Started GET "/resumes/new" for 77.8.47.62 at 2017-08-22 19:58:07 +0000
Cannot render console from 77.8.47.62! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by ResumesController#new as HTML
[1m[36mResume Exists (0.1ms)[0m [1mSELECT 1 AS one FROM "resumes" LIMIT 1[0m
[1m[35mResume Load (0.1ms)[0m SELECT "resumes".* FROM "resumes" WHERE "resumes"."id" = ? LIMIT 1 [["id", nil]]
Redirected to https://rails-tutorial-martinbortowski.c9.io/
Completed 302 Found in 10ms (ActiveRecord: 0.9ms)
Started GET "/" for 77.8.47.62 at 2017-08-22 19:58:08 +0000
Cannot render console from 77.8.47.62! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by WelcomesController#index as HTML
Rendered welcomes/index.html.erb within layouts/application (0.3ms)
Completed 200 OK in 59ms (Views: 58.2ms | ActiveRecord: 0.0ms)
In your code, Resume.exists? is akin to asking the question, "Is there at least one resume record in my database?"
If you examine the query it produces, you'll see something like
SELECT 1 AS one FROM `resumes` LIMIT 1
I believe what you really want to do is associate the resume to a user. As Pedro said, you'll want to set up a relation between User and Resume to keep track of the association.
Then you'll want something like
class ResumesController < ApplicationController
# ...
def new
if resume = current_user.resume
redirect_to resume
else
#resume = Resume.new
end
end
# ...
end
I can not for the life of me figure out why certain attributes of my paperclip attachment aren't not getting saved to the database via nested attributes. My post has one attachment but the :media params for the :attachment attribute not being saved, but the attachment object is being created. I figure I have something messed up with the way my strong params are being passed in. Thanks in advance.
NIL Params
media_file_name: nil, media_content_type: nil, media_file_size: nil, media_updated_at: nil>
IRB:
irb(main):001:0> p = Post.last
Post Load (0.1ms) SELECT "posts".* FROM "posts" ORDER BY "posts"."id" DESC LIMIT 1
=> #<Post id: 40, body: "test info", expiration: 1467065130586, created_at: "2016-06-27 21:05:41", updated_at: "2016-06-27 21:05:41">
irb(main):002:0> p.attachment
Attachment Load (0.2ms) SELECT "attachments".* FROM "attachments" WHERE "attachments"."attachable_id" = ? AND "attachments"."attachable_type" = ? LIMIT 1 [["attachable_id", 40], ["attachable_type", "Post"]]
=> #<Attachment id: 26, attachable_id: 40, attachable_type: "Post", created_at: "2016-06-27 21:05:41", updated_at: "2016-06-27 21:05:41", media_file_name: nil, media_content_type: nil, media_file_size: nil, media_updated_at: nil>
irb(main):003:0>
Schema:
ActiveRecord::Schema.define(version: 20160627165514) do
create_table "attachments", force: :cascade do |t|
t.integer "attachable_id"
t.string "attachable_type"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "media_file_name"
t.string "media_content_type"
t.integer "media_file_size"
t.datetime "media_updated_at"
end
add_index "attachments", ["attachable_type", "attachable_id"], name: "index_attachments_on_attachable_type_and_attachable_id"
create_table "posts", force: :cascade do |t|
t.text "body"
t.integer "expiration", limit: 8
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
end
Post Model:
class Post < ActiveRecord::Base
has_one :attachment, as: :attachable, dependent: :destroy
accepts_nested_attributes_for :attachment
end
Post Controller:
class PostsController < ApplicationController
def show
#I don't need this.
end
def index
#posts = Post.all
end
def new
#post = Post.new
#post.build_attachment
end
def create
#post = Post.new(post_params)
#post.build_attachment
if #post.save
respond_to do |format|
format.html {redirect_to(posts_path, notice:"Post succesfully created")}
format.js
end
else
render :new
end
end
private
def post_params
params.require(:post).permit(:body,:expiration, attachment_attributes: [:media])
end
end
Attachment Model:
class Attachment < ActiveRecord::Base
belongs_to :attachable, polymorphic:true
has_attached_file :media
end
HTML FORM:
<%=form_for(#post, url: posts_path, html:{multipart:true}) do |form|%>
<%=form.text_area :body%>
<%=fields_for(:attachment) do |ff|%>
<%= ff.file_field :media %>
<%end%>
<%=form.hidden_field :expiration%>
<%=form.submit "Post", class: "post-submit-button"%>
<%end%>
Log Dumb:
Started POST "/posts" for ::1 at 2016-06-27 16:05:41 -0500
Processing by PostsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"/b54OJOBJIaR551MAHDujCxjciI7OAx93EQAVrugCz0xtYnafaSH4widYOftZJUbDHLfmI6jly5eG5AxCCNJbQ==", "post"=>{"body"=>"test info", "expiration"=>"1467065130586"}, "attachment"=>{"media"=>"IMG_1004.jpg"}, "commit"=>"Post"}
(0.1ms) begin transaction
SQL (0.3ms) INSERT INTO "posts" ("body", "expiration", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["body", "test info"], ["expiration", 1467065130586], ["created_at", "2016-06-27 21:05:41.321484"], ["updated_at", "2016-06-27 21:05:41.321484"]]
SQL (0.1ms) INSERT INTO "attachments" ("attachable_type", "attachable_id", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["attachable_type", "Post"], ["attachable_id", 40], ["created_at", "2016-06-27 21:05:41.323335"], ["updated_at", "2016-06-27 21:05:41.323335"]]
(1.4ms) commit transaction
Redirected to http://localhost:3000/posts
Completed 302 Found in 8ms (ActiveRecord: 1.9ms)
Started GET "/posts" for ::1 at 2016-06-27 16:05:41 -0500
Processing by PostsController#index as HTML
Rendered layouts/_user_menu.html.erb (0.1ms)
Rendered posts/index.html.erb within layouts/application (1.8ms)
Completed 200 OK in 26ms (Views: 25.8ms | ActiveRecord: 0.0ms)
You're not binding your fields_for to your form. Try this:
<%=form_for(#post, url: posts_path, html:{multipart:true}) do |form|%>
<%=form.text_area :body%>
<%= form.fields_for(:attachment) do |ff|%>
<%= ff.file_field :media %>
<% end %>
<%=form.hidden_field :expiration%>
<%=form.submit "Post", class: "post-submit-button"%>
<%end%>
My user id isn't saving and I do not understand why.
I added the associations to both models and added the user_id to the notification params but the user id does not save automatically.
The campus_id relation does work properly and I do not really see the difference. What could be the problem? I am using a postgress database.
rails server log
Rendered /usr/local/rvm/gems/ruby-2.1.1#rails4/gems/actionpack-4.0.2/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (59.4ms)
Started POST "/campus/1/notifications" for 84.193.153.106 at 2014-10-18 19:41:03 +0000
Started POST "/campus/1/notifications" for 84.193.153.106 at 2014-10-18 19:41:03 +0000
Processing by NotificationsController#create as HTML
Processing by NotificationsController#create as HTML
Parameters: {"utf8"=>"_", "authenticity_token"=>"L9RH3hZyAKqzq9/kuJJDNaEHNVca2DbQSKSZLc8iTuw=", "notification"=>{"post"=>"thisisatest"}, "commit"=>"Maak notificatie", "campu_id"=>"1"}
Parameters: {"utf8"=>"_", "authenticity_token"=>"L9RH3hZyAKqzq9/kuJJDNaEHNVca2DbQSKSZLc8iTuw=", "notification"=>{"post"=>"thisisatest"}, "commit"=>"Maak notificatie", "campu_id"=>"1"}
Campus Load (0.6ms) SELECT "campus".* FROM "campus" WHERE "campus"."id" = $1 LIMIT 1 [["id", "1"]]
Campus Load (0.6ms) SELECT "campus".* FROM "campus" WHERE "campus"."id" = $1 LIMIT 1 [["id", "1"]]
User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 ORDER BY "users"."id" ASC LIMIT 1
User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 ORDER BY "users"."id" ASC LIMIT 1
(0.2ms) BEGIN
(0.2ms) BEGIN
SQL (134.0ms) INSERT INTO "notifications" ("campus_id", "created_at", "post", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["campus_id", 1], ["created_at", Sat, 18 Oct 2014 19:41:03 UTC +00:00], ["post", "thisisatest"], ["updated_at", Sat, 18 Oct 2014 19:41:03 UTC +00:00]]
SQL (134.0ms) INSERT INTO "notifications" ("campus_id", "created_at", "post", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["campus_id", 1], ["created_at", Sat, 18 Oct 2014 19:41:03 UTC +00:00], ["post", "thisisatest"], ["updated_at", Sat, 18 Oct 2014 19:41:03 UTC +00:00]]
(42.1ms) COMMIT
(42.1ms) COMMIT
Redirected to https://sl-backoffice-c9-christoph88.c9.io/notifications/9
Redirected to https://sl-backoffice-c9-christoph88.c9.io/notifications/9
Completed 302 Found in 188ms (ActiveRecord: 177.4ms)
Completed 302 Found in 188ms (ActiveRecord: 177.4ms)
Notification model
class Notification < ActiveRecord::Base
belongs_to :campus
belongs_to :user
validates :post, presence: true
validates :campus_id, presence: true
end
User model
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:confirmable
has_many :notifications
has_many :spotlights
end
notifications controller
class NotificationsController < ApplicationController
before_action :set_notification, only: [:show, :edit, :update, :destroy]
before_action :set_campus, only: [:index, :new, :create]
before_action :authenticate_user!
def index
#notifications = #campus.notifications
end
def show
#campus = #notification.campus
end
def new
#notification = #campus.notifications.build
end
def edit
end
def create
#notification = #campus.notifications.build(notification_params)
respond_to do |format|
if #notification.save
format.html { redirect_to #notification }
format.json { render action: 'show', status: :created, location: #notification }
flash[:success] = 'Notification was successfully created.'
else
format.html { render action: 'new' }
format.json { render json: #notification.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #notification.update(notification_params)
format.html { redirect_to #notification }
format.json { head :no_content }
flash[:success] = 'Notification was successfully updated.'
else
format.html { render action: 'edit' }
format.json { render json: #notification.errors, status: :unprocessable_entity }
end
end
end
def destroy
#notification.destroy
respond_to do |format|
format.html { redirect_to campu_notifications_url(#notification.campus_id) }
format.json { head :no_content }
flash[:error] = 'Notification was successfully deleted.'
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_notification
#notification = Notification.find(params[:id])
end
def set_campus
#campus = Campus.find(params[:campu_id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def notification_params
params.require(:notification).permit(:post, :campus_id, :user_id)
end
end
schema.rb
# encoding: UTF-8
# This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
#
# Note that this schema.rb definition is the authoritative source for your
# database schema. If you need to create the application database on another
# system, you should be using db:schema:load, not running all the migrations
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
# you'll amass, the slower it'll run and the greater likelihood for issues).
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20141018121628) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "campus", force: true do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "collis", force: true do |t|
t.string "name"
t.text "teaser"
t.text "description"
t.string "coursetype"
t.text "target"
t.string "campus"
t.datetime "startdate"
t.datetime "created_at"
t.datetime "updated_at"
t.string "guid"
end
create_table "coursespotlights", force: true do |t|
t.boolean "spotlight"
t.integer "colli_id"
t.datetime "start"
t.datetime "stop"
t.string "colli_guid"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "coursespotlights", ["colli_id"], name: "index_coursespotlights_on_colli_id", using: :btree
create_table "notifications", force: true do |t|
t.text "post"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "campus_id"
t.integer "user_id"
end
add_index "notifications", ["campus_id"], name: "index_notifications_on_campus_id", using: :btree
add_index "notifications", ["user_id"], name: "index_notifications_on_user_id", using: :btree
create_table "spotlights", force: true do |t|
t.boolean "spotlight"
t.datetime "start"
t.datetime "stop"
t.string "name"
t.text "teaser"
t.datetime "coursedate"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "campus_id"
t.integer "user_id"
end
add_index "spotlights", ["user_id"], name: "index_spotlights_on_user_id", using: :btree
create_table "users", force: true 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.inet "current_sign_in_ip"
t.inet "last_sign_in_ip"
t.string "confirmation_token"
t.datetime "confirmed_at"
t.datetime "confirmation_sent_at"
t.string "unconfirmed_email"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
end
Because user_id is not a part of your parameters
From the log:
Parameters: {"utf8"=>"_", "authenticity_token"=>"L9RH3hZyAKqzq9/kuJJDNaEHNVca2DbQSKSZLc8iTuw=", "notification"=>{"post"=>"thisisatest"}, "commit"=>"Maak notificatie", "campu_id"=>"1"}
then the line from the strong params filters out unwanted content
params.require(:notification).permit(:post, :campus_id, :user_id)
this means only "notification"=>{"post"=>"thisisatest"} part will be allowed
then from the sql insert:
SQL (134.0ms) INSERT INTO "notifications" ("campus_id", "created_at", "post", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["campus_id", 1], ["created_at", Sat, 18 Oct 2014 19:41:03 UTC +00:00], ["post", "thisisatest"], ["updated_at", Sat, 18 Oct 2014 19:41:03 UTC +00:00]]
you have campus_id here because you are doing the update on #campus:
#campus.notifications.build(notification_params)
so, just make sure user_id comes in as part of notification and that is it!