I am trying to delete a post in my app. It's working fine in localhost but when i pushed to heroku it's not working. I get an error saying "Something went wrong , Please check the logs". Here is my code:
posts_controller.rb
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user! , except: [:index,:show,:search]
before_filter :check_user, only: [:edit,:update,:destroy]
# GET /posts
# GET /posts.json
def search
if params[:search].present?
#posts = Post.search(params[:search])
else
#posts = Post.all
end
end
def index
if params[:tag]
#posts = Post.tagged_with(params[:tag])
else
#posts = Post.all
end
end
# GET /posts/1
# GET /posts/1.json
def show
#reviews = Review.where(post_id: #post.id)
end
# GET /posts/new
def new
#post = Post.new
end
# GET /posts/1/edit
def edit
#post = Post.find(params[:id])
end
# POST /posts
# POST /posts.json
def create
#post = Post.new(post_params)
#post.user_id = current_user.id
respond_to do |format|
if #post.save
format.html { redirect_to #post, notice: 'Post was successfully created.' }
format.json { render :show, status: :created, location: #post }
else
format.html { render :new }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /posts/1
# PATCH/PUT /posts/1.json
def update
respond_to do |format|
if #post.update(post_params)
format.html { redirect_to root_url, notice: 'Post was successfully updated.' }
format.json { render :show, status: :ok, location: #post }
else
format.html { render :edit }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# DELETE /posts/1
# DELETE /posts/1.json
def destroy
#post.destroy
respond_to do |format|
format.html { redirect_to root_path, notice: 'Post was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_post
#post = Post.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def post_params
params.require(:post).permit(:title, :description,:image,:all_tags)
end
def check_user
if current_user.id != #post.user_id
redirect_to root_path , alert: "Sorry this Post belongs to someone else"
end
end
end
The Logs
view/posts/index.html.erb
<h3>Posts</h3>
<table class="table">
<thead>
<tr>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #posts.each do |post| %>
<tr>
<td><h4><%=link_to post.title , post%></h4></td>
<td><%=raw tag_links(post.all_tags)%></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
<td><%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<%end%>
</tbody>
</table>
models/post.rb
class Post < ActiveRecord::Base
searchkick
has_many :reviews , dependent: :destroy
has_many :taggings, dependent: :destroy
has_many :tags, through: :taggings
#Paperclip Installation
has_attached_file :image, styles: { medium: "300x300>", thumb: "100x100>" }, default_url: "/images/:style/missing.png"
validates_attachment_content_type :image, :content_type => ["image/jpg", "image/jpeg", "image/png", "image/gif"]
def all_tags=(names)
self.tags = names.split(",").map do |name|
Tag.where(name: name.strip).first_or_create!
end
end
def all_tags
self.tags.map(&:name).join(", ")
end
def self.tagged_with(name)
Tag.find_by_name!(name).posts
end
end
Schema
ActiveRecord::Schema.define(version: 20151026124712) do
create_table "posts", force: :cascade do |t|
t.string "title"
t.text "description"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id"
t.string "tags"
t.string "image_file_name"
t.string "image_content_type"
t.integer "image_file_size"
t.datetime "image_updated_at"
end
create_table "reviews", force: :cascade do |t|
t.text "comment"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id"
t.integer "post_id"
end
create_table "taggings", force: :cascade do |t|
t.integer "post_id"
t.integer "tag_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "taggings", ["post_id"], name: "index_taggings_on_post_id"
add_index "taggings", ["tag_id"], name: "index_taggings_on_tag_id"
create_table "tags", force: :cascade do |t|
t.string "name"
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"
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
create_table "votes", force: :cascade do |t|
t.integer "votable_id"
t.string "votable_type"
t.integer "voter_id"
t.string "voter_type"
t.boolean "vote_flag"
t.string "vote_scope"
t.integer "vote_weight"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "votes", ["votable_id", "votable_type", "vote_scope"], name: "index_votes_on_votable_id_and_votable_type_and_vote_scope"
add_index "votes", ["voter_id", "voter_type", "vote_scope"], name: "index_votes_on_voter_id_and_voter_type_and_vote_scope"
end
As the error log says, there are foreign keys related to posts in taggings table, so it does not allow you to delete posts.
I guess a post has many taggings, and a tagging belongs to a tag? In this case, you need to delete all taggings belong to the post you want to delete. The easiest way is adding dependent: :destroy to your post model like
# models/post.rb
has_many :taggings, dependent: :destroy
You have some records in Taggings table which referenced to Post record.
So you have several options -
has_many :taggings, dependent: :destroy
Or you can change yours migration:
add_foreign_key :taggins, :posts, on_delete: :cascade (you can add this in database migration)
Described here
Related
I'm new in RoR, and I'm working on Blog app, and implementing categories for articles. But I have trouble - when I create any article with some categories ('sport' or 'movie' or any other) I receive validation errors
- Category must exist
- Category can't be blank
But I have working dropdown list or categories (this helper):
def categories
category =
["Sport",
"Movie",
"Art",
"Nature",
"Exotic"]
category.each do |categ|
my_category = "#{categ}"
end
return category
end
And here is a piece of code of my article.new.html.erb file:
<p>
<%= f.label :category %><br>
<%= f.select :category, categories,
prompt: "Choose your category" %>
</p>
Also here is my db schema where categories fields are present:
create_table "articles", force: :cascade do |t|
t.string "title"
t.text "text"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "pic"
t.string "photo_file_name"
t.string "photo_content_type"
t.bigint "photo_file_size"
t.datetime "photo_updated_at"
t.string "music_file_name"
t.string "music_content_type"
t.bigint "music_file_size"
t.datetime "music_updated_at"
t.string "movie_file_name"
t.string "movie_content_type"
t.bigint "movie_file_size"
t.datetime "movie_updated_at"
t.string "category_id"
end
create_table "categories", force: :cascade do |t|
t.string "name"
t.text "desc"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "comments", force: :cascade do |t|
t.string "commenter"
t.text "body"
t.bigint "article_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["article_id"], name: "index_comments_on_article_id"
end
create_table "subscribers", force: :cascade do |t|
t.string "f_name"
t.string "l_name"
t.string "email"
t.string "country"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "users", force: :cascade do |t|
t.string "userid"
t.string "email"
t.string "password_digest"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "admin", default: false
end
add_foreign_key "comments", "articles"
end
And here is my models:
class Article < ApplicationRecord
belongs_to :category
has_many :comments, dependent: :destroy
validates :title, presence: true, length: {minimum: 3}
validates :text, presence: true, length: {minimum: 3}
validates :category_id, presence: true
end
class Category < ApplicationRecord
has_many :articles
end
Also this is my Article controller:
class ArticlesController < ApplicationController
before_action :admin_authorize, :except => [:index, :show, :search]
def index
#articles = Article.includes(:category).order("created_at DESC")
if params[:category].blank?
#articles = Article.all.order("created_at DESC")
else
#category_id = Category.find_by(name: params[:category]).id
#articles = Article.where(category_id: #category_id).order("created_at DESC")
end
end
def new
#article = Article.new
#categories = Category.all.map{|c| [c.name, c.id]}
end
def show
#article = Article.find(params[:id])
end
def create
#article = Article.new(article_params)
#article.category_id = params[:category_id]
respond_to do |format|
if #article.save
format.html { redirect_to #article, notice: "Article was successfully created!" }
format.json { render :show, status: :created, location: #article }
else
format.html { render :new}
format.json {render json: #article.errors, status: :unprocessable_entity}
end
end
end
def edit
#article = Article.find(params[:id])
#categories = Category.all.map{|c| [ c.name, c.id ] }
end
def search
if params[:search].blank?
#articles = Article.all
else
#articles = Article.search(params)
end
end
def update
#article = Article.find(params[:id])
#article.category_id = params[:category_id]
if #article.update(article_params)
redirect_to #article
else
render 'edit'
end
end
def destroy
#article = Article.find(params[:id])
#article.destroy
redirect_to articles_path
end
private
def article_params
params.require(:article).permit(:title, :text, :search, :music, :movie, :photo)
end
def find_article
#article = Article.find(params[:id])
end
end
Thanks in advance!!
You forgot the category_id in your permitted params:
def article_params
params.require(:article).permit(:title, :text, :search, :music, :movie, :photo, :category_id)
end
You also need to change your select helper to send category_id and not category in the POST request.
Now, with your categories helper, you don't send any category id in your select dropdown, just some "category" names which are not bound to any Category instances.
You can fix the select like this and remove your helper:
<p>
<%= f.label :category %><br>
<%= f.select :category_id, Category.all.collect{|c| [c.name, c.id]},
prompt: "Choose your category" %>
</p>
I am stock trying to write the code that make possible for users to update a balance every time they make a transaction.
This is a simple bartering application:
The user can either offer products for sale or buy products from other users.
The user pays with a kind of virtual money (units).
When a user clicks in Order a transaction is executed.
The Models are: User, Product and Order.
If the user orders a product ( here order=transaction) I expect that the orders price (here price=amount) will be added to the users balance:
My expectation is that this code in orders_controller could make that the amount of #price pass and adds to #balance and makes possible the update:
#user.balance = balance: (#user.balance += #order.price)
But this is not working
I have tried as well in orders_controller with this:
def balance
if #order.save
#user.balance_update!(balance: #user.balance + #order.price)
end
end
But doesnt work.
What could be wrong with this code?
Please help!
These are the relevant files:
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
validates :fullname,presence: true
validates :description, presence: false
validates :balance, presence: true, numericality:true
before_validation :load_defaults
def load_defaults
if self.new_record?
self.balance = 100
end
end
has_many :products
has_many :orders
end
class Order < ActiveRecord::Base
belongs_to :user
belongs_to :product
validates :price, presence: true
validates :product_id, presence: true
validates :user, presence: true
end
class Product < ActiveRecord::Base
belongs_to :user
has_many :orders
end
class OrdersController < ApplicationController
before_action :authenticate_user!
def create
#order = current_user.orders.create(order_params)
#user.balance = balance: (#user.balance += #order.price)
redirect_to user_orders_path
end
end
def user_orders
#orders = current_user.orders
end
private
def order_params
params.require(:order).permit(:price, :user_id)
end
end
class UsersController < ApplicationController
def show
#user = User.find(params[:id])
#products = #user.products
end
end
class ProductsController < ApplicationController
before_action :set_product, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:show]
def index
#products = current_user.products
end
def show
end
def new
#product = current_user.products.build
end
def edit
end
def create
#product = current_user.products.build(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
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
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
def set_product
#product = Product.find(params[:id])
end
def product_params
params.require(:product).permit(:name, :description, :price)
end
end
<p>
User name: <%= #user.fullname %>
</p>
<p>
Balance: <%= #user.balance %>
</p>
ActiveRecord::Schema.define(version: 20171031150052) do
create_table "orders", force: :cascade do |t|
t.integer "user_id"
t.integer "product_id"
t.integer "price"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "transactiontype"
t.integer "buyer_id"
t.integer "seller_id"
end
add_index "orders", ["product_id"], name: "index_orders_on_product_id"
add_index "orders", ["user_id"], name: "index_orders_on_user_id"
create_table "products", force: :cascade do |t|
t.string "name"
t.text "description"
t.integer "price"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id"
end
add_index "products", ["user_id"], name: "index_products_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", null: false
t.datetime "updated_at", null: false
t.string "fullname"
t.string "description"
t.integer "balance"
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
Rails.application.routes.draw do
devise_for :users
get 'pages/index'
resources :products
resources :users
resources :products do
resources :orders, only: [:create]
end
resources :orders, only: [:show]
get '/user_orders' => 'orders#user_orders'
end
If you assign an attribute directly you just assign a value and need call save yourself:
#user.balance = #order.price
#user.save!
Or you can use update (there is no balance_update), then you call it with a hash:
#user.update!(balance: #user.balance + #order.price)
Try
#user.update(balance: #user.balance + #order.price)
I want to display an image according to a category name. My images are in the app/assets/images
My tutos will have categories that I have created in the console.
Now, I have this error (again...) undefined method 'name' for nil:NilClass.
Thanks again for your precious help !
here is my form:
= simple_form_for #tuto do |f|
- if #tuto.errors.any?
#error_explanation
h2 = "#{pluralize(#tuto.errors.count, "error")} prohibited this tuto from being saved:"
ul
- #tuto.errors.full_messages.each do |message|
li = message
= f.hidden_field :user_id, value: current_user.id
= f.input :title
= f.collection_select :category_id, Category.all, :id, :name, {prompt: "Choose a category"}
= f.input :content, as: :text, input_html: { rows: "15" }
= f.button :submit, "Save"
the tutos_controller.rb
class TutosController < ApplicationController
before_action :authenticate_user!
before_action :set_tuto, only: [:show, :edit, :update, :destroy, :upvote]
def index
#tutos = Tuto.all.includes(:user, :category)
end
def show
#tuto = Tuto.find(params[:id])
#user = User.all
end
def new
#tuto = Tuto.new
end
def edit
end
def create
#tuto = Tuto.new(tuto_params)
#tuto.user_id = current_user.id
respond_to do |format|
if #tuto.save
flash[:success] = "Test"
format.html { redirect_to #tuto, notice: 'Tuto was successfully created.' }
format.json { render :show, status: :created, location: #tuto }
else
format.html { render :new }
format.json { render json: #tuto.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #tuto.update(tuto_params)
format.html { redirect_to #tuto, notice: 'Tuto was successfully updated.' }
format.json { render :show, status: :ok, location: #tuto }
else
format.html { render :edit }
format.json { render json: #tuto.errors, status: :unprocessable_entity }
end
end
end
def destroy
#tuto.destroy
respond_to do |format|
format.html { redirect_to tutos_url, notice: 'Tuto was successfully destroyed.' }
format.json { head :no_content }
end
end
def upvote
#tuto.upvote_by current_user
redirect_to :back
end
private
# def get_user
# #user = User.find(#tuto.user_id)
# end
def set_tuto
#tuto = Tuto.find(params[:id])
end
def tuto_params
params.require(:tuto).permit(:title, :content, :id, :user_id, :category_id)
end
end
the categories_controller.rb
class CategoriesController < ApplicationController
private
def categories_params
params.require(:categories).permit(:name, :description, :id)
end
end
my views/tutos/index.html.slim
.container
.row
.col-xs-12.col-sm-12
h1.text-gray Tutorials
br
-if user_signed_in?
= link_to "Create a tuto", new_tuto_path, class:"btn btn-success"
#tutos.transitions-enabled
- #tutos.each do |tuto|
.box.panel-default
-if tuto.category.name == "Ruby"
=image_tag("select/ruby.png")
-elsif tuto.category.name == "Rails 4"
=image_tag("selec/rails4.png")
-elsif tuto.category.name == "Rails 5"
=image_tag("selec/rails5.png")
-elsif tuto.category.name == "Heroku"
=image_tag("select/heroku.png")
-elsif tuto.category.name == "AWS"
=image_tag("select/aws.png")
= link_to tuto.title, tuto_path(tuto)
h6 Created by:
= tuto.user.full_name
hr
my schema.rb
ActiveRecord::Schema.define(version: 20160920133801) do
create_table "categories", force: :cascade do |t|
t.string "name"
t.text "description"
t.string "image"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "tutos", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "title"
t.text "content"
t.integer "user_id"
t.integer "category_id"
end
add_index "tutos", ["user_id"], name: "index_tutos_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", null: false
t.datetime "updated_at", null: false
t.string "first_name"
t.string "last_name"
t.boolean "admin"
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
create_table "votes", force: :cascade do |t|
t.integer "votable_id"
t.string "votable_type"
t.integer "voter_id"
t.string "voter_type"
t.boolean "vote_flag"
t.string "vote_scope"
t.integer "vote_weight"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "votes", ["votable_id", "votable_type", "vote_scope"], name: "index_votes_on_votable_id_and_votable_type_and_vote_scope"
add_index "votes", ["voter_id", "voter_type", "vote_scope"], name: "index_votes_on_voter_id_and_voter_type_and_vote_scope"
end
EDIT here is the error message:
Looks like you may have created at least one Tuto object without a category_id at some point and it's still in your (development?) database. I'm guessing you don't want that, in which case I usually wipe my development database with rake db:reset. Just make sure you're executing commands in development if you do that of course. In the future, you may want to validate the presence of category_id on your Tuto model as well.
I have tags showing in my category show view. When someone views the Mobile Phones Category they will see tags at the top such as iphone, apple, 16gb, black and ect. When someone clicks on 16gb, it should show every item with 16gb tagged in it.
I've worked on this error for 12 hours and can't fix it.
When someone clicks on a tag i get this error.
ActiveRecord::RecordNotFound in CategoriesController#show
Couldn't find Category with 'id'=
def set_category
#category = Category.find(params[:id])
end
I can't figure out how to fix it?
Im using act_as_taggable gem.
Here is category controller
class CategoriesController < ApplicationController
before_action :set_category, only: [:show]
before_action :admin_user, only: [:destroy, :index, :edit]
def index
#categories = Category.all
end
def show
if params[:tag]
#items = Item.tagged_with(params[:tag])
else
#items = Item.where(category_id: #category.id).order("created_at DESC")
end
end
def new
#category = Category.new
end
def edit
end
def create
#category = Category.new(category_params)
respond_to do |format|
if #category.save
format.html { redirect_to #category, notice: 'Category was successfully created.' }
format.json { render :show, status: :created, location: #category }
else
format.html { render :new }
format.json { render json: #category.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #category.update(category_params)
format.html { redirect_to #category, notice: 'Category was successfully updated.' }
format.json { render :show, status: :ok, location: #category }
else
format.html { render :edit }
format.json { render json: #category.errors, status: :unprocessable_entity }
end
end
end
def destroy
#category.destroy
respond_to do |format|
format.html { redirect_to categories_url, notice: 'Category was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_category
#category = Category.find(params[:id])
end
def category_params
params.require(:category).permit(:name, :parent_id)
end
# Confirms an admin user.
def admin_user
redirect_to(root_url) unless current_user.try(:admin?)
end
end
Here is my category show view.
<p id="notice"><%= notice %></p>
<div class = "col-md-3">
<h1>
<strong><%= #category.name %></strong>
</h1>
</div>
<div class = "col-md-9">
<div id="tag_cloud">
<% tag_cloud Item.tag_counts, %w[s m l] do |tag, css_class| %>
<%= link_to tag.name, tag_path(tag.name), class: css_class %>
<% end %>
</div>
</div>
<div class = "col-md-12">
<div class="line-separator"></div>
</div>
<div class = "col-md-12">
<div id="items" class="transitions-enabled">
<% #items.each do |item| %>
<div class="box panel panel-default">
<div class="itemlisttitle"><%= item.title %></div>
<%= link_to image_tag(item.image.url (:medium)), item %>
<div class ="panel-body">
<div class = "itemlistprice">$<%= item.price %></div>
<div class = "itemlistretailer"><%= image_tag item.user.avatar(:thumb) %> Retailer: <%= link_to item.user.username, item.user %></div>
</div>
</div>
<% end %>
</div>
</div>
Here is routes. So you can see how the tags are routed.
Rails.application.routes.draw do
resources :categories
get 'password_resets/new'
get 'password_resets/edit'
get 'sessions/new'
resources :users
get 'user_items' => 'users#show_user_items'
root 'items#home'
get 'signup' => 'users#new'
get 'show' => 'users#show'
get 'login' => 'sessions#new'
post 'login' => 'sessions#create'
delete 'logout' => 'sessions#destroy'
resources :account_activations, only: [:edit]
resources :password_resets, only: [:new, :create, :edit, :update]
resources :items
get 'items_new' => 'items#new'
get 'tags/:tags', to: 'categories#show', as: :tag
Schema.rb
ActiveRecord::Schema.define(version: 20150731101116) do
create_table "categories", force: :cascade do |t|
t.string "name"
t.string "ancestry"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "categories", ["ancestry"], name: "index_categories_on_ancestry"
create_table "items", force: :cascade do |t|
t.string "title"
t.decimal "price"
t.text "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.integer "category_id"
end
add_index "items", ["user_id", "created_at"], name: "index_items_on_user_id_and_created_at"
add_index "items", ["user_id"], name: "index_items_on_user_id"
create_table "taggings", force: :cascade do |t|
t.integer "tag_id"
t.integer "taggable_id"
t.string "taggable_type"
t.integer "tagger_id"
t.string "tagger_type"
t.string "context", limit: 128
t.datetime "created_at"
end
add_index "taggings", ["tag_id", "taggable_id", "taggable_type", "context", "tagger_id", "tagger_type"], name: "taggings_idx", unique: true
add_index "taggings", ["taggable_id", "taggable_type", "context"], name: "index_taggings_on_taggable_id_and_taggable_type_and_context"
create_table "tags", force: :cascade do |t|
t.string "name"
t.integer "taggings_count", default: 0
end
add_index "tags", ["name"], name: "index_tags_on_name", unique: true
create_table "users", force: :cascade do |t|
t.string "username"
t.string "email"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "password_digest"
t.string "remember_digest"
t.boolean "admin", default: false
t.string "activation_digest"
t.boolean "activated", default: false
t.datetime "activated_at"
t.string "reset_digest"
t.string ">"
t.datetime "reset_sent_at"
t.string "avatar_file_name"
t.string "avatar_content_type"
t.integer "avatar_file_size"
t.datetime "avatar_updated_at"
t.text "description"
end
add_index "users", ["email"], name: "index_users_on_email", unique: true
end
actually you are sending only params[:tag] butto find category you have to send id as well, try following
Change
<%= link_to tag.name, tag_path(tag.name), class: css_class %>
To
<%= link_to tag.name, tag_path(tag.name, id: #category.id), class: css_class %>
and check again
When a user clicks on a tag tag.name is put as a parameter and the route goes to the show action of the categories controller, naming the parameter tags. The show action has a before_action method set which tries to find the relevant Category object based on the id which it gets from the parameter called id.
There's no parameter called id when the set_category method runs after the user clicks on a tag.
Change the method to this
def set_category
if params[:tag]
#category = Category.find_by_name(params[:tag])
end
if params[:id]
#category = Category.find(params[:id])
end
end
With this code the show action will work if you send the name of the tag as a parameter called :tag or the id as a parameter called :id
I have a problem.
I want to get all matches in my player#show where player was engaged. So I did a many-to-many relationship.
Match model:
class Match < ActiveRecord::Base
has_many :match_schedules
has_many :players, through: :match_schedules
end
Player model:
class Player < ActiveRecord::Base
has_many :match_schedules
has_many :matches, through: :match_schedules
has_attached_file :avatar, :styles => { :medium => "300x300>", :thumb => "100x100>" }, :default_url => "/images/:style/missing.png"
validates_attachment_content_type :avatar, :content_type => /\Aimage\/.*\Z/
end
and my match_schedule model:
class MatchSchedule < ActiveRecord::Base
belongs_to :player
belongs_to :match
end
If i do something like this in rails console:
p = Player.find 1
m = p.matches.new
m.playerA = “leo”
m.playerB = “cris”
p.save
It works, i can display loop with name:
<% #player.matches.each do |match| %>
<%= match.playerA %>
<% end %>
Problem is that i don't really know how I can connect matches to player in my new form, in browser. Already i have something like this:
Players_helper:
module PlayersHelper
def player_hash(players)
hash = Hash.new
players.each do |player|
hash["#{player.first_name}" + " " + "#{player.last_name}"] = player.first_name + player.last_name
end
hash
end
end
and _form:
<div class="form-inputs">
<%= f.select :playerA, options_for_select(player_hash(#abc)) %>
<%= f.select :playerB, options_for_select(player_hash(#abc)) %>
<%= f.input :PlayerApoints %>
<%= f.input :PlayerBpoints %>
</div>
Matches controller for new and create method looks like:
def new
#match = Match.new
#abc = Player.all
end
def create
#match = Match.new(match_params)
respond_to do |format|
if #match.save
format.html { redirect_to #match, notice: 'Match was successfully created.' }
format.json { render :show, status: :created, location: #match }
else
format.html { render :new }
format.json { render json: #match.errors, status: :unprocessable_entity }
end
end
end
And my schema.rb:
ActiveRecord::Schema.define(version: 20150706185030) do
create_table "match_schedules", force: :cascade do |t|
t.integer "match_id"
t.integer "player_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "matches", force: :cascade do |t|
t.string "playerA"
t.string "playerB"
t.integer "PlayerApoints"
t.integer "PlayerBpoints"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "players", force: :cascade do |t|
t.string "first_name"
t.string "last_name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "avatar_file_name"
t.string "avatar_content_type"
t.integer "avatar_file_size"
t.datetime "avatar_updated_at"
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"
t.datetime "updated_at"
end
You left out your match_params hash, so I have to do some guessing but something along the lines of:
in your Match class:
class Match < ActiveRecord::Base
has_many :match_schedules
has_many :players, through: :match_schedules
accepts_nested_attributes_for :match_schedules
end
in your controller:
def new
#match = Match.new
#match.match_schedules.build
#abc = Player.all
end
def create
#match = Match.new(match_params)
respond_to do |format|
if #match.save
format.html { redirect_to #match, notice: 'Match was successfully created.' }
format.json { render :show, status: :created, location: #match }
else
format.html { render :new }
format.json { render json: #match.errors, status: :unprocessable_entity }
end
end
end
in your match_params whitelist you'll need to add:
..., :player_ids => [])
since it is an array you need to put it after the other params.
You will also have to modify your view code. Basically you want to return a match_shedules_attributes => {player_ids => [1,2]} this gives you the ability to tell the MatchSchedule table the ID of each player associated with that match_id. You can do this with a fields_for inside the form_for block. See this http://guides.rubyonrails.org/form_helpers.html
So in the create action in the Match controller it should also save two records in the MatchSchedule table, one with each player's id and the id of that match.