Token Fields - Record Inserted and then Deleted - ruby-on-rails

I am trying to get token fields to work based on the RailsCasts episode #258 and I can submit the form just fine. When I go back to my main page, my tag does not appear.
Looking at the server logs on my local machine, I can see...
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = 'zviHK_WgeHLYUAtbKdzyfQ' LIMIT 1
Activity Load (0.1ms) SELECT "activities".* FROM "activities" WHERE "activities"."id" = ? LIMIT 1 [["id", "6"]]
(0.0ms) begin transaction
Tag Load (3.1ms) SELECT "tags".* FROM "tags" WHERE "tags"."id" = ? LIMIT 1 [["id", 1]]
Tag Load (0.1ms) SELECT "tags".* FROM "tags" INNER JOIN "activities_tags" ON "tags"."id" = "activities_tags"."tag_id" WHERE "activities_tags"."activity_id" = 6
(0.3ms) INSERT INTO "activities_tags" ("activity_id", "tag_id") VALUES (6, 1)
(0.2ms) DELETE FROM "activities_tags" WHERE "activities_tags"."activity_id" = 6 AND "activities_tags"."tag_id" IN (1)
(1.6ms) commit transaction
The 'INSERT INTO "activities_tags"...' has the correct values but, for some reason, it is deleting the record immediately and I can't figure out where that would be coming into play.
My Activity controller:
class ActivitiesController < ApplicationController
...
def update
#activity = Activity.find(params[:id])
params[:activity][:tag_ids] ||= []
respond_to do |format|
if #activity.update_attributes(params[:activity])
flash[:success] = "Activity was successfully updated!"
format.html { redirect_to master_resumes_url }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #activity.errors, status: :unprocessable_entity }
end
end
end
...
end
My Activity.rb:
class Activity < ActiveRecord::Base
attr_accessible :end_date, :organization, :position, :start_date, :user_id,
:tag_tokens, :tag_ids
attr_reader :tag_tokens
has_and_belongs_to_many :tags
belongs_to :user
def tag_tokens=(ids)
temp = ids.split(",")
self.tag_ids = temp[0]
end
end
My activity form:
<%= form_for(#activity) do |f| %>
<h4>Choose Tags</h4>
<%= f.label :tag_tokens, "Tags" %>
<%= f.text_field :tag_tokens, "data-pre" => #activity.tags.map(&:attributes).to_json %>
<p><%= link_to "Create A New Tag", new_tag_path %></p>
<% end %>
Finally, my activities.js:
$(function() {
$("#activity_tag_tokens").tokenInput("/tags.json", {
crossDomain: false,
prePopulate: $("#activity_tag_tokens").data("pre"),
theme: "facebook",
allowCustomEntry: true
});
});
Any thoughts?

1) Do you have a before_filter named anywhere?
2) Do you have :activities_tags named in attr_accessible?

Related

Error while setting up tagging for multiple models

