Rails comments gem Acts_as_commentable on pins - ruby-on-rails-4

I have a rails app where users can upload pins, I want to use the [acts_as_commentable_gem][1] to allow users to comment pins, here is my config:
app/models/pin.rb
class Pin < ActiveRecord::Base
acts_as_commentable
end
app/controlers/pins_controller.rb
def show
#pin.find params[:id]
#comment = #pin.comments.new
end
app/views/pins/show.html.erb
<%= form_tag "/pins/add_new_comment" do %>
<%= hidden_field_tag "id", post.id %>
<%= text_area_tag "comment[comment]" %>
<%= submit_tag "Pin Comment" %>
<% end %>
app/models/comment.rb
class Comment < ActiveRecord::Base
include ActsAsCommentable::Comment
belongs_to :commentable, :polymorphic => true
default_scope -> { order('created_at ASC') }
# NOTE: install the acts_as_votable plugin if you
# want user to vote on the quality of comments.
#acts_as_voteable
# NOTE: Comments belong to a user
belongs_to :user
end
app/controllers/pin_controller.rb
def add_new_comment
pin = Pin.find(params[:id])
pin.comments << Pin.new(params[:comment])
redirect_to :action => :show, :id => pin
end
finally in my config/routes
get "/pins/add_new_comment" => "pins#add_new_comment", :as => "add_new_comment_to_pins", :via => [:pin]
But I run to a routing error:
undefined local variable or method `acts_as_commentable' for PinsController:Class
I am really not sure where this error come from, any ideas?

I am not really sure but you route shouldn't be like
get "/pins/:id/add_new_comment" => "pins#add_new_comment", :as => "add_new_comment_to_pins"

Related

rails: param.require(:model) ActionController::ParameterMissing OR Empty

My goal is to create a new Reminder record with hardcoded values:
In the following structure:
Reminder belongs_to :deck
Deck has_one :reminder, dependent: :destroy
In deck controller I get to the view like this :
def repitition_alerts
#deck = Deck.find(params[:id])
#reminder = Reminder.new
end
On that page I want to create a new Reminder with a link_to:
<%= link_to "make alerts", deck_reminders_path(#deck, #reminder, {:action => :create}, next_alert: 'soon', interval: false), :method => :post %>
I am getting the following error in the browser:
ActionController::ParameterMissing in RemindersController#create
From terminal output:
ActionController::ParameterMissing (param is missing or the value is empty: reminder):
app/controllers/reminders_controller.rb:34:in `reminder_params'
app/controllers/reminders_controller.rb:19:in `create'
In the reminders_controller.rb I have:
def reminder_params
params.require(:reminder).permit(:deck_id, :interval, :next_alert, :alerts)
end
If I understand it correctly. Rails don't see the #reminder passed into it? But it's in the page. I can put this on the same page <%= #reminder %> and I see #<Reminder:0x007fc012fa00a8> rendered out on the page. So the object itself exists.
(Rails 4.2)
You need the params for reminder nested under :reminder. Switch your link_to to this:
<%= link_to "make alerts", deck_reminders_path(
#deck,
#reminder,
{:action => :create},
reminder: {
next_alert: 'soon',
interval: false
}
), :method => :post %>

customizing devise routes for sign in and sign up

I have the sign-up and sign-in form on the same page and want any sign-up and sign-in errors such as 'email already exists' to appear on this page. I've customised the Registrations controller using this solution and also created a custom DeviseFailure class so errors on sign in redirect back to this page.
I have 2 questions:
If the sign up fails due to an error in the form (e.g. entering an email address that has already been registered) and then I try to sign in I get an
Internal Server Error - inGET, accepted HTTP methods are OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT, PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, UNLOCK, VERSION-CONTROL, REPORT, CHECKOUT, CHECKIN, UNCHECKOUT, MKWORKSPACE, UPDATE, LABEL, MERGE, BASELINE-CONTROL, MKACTIVITY, ORDERPATCH, ACL, SEARCH, MKCALENDAR, and PATCH.
If I then reload the redirect occurs correctly. I dont know how to address this error.
How do I trap errors just for the sign in form or just for the sign up form? Currently the errors are displaying twice - once for each form.
routes.rb
authenticated :user do
root 'preorders#by_campaign', as: :authenticated_root
end
root to: 'users#index'
devise_for :users, :controllers => { :sessions => "sessions",
:passwords => "passwords",
:registrations => "registrations" }
application_controller.rb
def after_sign_in_path_for(resource)
preorders_by_campaign_url
end
def after_sign_out_path_for(resource)
root_url
end
registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
protected
def after_sign_up_path_for(resource)
after_sign_in_path_for(resource)
end
def create
build_resource(sign_up_params)
if resource.save
yield resource if block_given?
if resource.active_for_authentication?
set_flash_message :notice, :signed_up if is_flashing_format?
sign_up(resource_name, resource)
respond_with resource, location: after_sign_up_path_for(resource)
else
set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_flashing_format?
expire_data_after_sign_in!
respond_with resource, location: after_inactive_sign_up_path_for(resource)
end
else
clean_up_passwords resource
resource.errors.full_messages.each {|x| flash[x] = x} # Rails 4 simple way
redirect_to root_path
end
end
end
index.rb
.user_form
%h2 Sign up
= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f|
= render partial: "errors", locals: {flash: flash}
%div
= f.label :email
= f.email_field :email
%div
= f.label :password
= f.password_field :password
%div
= f.label :password_confirmation
= f.password_field :password_confirmation
%div= f.submit "Sign up"
.user_form
%p Already signed up? Sign in
= form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f|
= render partial: "errors", locals: {flash: flash}
%div
= f.label :email
= f.email_field :email
%div
= f.label :password
= f.password_field :password
%div= f.submit "Sign in"
_errors.html.haml
-if flash.any?
%ul{class: "errors"}
- flash.each do |msg|
%li=msg.first

Kaminari paginate at different controller mixing with devise (check answer)

I have 2 non nested models, User and Record. The goal is to paginate the #user.records called #records at users/show
Here is the Record part:
at app/models/record.rb
class Record < ActiveRecord::Base
default_scope lambda { order('records.created_at DESC') }
paginates_per 48
end
I am using Kaminari at records/index and works great. Problem is to use it at users/show
Here the app/controllers/users_controller.rb
def show
#user = User.find(params[:id])
#records = #user.records.page params([:page])
# Not working alternative:
# #records = #user.records.page(params[:page]).per(48)
end
Here is the view that triggers the display, is the listing rendered inside users/show...
<% #records.each do |record| %>
<%= link_to (image_tag record.thumbnail.url(:list)), record %>
<%= link_to record.name, record %>
<% end %>
<%= paginate #records %>
Errors are very interesting. As it is, error is:
No route matches {:action=>"show", :controller=>"users", :controllers=>{"registrations"=>:registrations}, :id=>"1", :page=>nil}
Meaning paginate #records is building a request to Active Record that hopes to find an action I do not have in that controller (I am using devise). So at Kaminari instructions says is possible to pass the params, like this:
<%= paginate #records, :params => { :controller => 'foo', :action => 'bar' }, :remote => true %>
Then the error becomes like this:
No route matches {:action=>"remote_records_pagination", :controller=>"records", :controllers=>{"registrations"=>:registrations}, :id=>"1", :page=>nil}
I have a remote_recors_pagination defined at records_controller, renders records_paginate_remotely.js, but the pagination method does not find it. Why it keeps showing :controllers registrations?
Finally, to change the view like this:
<%= paginate #user.records %>
<% #user.records.each do |record| %>
<%= link_to (image_tag record.thumbnail.url(:list)), record %>
<%= link_to record.name, record %>
<% end %>
<% end %>
Produces an undefined method error.
Should not the example be working with or without js file? Any help?
Thanks.
I found a solution. I am posting an answer because the problem was on routes and the mix with devise, common combo that more people may find.
So, routes was like this:
devise_for :users
resources :users, only: :show, , :controllers => { :registrations => :registrations } do
member do
get :following, :followers
end
end
To change it to this:
devise_for :users, :controllers => { :registrations => :registrations }
resources :users, only: :show do
member do
get :following, :followers
end
end
allows the paginate command interact with Active Record normally. Devise first test seems ok.

Polymorphic has-many-through accepts_nested_attributes_for error

I have a problem with my following setup. It is a polymorphic n:m association between the feature, page and slide model. the join model is the slideshow model.
feature.rb - a model in a refinerycms extension
module Refinery
module MyExtension
class Feature < Refinery::Core::BaseModel
# associations
has_many :slideshows, :as => :slideable, :class_name => "::Refinery::MyExtension::Slideshow"
has_many :slides, :through => :slideshows, :class_name => "::Refinery::MyExtension::Slide"
accepts_nested_attributes_for :slides, :allow_destroy => :false
end
end
end
page_decorator.rb - a decorator for the refinery page model
Refinery::Page.class_eval do
# associations
has_many :slideshows, :as => :slideable, :class_name => "Refinery::MyExtension::Slideshow"
has_many :slides, :through => :slideshows, :class_name => "Refinery::MyExtension::Slideshow"
end
slide.rb - a model in a refinerycms extension
module Refinery
module MyExtension
class Slide < Refinery::Core::BaseModel
# associations
has_many :slideshows, :class_name => "::Refinery::MyExtension::Slideshow"
has_many :pages, :through => :slideshows, :source => :slideable, :source_type => "::Refinery::Page"
has_many :features, :through => :slideshows, :source => :slideable, :source_type => "::Refinery::MyExtension::Feature"
end
end
end
slideshow.rb - a model in a refinerycms extension
module Refinery
module MyExtension
class Slideshow < Refinery::Core::BaseModel
# associations
belongs_to :slide, :class_name => "::Refinery::MyExtension::Slide"
belongs_to :slideable, :polymorphic => true
accepts_nested_attributes_for :slide, :allow_destroy => :false
end
end
end
I think the associations are correct, but I have a problem creating new slides within the feature#form.
feature-form:
<%= form_for [refinery, :my_extension_admin, #feature] do |f| -%>
<%= f.text_field :field1 %>
<%= f.text_field :field2 %>
<%= "some-more-fields..." %>
<% slideshows = #feature.slideshows.empty? ? #feature.slideshows.build : #feature.slideshows %>
<%= f.fields_for(:slideshows, slideshows) do |slideshow_form| %>
<%= slideshow_form.hidden_field :position, :value => 0 %>
<% slide = slideshow_form.object.slide.nil? ? slideshow_form.object.build_slide : slideshow_form.object.slide %>
<%= slideshow_form.fields_for(:slide, slide) do |slide_form| %>
<%= slide_form.text_field :a_field -%>
<%= slide_form.text_field :another_field -%>
<% end %>
<% end %>
<% end %>
If I hit "save" I get following error:
::Refinery::MyExtension::Slideshow(#70206105711540) expected, got Array(#70206014033940)
My params hash looks as following:
{"utf8"=>"✓", "authenticity_token"=>"my-token", "switch_locale"=>"de", "feature"=>{"field1"=>"a value", "field2"=>"some value", "slideshows"=>{"position"=>"0", "slide_attributes"=>{"a_field"=>"some value", "another_field"=>"some value"}}}, "action"=>"create", "controller"=>"refinery/my_extension/admin/features", "locale"=>:de}
My controller looks as following:
module Refinery
module MyExtension
module Admin
class FeaturesController < ::Refinery::AdminController
crudify :'refinery/my_extension/feature', :title_attribute => 'name', :xhr_paging => true
def feature_params
params.require(:feature).permit(:field1, :field2, :slideshows => [:position, :slide => [:a_field, :anothter_field]])
end
end
end
end
end
I use Rails 4.1.5 and refinerycms. But I think it has nothing to do with refinerycms, just with normal Rails behavior.
I already took a look at following resources:
ActiveRecord::AssociationTypeMismatch when attempting to save nested attributes in Rails
Has Many Through Association Polymorphic Error
accepts_nested_attributes_for with has_many => :through Options
Anybody an idea what I am missing?
try to create method "new" something like this
def new
#feature = ::Refinery::MyExtension::Feature.new
#feature.slideshows.build
end
and edit method
def edit
#feature = ::Refinery::MyExtension::Feature.find(params[:id])
#feature.slideshows.build
end

Nested attributes using paperclip rails 4

I am new to rails and I am trying to work with nested attributes.
The main idea is to have a a deal(offer) model, a deal will have multiple deal_photos from paperclip.
I have already watched Ryan's Railscast for nested forms and read many articles with many tips regarding problems on the same issue but still it doesn't work for me.
Here is my Implementation:
class Deal < ActiveRecord::Base
belongs_to :user
has_many :deal_photos, dependent: :destroy
accepts_nested_attributes_for :deal_photos
end
class DealPhoto < ActiveRecord::Base
belongs_to :deal
has_attached_file :photo, :styles => { :large => "600x170", :medium => "250x250!", :thumb => "100x100>" }, :default_url => lambda { |photo| photo.instance.set_default_url}
def set_default_url
ActionController::Base.helpers.asset_path('missing.png')
end
end
In my deals controller:
class DealsController < ApplicationController
def new_deal
#deal=Deal.new()
#user= User.find(params[:id])
3.times { #deal.deal_photos.build }
end
def create
#deal = Deal.new(deal_param)
#user= User.find(params[:user_id])
if #deal.save
#user.deals << #deal
flash[:notice]="Thank you"
end
end
def edit
#deal=Deal.find(params[:deal_id])
3.times { #deal.deal_photos.build }
end
def update
#deal=Deal.find(params[:id])
if #deal.update_attributes(deal_params)
flash[:notice]="Deal updated successfully"
end
end
private
def deal_params
params.require(:deal).permit(:title, :description, :contact_num, :user_id, :deal_photos_attributes => [ :id, :caption, :photo, :deal_id])
end
Finally in my form for a new deal:
<%= form_for(:deal, :url=>{:action=>'create', :user_id=> #user.id}) do |f| %>
<label>Title<b style="color:red;">*</b>
<%= f.text_field(:title, :placeholder=>"") %>
</label>
------------more fields---------------------
<%= f.fields_for :deal_photos do |builder| %>
<div>
<%= builder.label :caption, "Image Caption" %>
<%= builder.text_field :caption %>
<%= builder.label :photo, "Image File" %>
<%= builder.file_field :photo %>
</div>
<%end%>
<%= button_tag("Create", :class=> "secondary button", :button_type => "submit") %>
(I have migrated the db for deals_photo to accept paperclip)
The above, creates a form with all fields but instead of 3 inputs for file upload shows only one. It creates 3 empty associations #deal.deal_photos but even if I choose one image to upload from the form it doesn't save it.
If you have any useful advices or another similar question please help!
What's in your deal_param method?
Do you permit deal_photos' attributes in it?
If no then do something like
def deal_params
params.require(:deal).permit(deal_attr1, deal_attr2,...., deal_photos_attributes: [:deal_photo_attr1, ...])
end
Also, do you get a deal_id in your deal_photos in view?
Finally, I was able to solve the problem in the new_deal.html.erb when I replaced the:
<%= form_for(:deal, :url=>{:action=>'create', :user_id=> #user.id}) do |f| %>
with
<%= form_for(#deal, :url=>{:action=>'create', :user_id=> #user.id}) do |f| %>
What is changed is that the second line is for the specific new deal instance. Maybe the reason that the first was not working is that the deal_photos didn't get the deal_id, as Alexphys said. But still I haven't figure out the exact reason.