I'm trying to setup multiple tagging in my app. I have used a single tag and tagging model which works fine for tagging a single model.
However, after setting up the association, i got this error when i wanted to create a new question undefined method map for nil:NilClass which actually points to <%= select_tag(:kategory_id, options_for_select(#kategories), :prompt => "Select Category", class: "form-control") %>. I don't know why it's pointing to this since it has nothing to do with the tagging. I might have made a mistake somewhere which i could not figure out.
Here is how i do the setup.
I added taggable_id and taggable_type to taggings table.
class AddAttributesToTaggings < ActiveRecord::Migration[5.1]
def change
add_column :taggings, :taggable_id, :integer
add_column :taggings, :taggable_type, :string
add_index :taggings, [:taggable_type, :taggable_id]
end
end
Tag.rb
class Tag < ApplicationRecord
has_many :taggings
has_many :posts, through: :taggings, source: :taggable, source_type: Post
has_many :questions, through: :taggings, source: :taggable, source_type: Question
has_many :user_tags, dependent: :destroy
has_many :users, through: :user_tags
extend FriendlyId
friendly_id :name, use: :slugged
def should_generate_new_friendly_id?
name_changed?
end
end
tagging.rb
class Tagging < ApplicationRecord
belongs_to :tag
belongs_to :taggable, :polymorphic => true
end
Question.rb
class Question < ApplicationRecord
belongs_to :user
belongs_to :kategory
validates :title, :content, presence: true
is_impressionable counter_cache: true, unique: :all
Question.order('impressions_count DESC')
scope :most_recent, -> { order(created_at: :desc) }
extend FriendlyId
friendly_id :title, use: :slugged
def should_generate_new_friendly_id?
title_changed?
end
include Taggable
def related_questions
Question.joins(:tags).where(tags: { id: self.tags.pluck(:id) }).where.not(id: self.id)
end
end
models/concerns/taggable.rb
module Taggable
extend ActiveSupport::Concern
included do
has_many :taggings, :as => :taggable
has_many :tags, :through => :taggings
end
def tag_list
self.tags.collect do |tag|
tag.name
end.join(", ")
end
def tag_list=(tags_string)
tag_names = tags_string.split(",").collect{|s| s.strip.downcase}.uniq
new_or_found_tags = tag_names.collect { |name| Tag.friendly.find_or_create_by(name: name) }
self.tags = new_or_found_tags
end
end
tags and taggings table in schema.rb
create_table "taggings", force: :cascade do |t|
t.bigint "tag_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "taggable_id"
t.string "taggable_type"
t.index ["tag_id"], name: "index_taggings_on_tag_id"
t.index ["taggable_type", "taggable_id"], name: "index_taggings_on_taggable_type_and_taggable_id"
end
create_table "tags", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "slug"
t.index ["slug"], name: "index_tags_on_slug", unique: true
end
questions/_form
<%= form_with(model: question, local: true) do |form| %>
<% if question.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(question.errors.count, "error") %> prohibited this question from being saved:</h2>
<ul>
<% question.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<b><%= form.label "Category" %></b>
<%= select_tag(:kategory_id, options_for_select(#kategories), :prompt => "Select Category", class: "form-control") %>
</div>
<br>
<div class="field">
<b><%= form.label :title %></b>
<%= form.text_field :title, id: :question_title, class: "form-control" %>
</div>
<br>
<div class="field">
<%= form.label :content %>
<%= form.text_area :content, id: :question_content, class: "form-control" %>
</div>
<br>
<div>
<%= form.label :tag_list %>
<%= form.text_field :tag_list %>
</div>
<br>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
questions_controller.rb
class QuestionsController < ApplicationController
before_action :set_question, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
before_action :find_contacts
before_action :find_kategory
impressionist :actions=>[:show,:index]
# GET /questions
# GET /questions.json
def index
if params[:kategory].blank?
#questions = Question.most_recent
else
#kategory_id = Kategory.find_by(name: params[:kategory]).id
#questions = Question.where(:kategory_id => #kategory_id).most_recent
end
end
# GET /questions/1
# GET /questions/1.json
def show
impressionist(#question)
#most_viewed = Question.order('impressions_count DESC').take(20)
end
# GET /questions/new
def new
#question = current_user.questions.build
#kategories = Kategory.all.map{ |k| [k.name, k.id] }
end
# GET /questions/1/edit
def edit
#kategories = Kategory.all.map{ |k| [k.name, k.id] }
end
# POST /questions
# POST /questions.json
def create
#question = current_user.questions.build(question_params)
#question.kategory_id = params[:kategory_id]
respond_to do |format|
if #question.save
flash[:success] = 'Your question was successfully posted.'
format.html { redirect_to #question }
format.json { render :show, status: :created, location: #question }
else
format.html { render :new }
format.json { render json: #question.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /questions/1
# PATCH/PUT /questions/1.json
def update
respond_to do |format|
if #question.update(question_params)
flash[:success] = 'Your question was successfully updated.'
format.html { redirect_to #question }
format.json { render :show, status: :ok, location: #question }
else
format.html { render :edit }
format.json { render json: #question.errors, status: :unprocessable_entity }
end
end
end
# DELETE /questions/1
# DELETE /questions/1.json
def destroy
#question.destroy
respond_to do |format|
flash[:success] = 'Your question has been deleted.'
format.html { redirect_to questions_url }
format.json { head :no_content }
end
end
def most_viewed
#questions = Question.order('impressions_count DESC').take(20)
end
private
# Use callbacks to share common setup or constraints between actions.
def set_question
#question = Question.friendly.includes(:tags).find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def question_params
params.require(:question).permit(:title, :content, :kategory_id, :tag_list)
end
def find_contacts
#contacts = user_signed_in? ? current_user.all_active_contacts : ''
end
def find_kategory
#questions = Kategory.where(:kategory_id => #kategory_id)
end
end
UPDATE:**I'm now able to save a question without adding any tag but with tags added, I get a form error that tagging is invalid. **Tags are properly loaded when I edit a question.
Error Log:
Started POST "/questions" for 127.0.0.1 at 2018-07-13 12:01:01 +0100
Processing by QuestionsController#create as HTML
Parameters: {"utf8"=>"√", "authenticity_token"=>"hgLn8bzd6fVSzCIPtRd3P0Jp/LEso
/h5cKNBY0a80x3i4RF6tpLlRyqmls3xRFryqyP1/s/rLDVIt9C1/uK+qw==", "kategory_id"=>"1"
, "question"=>{"title"=>"Help!!! My Dell Inspiron 6400 is hanging", "content"=>"
Lorem ipsum dolor amet seitan offal ethical, beard viral lo-fi put a bird on it
salvia actually yr. Ethical ennui pitchfork fanny pack, gentrify seitan sartoria
l bespoke. Viral 90's church-key swag, you probably haven't heard of them banh m
i intelligentsia brunch DIY iceland wolf pitchfork. Everyday carry photo booth n
ormcore XOXO tumblr portland.\r\n\r\nBrooklyn heirloom kombucha, edison bulb leg
gings hell of DIY chartreuse austin tacos bitters. Blog hexagon copper mug blue
bottle cray. Post-ironic direct trade kale chips mumblecore. Craft beer squid cr
onut vape, hoodie bitters succulents ramps snackwave vegan small batch brunch ch
ia food truck umami. Chillwave blue bottle viral raclette authentic health goth
vape coloring book cardigan 3 wolf moon taxidermy. Gluten-free tote bag hella, l
omo pinterest direct trade gastropub tattooed. Iceland hammock post-ironic, bush
wick cornhole tumeric dreamcatcher blog palo santo chartreuse 90's food truck sy
nth chicharrones.", "tag_list"=>"hardware"}, "commit"=>"Create Question"}
User Load (2.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDE
R BY "users"."id" ASC LIMIT $2 [["id", 3], ["LIMIT", 1]]
Private::Conversation Load (2.9ms) SELECT "private_conversations".* FROM "pri
vate_conversations" WHERE ("private_conversations"."recipient_id" = $1 OR "priva
te_conversations"."sender_id" = $2) [["recipient_id", 3], ["sender_id", 3]]
Private::Message Load (2.0ms) SELECT "private_messages".* FROM "private_messa
ges" WHERE "private_messages"."conversation_id" IN (2, 3, 4, 6)
Group::Conversation Load (3.9ms) SELECT "group_conversations".* FROM "group_c
onversations" INNER JOIN "group_conversations_users" ON "group_conversations"."i
d" = "group_conversations_users"."conversation_id" WHERE "group_conversations_us
ers"."user_id" = $1 [["user_id", 3]]
Group::Message Load (2.0ms) SELECT "group_messages".* FROM "group_messages" W
HERE "group_messages"."conversation_id" = 1
User Load (2.0ms) SELECT "users".* FROM "users" WHERE "users"."id" IN (2, 3,
5)
(40.0ms) SELECT "group_conversations"."id" FROM "group_conversations" INNER
JOIN "group_conversations_users" ON "group_conversations"."id" = "group_conversa
tions_users"."conversation_id" WHERE "group_conversations_users"."user_id" = $1
[["user_id", 3]]
CACHE (0.0ms) SELECT "group_conversations"."id" FROM "group_conversations" I
NNER JOIN "group_conversations_users" ON "group_conversations"."id" = "group_con
versations_users"."conversation_id" WHERE "group_conversations_users"."user_id"
= $1 [["user_id", 3]]
User Load (2.9ms) SELECT "users".* FROM "users" INNER JOIN "contacts" ON "use
rs"."id" = "contacts"."contact_id" WHERE "contacts"."user_id" = $1 AND "contacts
"."accepted" = $2 [["user_id", 3], ["accepted", "t"]]
User Load (4.9ms) SELECT "users".* FROM "users" INNER JOIN "contacts" ON "use
rs"."id" = "contacts"."user_id" WHERE "contacts"."contact_id" = $1 AND "contacts
"."accepted" = $2 ORDER BY "users"."created_at" ASC [["contact_id", 3], ["accep
ted", "t"]]
Tag Load (2.0ms) SELECT "tags".* FROM "tags" WHERE "tags"."name" = $1 LIMIT
$2 [["name", "hardware"], ["LIMIT", 1]]
Kategory Load (10.7ms) SELECT "kategories".* FROM "kategories"
(1.0ms) BEGIN
Question Exists (4.9ms) SELECT 1 AS one FROM "questions" WHERE ("questions".
"id" IS NOT NULL) AND "questions"."slug" = $1 LIMIT $2 [["slug", "help-my-dell-
inspiron-6400-is-hanging"], ["LIMIT", 1]]
Kategory Load (5.9ms) SELECT "kategories".* FROM "kategories" WHERE "kategor
ies"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
(0.0ms) ROLLBACK
Rendering questions/new.html.erb within layouts/application
Rendered questions/_form.html.erb (17.6ms)
Rendered questions/new.html.erb within layouts/application (141.6ms)
Rendered layouts/navigation/header/_toggle_button.html.erb (1.0ms)
Rendered layouts/navigation/header/_home_button.html.erb (30.3ms)
User Load (28.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIM
IT $2 [["id", 5], ["LIMIT", 1]]
Rendered layouts/navigation/header/dropdowns/conversations/_private.html.erb (
73.2ms)
User Load (2.9ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMI
T $2 [["id", 3], ["LIMIT", 1]]
CACHE User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $
1 LIMIT $2 [["id", 5], ["LIMIT", 1]]
Rendered layouts/navigation/header/dropdowns/conversations/_private.html.erb (
109.4ms)
Rendered layouts/navigation/header/dropdowns/conversations/_group.html.erb (3.
9ms)
User Load (30.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIM
IT $2 [["id", 1], ["LIMIT", 1]]
Rendered layouts/navigation/header/dropdowns/conversations/_private.html.erb (
40.0ms)
CACHE User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $
1 LIMIT $2 [["id", 3], ["LIMIT", 1]]
User Load (2.9ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMI
T $2 [["id", 2], ["LIMIT", 1]]
Rendered layouts/navigation/header/dropdowns/conversations/_private.html.erb (
100.6ms)
Rendered layouts/navigation/header/dropdowns/_conversations.html.erb (983.4ms)
User Load (2.0ms) SELECT "users".* FROM "users" INNER JOIN "contacts" ON "use
rs"."id" = "contacts"."user_id" WHERE "contacts"."contact_id" = $1 AND "contacts
"."accepted" = $2 [["contact_id", 3], ["accepted", "f"]]
Rendered layouts/navigation/header/dropdowns/contact_requests/_no_requests.htm
l.erb (1.0ms)
Rendered layouts/navigation/header/dropdowns/_contact_requests.html.erb (374.0
ms)
Rendered layouts/navigation/header/_dropdowns.html.erb (1713.9ms)
Rendered layouts/navigation/_header.html.erb (2485.4ms)
Kategory Load (2.9ms) SELECT "kategories".* FROM "kategories"
Rendered layouts/navigation/collapsible_elements/_constant_links.html.erb (2.0
ms)
(2.0ms) SELECT COUNT(*) FROM "questions" INNER JOIN "save_questions" ON "que
stions"."id" = "save_questions"."question_id" WHERE "save_questions"."user_id" =
$1 [["user_id", 3]]
Rendered layouts/navigation/collapsible_elements/_signed_in_links.html.erb (21
.5ms)
Rendered layouts/navigation/_collapsible_elements.html.erb (543.0ms)
Rendered layouts/_navigation.html.erb (3323.2ms)
Rendered layouts/application/_private_conversations_windows.html.erb (1.0ms)
Rendered layouts/application/_group_conversations_windows.html.erb (2.0ms)
Completed 200 OK in 22203ms (Views: 21796.6ms | ActiveRecord: 158.2ms)
You need to define #kategories = Kategory.all.map{ |k| [k.name, k.id] } in create and update actions. This actions rerender new/edit actions if they can't save the question, and they need #kategories for rerendering
If you provide the full server log for create action I can try to help you to figure out - why #question can not be saved
Looks to me like your #kategories, or something within there (perhaps a name), is nil, hence the error :) (Hopefully this is a good thing, as all may be well with your tagging.)
Ensure Kategory.all.map { |k| [k.name, k.id] } in your new action is returning records and this error should go away.
N.B. you can also use options_from_collection_for_select here.
# in the controller
def new
#question = current_user.questions.build
#kategories = Kategory.all
end
# and the view
<%= select_tag(:kategory_id, options_from_collection_for_select(#kategories, :name, :id), prompt: "Select Category", class: "form-control") %>
This way, if you don't have any categories, you won't get an error - instead, you just won't have any options available.

In Rails, my model association with a view is causing a new SELECT statement for every row

I have an issue with bringing a view into my app, which calculates a running balance for a transactions table using SQL. I have the following models:
account.rb
class Account < ApplicationRecord
belongs_to :user
has_many :transactions, dependent: :destroy
validates :name, presence: true, length: { maximum: 50, minimum: 2 }
validates :starting_balance, presence: true
#validates_associated :transactions
after_create :create_initial_transaction
def create_initial_transaction
self.update_attributes(current_balance: 0.00)
Transaction.create(trx_type: 'credit', trx_date: DateTime.now, account_id: self.id, description: "Starting Balance", amount: self.starting_balance)
#self.update_attributes(current_balance: #initbalance)
end
end
transaction.rb
class Transaction < ApplicationRecord
belongs_to :account
has_one :transaction_balance
delegate :running_balance, to: :transaction_balance
attr_accessor :trx_type
#default_scope { order('trx_date, id DESC') }
validates_presence_of :trx_type, :message => "Please select debit or credit"
validates :trx_date, presence: true
validates :description, presence: true, length: { maximum: 150 }
validates :amount, presence: true, numericality: { greater_than_or_equal_to: 0 }
validates :memo, length: { maximum: 500 }
before_save :convert_amount
after_create :update_account_balance_new
after_update :update_account_balance_edit
after_destroy :update_account_balance_destroy
scope :with_balance, -> { joins(:transaction_balance) }
scope :desc, -> { order('trx_date, id DESC') }
# Determine the transaction_type for existing records based on amount
def transaction_type
if !new_record?
if self.amount >= 0
return ['Credit', 'credit']
else
return ['Debit', 'debit']
end
else
return ['Debit', 'debit']
end
end
private
def convert_amount
if self.trx_type == "debit"
self.amount = -self.amount.abs
end
end
def update_account_balance_new
#account = Account.find(account_id)
#account.update_attributes(current_balance: #account.current_balance + amount)
end
def update_account_balance_edit
#account = Account.find(account_id)
if saved_change_to_amount?
#account.update_attributes(current_balance: #account.current_balance - amount_was + amount)
end
end
def update_account_balance_destroy
#account = Account.find(account_id)
#account.update_attributes(current_balance: #account.current_balance - amount_was)
end
end
Basically my app allows users to create bank accounts, then add transactions to them to keep track of finances. I wanted to add a running balance at the transaction level, so I created a view which joins back to the transactions table 1:1 ....
Migration for view
class CreateTransactionBalancesView < ActiveRecord::Migration[5.1]
def up
execute <<-SQL
CREATE VIEW transaction_balances AS (
SELECT id AS transaction_id,
SUM(amount) OVER(PARTITION BY account_id ORDER BY trx_date, id) AS running_balance
FROM transactions
)
SQL
end
def down
execute("DROP VIEW transaction_balances")
end
end
Now, when I created a model for this view, I had issues referencing "belongs_to :transaction" because it was complaining that "transaction" was a reserved word, so I had to find a workaround, as seen in my model below:
transaction_balance.rb
class TransactionBalance < ApplicationRecord
self.primary_key = "transaction_id"
#belongs_to :transaction
belongs_to :user_transaction, foreign_key: "transaction_id", class_name: "Transaction"
end
transactions_controller.rb
class TransactionsController < ApplicationController
before_action :find_account
before_action :find_transaction, only: [:edit, :update, :show, :destroy]
# Index action to render all transactions
def index
#transactions = #account.transactions.paginate(page: params[:page], per_page: 25)
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #transactions }
end
end
# New action for creating transaction
def new
#transaction = #account.transactions.build
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #transaction }
end
end
# Create action saves the trasaction into database
def create
#transaction = #account.transactions.build(transaction_params)
respond_to do |format|
if #transaction.save
format.html { redirect_to([#transaction.account, #transaction], :notice => 'Transaction was successfully created.') }
format.xml { render :xml => #transaction, :status => :created, :location => [#transaction.account, #transaction] }
else
format.html { render :action => "new" }
format.xml { render :xml => #transaction.errors, :status => :unprocessable_entity }
end
end
end
# Edit action retrieves the transaction and renders the edit page
def edit
end
# Update action updates the transaction with the new information
def update
respond_to do |format|
if #transaction.update_attributes(transaction_params)
format.html { redirect_to([#transaction.account, #transaction], :notice => 'Transaction was successfully updated.') }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #transaction.errors, :status => :unprocessable_entity }
end
end
end
# The show action renders the individual transaction after retrieving the the id
def show
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #transaction }
end
end
# The destroy action removes the transaction permanently from the database
def destroy
#transaction.destroy
respond_to do |format|
format.html { redirect_to(account_transactions_url) }
format.xml { head :ok }
end
end
private
def transaction_params
params.require(:transaction).permit(:trx_date, :description, :amount, :trx_type, :memo)
end
def find_account
#account = current_user.accounts.find(params[:account_id])
end
def find_transaction
#transaction = #account.transactions.find(params[:id])
end
end
And finally, my transactions index view, where I reference the running_balance field
<% #transactions.with_balance.desc.each do |transaction| %>
<tr class="row m-0">
<td class="col-sm-1 text-center"><%= link_to transaction.id, [transaction.account, transaction] %></td>
<td class="col-sm-1 text-center"><%= transaction.trx_date.strftime('%m/%d/%Y') %></td>
<td class="col-sm-4"><%= transaction.description %></td>
<td class="col-sm-2 text-right"><%= if transaction.amount >= 0 then number_to_currency(transaction.amount) end %></td>
<td class="col-sm-2 text-right"><%= if transaction.amount < 0 then "(" + number_to_currency(transaction.amount.abs) + ")" end %></td>
<td class="col-sm-2 text-right"><%= number_to_currency(transaction.running_balance) %></td>
</tr>
<% end %>
Now, my problem is when I access the transactions index page in browser, my server console shows the following:
Started GET "/accounts/1/transactions" for 127.0.0.1 at 2018-03-28 16:32:08 -0400
Processing by TransactionsController#index as HTML
Parameters: {"account_id"=>"1"}
User Load (0.6ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 1], ["LIMIT", 1]]
Account Load (1.1ms) SELECT "accounts".* FROM "accounts" WHERE "accounts"."user_id" = $1 AND "accounts"."id" = $2 LIMIT $3 [["user_id", 1], ["id", 1], ["LIMIT", 1]]
Rendering transactions/index.html.erb within layouts/application
Transaction Load (0.8ms) SELECT "transactions".* FROM "transactions" INNER JOIN "transaction_balances" ON "transaction_balances"."transaction_id" = "transactions"."id" WHERE "transactions"."account_id" = $1 ORDER BY trx_date, id DESC LIMIT $2 OFFSET $3 [["account_id", 1], ["LIMIT", 25], ["OFFSET", 0]]
TransactionBalance Load (0.3ms) SELECT "transaction_balances".* FROM "transaction_balances" WHERE "transaction_balances"."transaction_id" = $1 LIMIT $2 [["transaction_id", 8], ["LIMIT", 1]]
TransactionBalance Load (1.5ms) SELECT "transaction_balances".* FROM "transaction_balances" WHERE "transaction_balances"."transaction_id" = $1 LIMIT $2 [["transaction_id", 7], ["LIMIT", 1]]
TransactionBalance Load (0.3ms) SELECT "transaction_balances".* FROM "transaction_balances" WHERE "transaction_balances"."transaction_id" = $1 LIMIT $2 [["transaction_id", 6], ["LIMIT", 1]]
TransactionBalance Load (0.2ms) SELECT "transaction_balances".* FROM "transaction_balances" WHERE "transaction_balances"."transaction_id" = $1 LIMIT $2 [["transaction_id", 5], ["LIMIT", 1]]
TransactionBalance Load (0.2ms) SELECT "transaction_balances".* FROM "transaction_balances" WHERE "transaction_balances"."transaction_id" = $1 LIMIT $2 [["transaction_id", 4], ["LIMIT", 1]]
TransactionBalance Load (0.3ms) SELECT "transaction_balances".* FROM "transaction_balances" WHERE "transaction_balances"."transaction_id" = $1 LIMIT $2 [["transaction_id", 3], ["LIMIT", 1]]
TransactionBalance Load (1.0ms) SELECT "transaction_balances".* FROM "transaction_balances" WHERE "transaction_balances"."transaction_id" = $1 LIMIT $2 [["transaction_id", 1], ["LIMIT", 1]]
(1.8ms) SELECT COUNT(*) FROM "transactions" WHERE "transactions"."account_id" = $1 [["account_id", 1]]
Rendered transactions/index.html.erb within layouts/application (59.8ms)
Account Load (0.5ms) SELECT "accounts".* FROM "accounts" WHERE "accounts"."user_id" = $1 [["user_id", 1]]
Rendered layouts/_navbar.html.erb (3.9ms)
Completed 200 OK in 255ms (Views: 169.1ms | ActiveRecord: 19.5ms)
As seen above, the view is being selected from for each individual record. What I expect it to do is to join the transactions table with the transaction_balances view in one single select statement. Any help on this would be greatly appreciated! Thanks!
In your TransactionsController#index action, change this line:
#transactions = #account.transactions.paginate(page: params[:page], per_page: 25)
to this (credit to #engineersmnky):
#transactions = #account.transactions.includes(:transaction_balance).references(:transaction_balance).paginate(page: params[:page], per_page: 25)
This will generate a single query that allows your view to access the transaction_balance for each transaction without going back to the database.
This is happening because you're not loading the TransactionBalance records when you load the transactions in your controller. Here's what you're doing:
#account.transactions
And here's what will fix the problem:
#account.transactions.with_balance
This will use the with_balance scope in your model, which does joins(:balance), which will load both the transacations and all their balances in the one query.
I'm not sure where you're getting your #account from in your TransactionsController, but you may want to do a join or an includes.
For instance, #account = Account.includes(:transactions).find(params[:account_id]) before you query the transactions will eager load the transactions and pull them in one query rather than "n+1-ing" them.
The API dock entry can tell you more about the includes method
and
This article can tell you more about how to get rid of the n+1 querying problem.
Good luck!

Rails Tutorial partial refresh

I went through Michael Hartl's Rails Tutorial book and I want to use Ajax for automatic feed refresh, on micropost creation and micropost deletion.
As far as I understand, I only need to specify the remote: true parameter in the form inside the correct partial and respond to js inside the appropriate method.
Nevertheless, when I try to accomplish the partial refresh with a create action I'm getting a strange NoMethodError indicating that my #feed_items is a nil object.
Started POST "/microposts" for 77.70.8.167 at 2016-06-28 10:21:32 +0000
Processing by MicropostsController#create as JS
Parameters: {"utf8"=>"✓", "authenticity_token"=>"qJHp9flp+EV+cxdeF69L8eSzC1fMsjr+mi57f3u3z2Y/fJI9dl1to9t4jlrX4g2uhIP67FiwvjwL7SP2Hmc4fw==", "micropost"=>{"content"=>"dsdsds"}, "commit"=>"Post"}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 1]]
(0.1ms) begin transaction
SQL (0.3ms) INSERT INTO "microposts" ("content", "user_id", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["content", "dsdsds"], ["user_id", 1], ["created_at", "2016-06-28 10:21:32.797365"], ["updated_at", "2016-06-28 10:21:32.797365"]]
(11.1ms) commit transaction
###################################NilClass
Rendered shared/_feed.html.erb (7.7ms)
Rendered microposts/create.js.erb (11.5ms)
Completed 500 Internal Server Error in 43ms (ActiveRecord: 11.7ms)
NoMethodError (undefined method `any?' for nil:NilClass):
app/views/shared/_feed.html.erb:3:in `_app_views_shared__feed_html_erb___1168566426182367941_69986820092480'
app/views/microposts/create.js.erb:1:in `_app_views_microposts_create_js_erb__3336806296105309297_69986601152860'
app/controllers/microposts_controller.rb:9:in `create'
Here's my _micropost.html.erb partial:
<%= form_for(#micropost, remote: true) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.text_area :content, placeholder: "Compose new micropost..." %>
</div>
<%= f.submit "Post", class: "btn btn-primary" %>
<span class="picture">
<%= f.file_field :picture, accept: 'image/jpeg, image/gif, image/png' %>
</span>
<% end %>
<script type="text/javascript">
$('#micropost_picture').bind('change', function(){
size_in_megabytes = this.files[0].size/1024/1024;
if (size_in_megabytes > 5) {
alert('Maximum file size is 5MB. Please chose a smaller file.')
}
})
</script>
Create.js.erb:
$(".ajaxreloadposts").html("<%= escape_javascript(render('shared/feed')) %>");
_feed.html.erb:
<% if #feed_items.any? %>
<ol class="microposts">
<%= render #feed_items %>
</ol>
<%= will_paginate #feed_items %>
<% end %>
Create action:
def create
#micropost = current_user.microposts.build(micropost_params)
if #micropost.save!
# flash[:success] = "Micropost created!"
respond_to do |format|
format.html { redirect_to root_path }
format.js
end
else
#feed_items = []
render 'static_pages/home'
end
end
_home_logged_in.html.erb:
<div class="row">
<aside class="col-md-4">
<section class="user_info">
<%= render 'shared/user_info' %>
</section>
<section class="stats">
<%= render 'shared/stats' %>
</section>
<section class="micropost_form">
<%= render 'shared/micropost_form' %>
</section>
</aside>
<div class="col-md-8">
<h3>Where are your buddies right now?</h3>
<%= render 'shared/gmaps' %>
</div>
<div class="col-md-8">
<h3>Micropost Feed</h3>
<span class="ajaxreloadposts">
<%= render 'shared/feed' %>
</span>
</div>
</div>
And finally, I guess, the relevant part of my static_pages_controller:
def home
if logged_in?
#micropost = current_user.microposts.build
#feed_items = current_user.feed.paginate(page: params[:page])
#gmaps_users = current_user.gmaps_feed
#hash = Gmaps4rails.build_markers(#gmaps_users) do |spot, marker|
marker.lat spot.lat
marker.lng spot.lng
marker.infowindow spot.user.name
end
if !current_user.checkin.nil?
#user_lat = current_user.checkin.lat
#user_lng = current_user.checkin.lng
end
end
end
I tried following these resources, but in vain:
AJAX to update micropost vote up/down partial only refreshes the most recent post
and
AJAX feed update on post
and
How to update feed using ajax in Rails 4.0
I might have missed something, but since I'm really new to Rails, I hope you'll be merciful.
Thanks for your time, help and cheers.
Okay, it might be a bit noobish, but I managed to fix the problem by inserting an instance variable called #feed_items inside both the create and destroy methods.
def create
#feed_items = current_user.feed.paginate(page: params[:page])
#micropost = current_user.microposts.build(micropost_params)
if #micropost.save!
# flash[:success] = "Micropost created!"
respond_to do |format|
format.html { redirect_to root_path }
format.js
end
else
#feed_items = []
render 'static_pages/home'
end
end
def destroy
#micropost.destroy
#feed_items = current_user.feed.paginate(page: params[:page])
# flash[:success] = "Micropost deleted!"
respond_to do |format|
format.html { redirect_to request.referrer || root_url }
format.js
end
end
Here's the rails output from micropost creation and deletion:
Started POST "/microposts" for 77.70.8.167 at 2016-06-28 12:20:56 +0000
Processing by MicropostsController#create as JS
Parameters: {"utf8"=>"✓", "authenticity_token"=>"wd7XeH4MYDINH2+PrDy8perRJ77VKTwjZ82tsHdESbNWM6yw8Tj11KgU9otscfr6iuHWBUEruOH2DvU5EpS+qg==", "micropost"=>{"content"=>"workworkwork"}, "commit"=>"Post"}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 1]]
(0.1ms) begin transaction
SQL (0.3ms) INSERT INTO "microposts" ("content", "user_id", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["content", "workworkwork"], ["user_id", 1], ["created_at", "2016-06-28 12:20:56.699428"], ["updated_at", "2016-06-28 12:20:56.699428"]]
(11.0ms) commit transaction
(3.5ms) SELECT COUNT(*) FROM "microposts" WHERE (user_id IN (SELECT followed_id FROM relationships
WHERE follower_id = 1)
OR user_id = 1)
Micropost Load (1.2ms) SELECT "microposts".* FROM "microposts" WHERE (user_id IN (SELECT followed_id FROM relationships
WHERE follower_id = 1)
OR user_id = 1) ORDER BY "microposts"."created_at" DESC LIMIT 30 OFFSET 0
CACHE...
Rendered microposts/_micropost.html.erb (43.1ms)
Rendered shared/_feed.html.erb (60.3ms)
Rendered microposts/create.js.erb (65.5ms)
Completed 200 OK in 99ms (Views: 76.4ms | ActiveRecord: 17.6ms)
Started DELETE "/microposts/348" for 77.70.8.167 at 2016-06-28 12:20:59 +0000
Processing by MicropostsController#destroy as JS
Parameters: {"id"=>"348"}
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 1]]
Micropost Load (0.1ms) SELECT "microposts".* FROM "microposts" WHERE "microposts"."user_id" = ? AND "microposts"."id" = ? ORDER BY "microposts"."created_at" DESC LIMIT 1 [["user_id", 1], ["id", 348]]
(0.1ms) begin transaction
SQL (0.4ms) DELETE FROM "microposts" WHERE "microposts"."id" = ? [["id", 348]]
(9.5ms) commit transaction
(0.5ms) SELECT COUNT(*) FROM "microposts" WHERE (user_id IN (SELECT followed_id FROM relationships
WHERE follower_id = 1)
OR user_id = 1)
Micropost Load (1.3ms) SELECT "microposts".* FROM "microposts" WHERE (user_id IN (SELECT followed_id FROM relationships
WHERE follower_id = 1)
OR user_id = 1) ORDER BY "microposts"."created_at" DESC LIMIT 30 OFFSET 0
CACHE...
Rendered microposts/_micropost.html.erb (50.9ms)
Rendered shared/_feed.html.erb (65.8ms)
Rendered microposts/destroy.js.erb (71.0ms)
Completed 200 OK in 99ms (Views: 75.6ms | ActiveRecord: 18.9ms)

rails has_many through undefined method `body' for

I have models
class Riskfactor < ActiveRecord::Base
has_many :bodies_riskfactors
has_many :bodies, through: :bodies_riskfactors
end
class Body < ActiveRecord::Base
has_many :bodies_riskfactors
has_many :riskfactors, through: :bodies_riskfactors
end
class DisordersArticle < ActiveRecord::Base
belongs_to :disorder
belongs_to :article
end
in view
= form_for [:admin, #riskfactor], html: {role: "form"} do |f|
= f.select :body_ids, Body.all.collect {|x| [x.name, x.id]}, {}, :multiple => true
and I have error on update
What could be wrong?
Processing by Admin::RiskfactorsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"CVkdBHLzLAeQ8FRFBVyonUuyn1FZAYG+X9fX/mmj+Bo=", "riskfactor"=>{"body_ids"=>["", "1"], "position"=>"1", "slug"=>"risk-factor-2", "name_ru"=>"High Blood Pressure", "published_ru"=>"no", "content_ru"=>"", "meta_description_ru"=>"", "meta_keywords_ru"=>"", "name_en"=>"High Blood Pressure", "published_en"=>"no", "content_en"=>"High Blood Pressure High Blood Pressure High Blood Pressure High Blood Pressure High Blood Pressure", "meta_description_en"=>"", "meta_keywords_en"=>""}, "button"=>"", "id"=>"4"}
User Load (0.3ms) SELECT users.* FROM users WHERE users.id = 1 ORDER BY users.id ASC LIMIT 1
Riskfactor Load (0.3ms) SELECT riskfactors.* FROM riskfactors WHERE riskfactors.id = 4 LIMIT 1
(0.1ms) BEGIN
Body Load (0.3ms) SELECT bodies.* FROM bodies WHERE bodies.id = 1 ORDER BY position LIMIT 1
Body Load (2.6ms) SELECT bodies.* FROM bodies INNER JOIN bodies_riskfactors ON bodies.id = bodies_riskfactors.body_id WHERE bodies_riskfactors.riskfactor_id = 4 ORDER BY position
Riskfactor::Translation Load (0.3ms) SELECT riskfactor_translations.* FROM riskfactor_translations WHERE riskfactor_translations.riskfactor_id = 4
Riskfactor Exists (0.6ms) SELECT 1 AS one FROM riskfactors WHERE (riskfactors.slug = 'risk-factor-2' AND riskfactors.id != 4) LIMIT 1
(0.2ms) ROLLBACK
Completed 500 Internal Server Error in 15ms
NoMethodError (undefined method body' for #<Riskfactor:0x007f9a0351c350>):
app/controllers/admin/riskfactors_controller.rb:45:inblock in update'
app/controllers/admin/riskfactors_controller.rb:44:in `update'
RiskfactorsController
class Admin::RiskfactorsController < Admin::BaseController
before_action :set_riskfactor, only: [:show, :edit, :update, :destroy]
def update
respond_to do |format|
if #riskfactor.update(riskfactor_params)
format.html { redirect_to [:edit, :admin, #riskfactor], notice: 'Riskfactor was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #riskfactor.errors, status: :unprocessable_entity }
end
end
end
private
def set_riskfactor
#riskfactor = Riskfactor.find(params[:id])
end
def riskfactor_params
params.require(:riskfactor).permit!
end
end
Imho the problem is that you have body_ids in your view, but you named you association as bodies. Try to rename body_ids to bodies_ids or something like that.

Not sure where this error is being thrown (acts-as-taggable-on tagged field)

So I'm making a blog and am trying to use acts_as_taggable_oneach entryfor a :category, :subcategory and :topic. The entry model belongs_to :user and acts_as_ordered_taggable/acts_as_ordered_taggable_on :category, :subcategory,.
In entries_controller.rb update is:
#entry = Entry.find_by_id(params[:id])
if #entry.update_attributes(params[:entry])
redirect_to entries_path
else
render "edit"
end
When I submit an edit to the entry I get this error:
> NoMethodError Exception: undefined method `each' for "test_category":String
In this situation the String 'test_category' is the value of what I edited :category to be.
Is this something to do with acts_as_taggable_on?
entry.rb
class Entry < ActiveRecord::Base
belongs_to :user
# Paperclip
has_many :attached_assets, :dependent => :destroy
accepts_nested_attributes_for :attached_assets, :allow_destroy => true
# Acts_As_Taggable
acts_as_ordered_taggable
acts_as_ordered_taggable_on :category, :subcategory, :topic
validates_presence_of :title, :subtitle, :category, :post, :subcategory, :topic
attr_accessible :title, :subtitle, :category_list, :post, :subcategory_list, :topic_list, :asset, :asset_file_name, :asset_type, :entry_id
delegate :title?, :subtitle?, :category?, :post?, :subcategory?, :topic?, :to => :user
before_save :to_l
private
def to_l
self.category.downcase
end
end
entries_controller.rb
class EntriesController < ApplicationController
before_filter :authenticate_action
def index
#entries = Entry.order("created_at desc")
end
def new
#entry = Entry.new
end
def show
#entry = Entry.find_by_id(params[:id])
end
def create
#entry = Entry.new(params[:entry])
if #entry.save
redirect_to entries_path
else
render "new"
end
end
def edit
#entry = Entry.find_by_id(params[:id])
end
def update
#entry = Entry.find_by_id(params[:id])
debugger
if #entry.update_attributes(params[:entry])
redirect_to entries_path
else
puts #entry.errors.messages.inspect
render "edit"
end
end
def destroy
#entry = Entry.find_by_id(params[:id])
#entry.destroy
redirect_to entries_path, :notice => "#{#entry.title} has been deleted"
end
end
WEBrick output
> /Users/kyle/Projects/blog/app/controllers/entries_controller.rb:33
> if #entry.update_attributes(params[:entry])
> (rdb:135)
> {:category=>["can't be blank"], :subcategory=>["can't be blank"], :topic=>["can't be blank"]}
> Started PUT "/entries/4" for 127.0.0.1 at 2012-07-19 11:29:43 -0500
> Processing by EntriesController#update as HTML
> Parameters: {"utf8"=>"✓", "authenticity_token"=>"47zbADuuFS3xC5RFc6nLR7qUnE2bn1MZoNm0IwESCcI=", "entry"=>{"title"=>"Test 4", "subtitle"=>"Just Kidding!", "category_list"=>"test_category new", "subcategory_list"=>"test_subcategory new", "topic_list"=>"test_topic new", "post"=>"I pulled a George Lucas, sploops! \r\n\r\njfk;dajgk;dasjkgl;dasczcvzcVzcxv"}, "commit"=>"Update Entry", "id"=>"4"}
> User Load (0.6ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 2]]
> Entry Load (1.1ms) SELECT "entries".* FROM "entries" WHERE "entries"."id" = 4 LIMIT 1
> (0.2ms) BEGIN
> ActsAsTaggableOn::Tag Load (0.7ms) SELECT "tags".* FROM "tags" INNER JOIN "taggings" ON "tags"."id" = "taggings"."tag_id" WHERE "taggings"."taggable_id" = 4 AND "taggings"."taggable_type" = 'Entry' AND (taggings.context = 'category' AND taggings.tagger_id IS NULL) ORDER BY taggings.id
> ActsAsTaggableOn::Tag Load (0.9ms) SELECT "tags".* FROM "tags" INNER JOIN "taggings" ON "tags"."id" = "taggings"."tag_id" WHERE "taggings"."taggable_id" = 4 AND "taggings"."taggable_type" = 'Entry' AND (taggings.context = 'subcategory' AND taggings.tagger_id IS NULL) ORDER BY taggings.id
> ActsAsTaggableOn::Tag Load (1.1ms) SELECT "tags".* FROM "tags" INNER JOIN "taggings" ON "tags"."id" = "taggings"."tag_id" WHERE "taggings"."taggable_id" = 4 AND "taggings"."taggable_type" = 'Entry' AND (taggings.context = 'topic' AND taggings.tagger_id IS NULL) ORDER BY taggings.id
> ActsAsTaggableOn::Tag Load (0.7ms) SELECT "tags".* FROM "tags" INNER JOIN "taggings" ON "tags"."id" = "taggings"."tag_id" WHERE "taggings"."taggable_id" = 4 AND "taggings"."taggable_type" = 'Entry' AND (taggings.context = 'category') ORDER BY taggings.id
> ActsAsTaggableOn::Tag Load (0.8ms) SELECT "tags".* FROM "tags" INNER JOIN "taggings" ON "tags"."id" = "taggings"."tag_id" WHERE "taggings"."taggable_id" = 4 AND "taggings"."taggable_type" = 'Entry' AND (taggings.context = 'subcategory') ORDER BY taggings.id
> ActsAsTaggableOn::Tag Load (0.7ms) SELECT "tags".* FROM "tags" INNER JOIN "taggings" ON "tags"."id" = "taggings"."tag_id" WHERE "taggings"."taggable_id" = 4 AND "taggings"."taggable_type" = 'Entry' AND (taggings.context = 'topic') ORDER BY taggings.id
> (0.2ms) ROLLBACK
> Rendered entries/_form.html.haml (49.3ms)
> Rendered entries/edit.html.haml within layouts/application (53.0ms)
> Completed 200 OK in 9380ms (Views: 91.8ms | ActiveRecord: 6.9ms)
Okay, I got things working.
First, I replaced the occurrences of :category, :subcategory and :topic with :category_list, :subcategory_list and :topic_list in validates_presence_of and attr_accessible.
** WARNING: acts-as-taggable-on still needs to have acts-as-[ordered-]taggable and acts-as-[ordered-]taggable-on :attr to be the original columns (i.e. :category, :subcategory and :topic) to function properly!
Did you catch WARNING: above? Good.
Then I went to my _form.html.haml and replaced the attributes :category, :subcategory and :topic for my f.text_field's with :category_list, :subcategory_list, and :topic_list.
That's it! Things are working smoooothly now!
Also, just for reference, I configured acts-as-taggable-on in application.rb with:
ActsAsTaggableOn.delimiter = ' ' # use space as delimiter
ActsAsTaggableOn.remove_unused_tags = true
ActsAsTaggableOn.force_lowercase = true
Update
I decided that the much less complicated way to do things would be to have a single attribute called :tags for my ...tags, rather than having three separate fields to have 'act as taggable'. So, here's what I've done since answering this post:
Drop Un-needed Tables
kyle-/blog: rails g migration RemoveCategoryFromEntry category:string
invoke active_record
create db/migrate/20120719214435_remove_category_from_entry.rb
kyle-/blog: rake db:migrate
== RemoveCategoryFromEntry: migrating ========================================
-- remove_column(:entries, :category)
-> 0.0141s
== RemoveCategoryFromEntry: migrated (0.0143s) ===============================
kyle-/blog: rails g migration RemoveSubcategoryFromEntry subcategory:string
invoke active_record
create db/migrate/20120719214845_remove_subcategory_from_entry.rb
kyle-/blog: rake db:migrate
== RemoveSubcategoryFromEntry: migrating =====================================
-- remove_column(:entries, :subcategory)
-> 0.0024s
== RemoveSubcategoryFromEntry: migrated (0.0025s) ============================
kyle-/blog: rails g migration RemoveTopicFromEntry topic:string
invoke active_record
create db/migrate/20120719214922_remove_topic_from_entry.rb
kyle-/blog: rake db:migrate
== RemoveTopicFromEntry: migrating ===========================================
-- remove_column(:entries, :topic)
-> 0.0020s
== RemoveTopicFromEntry: migrated (0.0021s) ==================================
kyle-/blog: rails g migration AddTagsToEntry tags:string
invoke active_record
create db/migrate/20120719215013_add_tags_to_entry.rb
kyle-/blog: rake db:migrate
== AddTagsToEntry: migrating =================================================
-- add_column(:entries, :tags, :string)
-> 0.0039s
== AddTagsToEntry: migrated (0.0040s) ========================================
entry.rb
class Entry < ActiveRecord::Base
belongs_to :user
# Paperclip
has_many :attached_assets, :dependent => :destroy
accepts_nested_attributes_for :attached_assets, :allow_destroy => true
# Acts_As_Taggable
acts_as_ordered_taggable
acts_as_ordered_taggable_on :tags
validates_presence_of :title, :subtitle, :post, :tag_list
attr_accessible :title, :subtitle, :tag_list, :post, :asset, :asset_file_name, :asset_type, :entry_id
delegate :title?, :subtitle?, :tags?, :post?, :to => :user
end
entries/_form.html.haml
- if #entry.errors
- #entry.errors.messages.each do |message|
= message
= form_for #entry, :url => entry_path, :html => {:multipart => true} do |f|
= f.label :title, "Title"
= f.text_field :title
%br
= f.label :subtitle, "Subtitle"
= f.text_field :subtitle
%br
= f.label :tag_list, "Tags"
= f.text_field :tag_list
%br
= f.label :asset
= f.file_field :asset, :html => {:multiple => true, :name => "entry[attached_assets_attributes][][assset]"}
%br
= f.label :post, "Post"
= f.text_area :post
%br
= f.submit
entries/show.html.haml
%h1= #entry.title
%h2= #entry.subtitle
%h3= #entry.tag_list
%h4= #entry.updated_at
%entry
= #entry.post
= link_to "Back", entries_path
= render "disqus"
entries#create
def create
#entry = Entry.new(params[:entry])
if #entry.save
redirect_to entry_path(#entry), :notice => '#{#entry.title} has been created'
else
puts #entry.errors.messages.inspect
render 'new'
end
end
application.rb changes
I've removed ActsAsTaggableOn.delimiter = ' ' and ActsAsTaggableOn.remove_unused_tags = true as I decided I wanted to use commas as delimiters after all and because acts-as-taggable-on was removing tags that I was testing with.
# acts-as-taggable-on
ActsAsTaggableOn.force_lowercase = true

Resources