best_in_place & model attribute accessing (noob?) - nested-attributes

I've only been learning Rails for ~a month, so I'm not sure if the answer here is really simple or more complex.
I have two models, we will call them "SpecialUser" and "User".
My User model looks something like this:
class User < ActiveRecord::Base
has_one :special_user
attr_accessible :name, :email, :password, :password_confirmation, :remember_me, :roles, :user_type, :address_1, :address_2, :city, :state, :zip
(&c.)
And my SpecialUser model looks something like this:
class SpecialUser < ActiveRecord::Base
belongs_to :user
(&c.)
We are using https://github.com/bernat/best_in_place to create a form to edit the information for the SpecialUser. Previously, we had a separate "address" attribute for the SpecialUser, but recently pulled it in favor of specifying the full address (address_1, address_2, city, state, zip...) and putting that in the user so that regular users can have addresses too. :)
However, when I try to do this:
<% # best_in_place_if can?(:edit, #super_user), #super_user.user, :address_1 %>
I get this error:
NoMethodError in Project_professionals#show
undefined method `user_path' for #<#<Class:0x0000013457fb90>:0x00000132e1fdd8>
I have also tried replacing #super_user.user with User.find(#super_user.user) and User.find(#super_user.user_id), but I get the exact same error.
When I do
<%= #super_user.user.address_1 %>
It works!
After reading through the best_in_place stuff, I'm still having trouble finding my answer. :( Not sure if it's a limitation of the gem we're using or me missing something.

best_in_place should handle it -- no limitation
See if this fixes it
:path: URL to which the updating action will be sent. If not defined
it defaults to the :object path.
<%= best_in_place_if can?(:edit, #super_user), #super_user.user, :address_1, :path => super_user_user_path %>

Related

Active Admin create additional URL on unique field

I have an object Foo which has fields id and token (both are unique, both have db indexes). I want to be able to get to Foo 1 by going to url "/admin/foos/token-of-foo-1" in addition to being able to use the url "/admin/foos/1". I know that I will need to do something like the below in my routes.rb, but I'm having trouble. Help?
ActiveAdmin.routes(self) # keep this
get 'admin/???', to: 'admin/???' # add ...something
Hmm, some thoughts:
#admin/foo.rb
controller do
def find_resource
if params[:id].length == 16 # it's a token
end_of_association_chain.find_by_token(params[:id])
else
end_of_association_chain.find(params[:id])
end
end
end
For this kind of purposes I use this gem called FriendlyID. You can select which fields should form the URL slug, in your case the field token:
class Foo < ApplicationRecord
extend FriendlyId
friendly_id :token, use: :slugged
end
Let me know if you have more doubts on how to configure. It has a great integration with Active Admin.

Rails 4.1 Nested Attributes and Fields For Getting Unpermitted Parameters and Not Saving

Research: Rails 4.0 beta, fields_for not accepting pluralized model_name in one-to-many association, Rails 4 Nested Attributes with fields_for Don't Save to Database
First, let's get the most common problem out of the way: incorrectly named attributes parameters for strong parameters. Mine is correctly plural.
class AdultsController < ApplicationController
...
def update
authorize #user
respond_to do |format|
if #user.update_attributes(user_params)
format.html { redirect_to unit_adult_path(#unit, #user), notice: "#{#user.full_name} was successfully updated." }
else
format.html { render action: 'edit' }
end
end
end
def user_params
params.require(:adult).permit(:first_name, :last_name, phones_attributes: [])
end
end
And my models are setup correctly
class User < ActiveRecord::Base
has_many :phones, dependent: :destroy
accepts_nested_attributes_for :phones, allow_destroy: true, reject_if: proc { |a| a["number"].blank? }
end
class Phone < ActiveRecord::Base
belongs_to :user, touch: true
end
And the view
# adult/_form.html.haml
= bootstrap_form_for [#unit, #user] do |f|
= f.text_field :first_name, control_col: 'col-md-4'
= f.text_field :last_name, control_col: 'col-md-4'
= f.fields_for :phones do |f_phone|
= f_phone.form_group do
= f_phone.select :kind, options_for_phones, hide_label: true, layout: :default
= f_phone.phone_field :number, hide_label: true, layout: :default
= f_phone.check_box :_destroy, label: 'remove'
But, when I submit the User form to save
Started PATCH "/units/2/adults/1" for 127.0.0.1 at 2014-07-11 15:20:17 -0700
Processing by AdultsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"pDjDVSiEs5qqHLqnbxQMeGWDOUGvhXPPvgyRGmitmps=", "adult"=>{"first_name"=>"Karl", "last_name"=>"Smith", "phones_attributes"=>{"0"=>{"kind"=>"other", "number"=>"888.1212", "_destroy"=>"0", "id"=>"173"}, "1"=>{"kind"=>"mobile", "number"=>"888.1212", "_destroy"=>"0", "id"=>"174"}} }, "commit"=>"Update Adult", "unit_id"=>"2", "id"=>"1"}
Unpermitted parameters: phones_attributes
I don't understand why the nested data is being rejected by the strong parameter evaluation. It looks correct to me.
The one thing I do notice is that the params data for "phones_attributes" value is a HASH not an ARRAY. In the user_params, phones_attributes: [] looks like it expecting an ARRAY. So I changed it to a HASH.
def user_params
params.require(:adult).permit(:first_name, :last_name, phones_attributes: {})
end
But now I get the following error.
Unpermitted parameters: 0, 1
So I tried specifying the field names in the "phones_attributes" array.
def user_params
params.require(:adult).permit(:first_name, :last_name, phones_attributes: [:id, :kind, :number])
end
And I still get.
Unpermitted parameters: phones_attributes
I know I must be missing something small, but I can't find my error.
EDIT: all my nested attributes forms do not work. Not 100% sure when they stopped, but ones that worked previously no longer work and have not been modified.
Figured this out. I was using javascript to copy the phone fields (kind, number) to make a new set of inputs available for entry. The script was adding non numeric characters to part of the field id, and this was causing rails to ignore all the submitted phone_attributes.
For the next person that comes along...
When fields_for renders out the fields, it will index each input name for uniqueness when the submitted post data is converted to params. In the example below, this number field
<input id="adult_phones_attributes_0_number" name="adult[phones_attributes][0][number]" type="tel" value="7773331111">
will look something like this when converted to params
"phones_attributes"=>{"0"=>{"number"=>"7773331111"}}
The hash key of "0" comes from the index created by fields_for. It's the "[0]" portion of the name.
In versions of rails past, if that nested attributes params hash key was not a number, the k/v pair was just ignored. Well now with strong parameters (I'm guessing the culprit), it will reject the entire "phones_attributes" hash.
My script was copying the input field, doing a regex on the html to change the "[0]" index to a random number. But sometimes it would replace it will non-digit characters. And this was causing the problem.

ActiveAdmin won't save has many and belongs to many field

I have 2 models. Category and Post. They are connected using a has_many_and_belongs_to_many relationship. I checked in the rails console and the relationship works.
I created checkboxes in activeadmin to set the post categories using this form field:
f.input :categories, as: :check_boxes, collection: Category.all
The problem is when I try to save it because every other field data (title, body, meta infos etc.) is saved, but the category stays the same even if I unchecked it, or checked another too.
I am using strong parameters like this:
post_params = params.require(:post).permit(:title,:body,:meta_keywords,:meta_description,:excerpt,:image,:categories)
Please give me some suggestions to make active admin save the categories too!
Best Wishes,
Matt
Try this in AA:
controller do
def permitted_params
params.permit post: [:title, :body, :meta_keywords, :meta_description, :excerpt, :image, category_ids: []]
end
end
Put something like this in /app/admin/post.rb:
ActiveAdmin.register Post do
permit_params :title, :body, :meta_keywords, :meta_description, :excerpt, :image, category_ids: [:id]
end
If you are using accepts_nested_attributes_for then it would look like this:
ActiveAdmin.register Post do
permit_params :title, :body, :meta_keywords, :meta_description, :excerpt, :image, categories_attributes: [:id]
end
I've tested, this might works for you and others as well
# This is to show you the form field section
form do |f|
f.inputs "Basic Information" do
f.input :categories, :multiple => true, as: :check_boxes, :collection => Category.all
end
f.actions
end
# This is the place to write the controller and you don't need to add any path in routes.rb
controller do
def update
post = Post.find(params[:id])
post.categories.delete_all
categories = params[:post][:category_ids]
categories.shift
categories.each do |category_id|
post.categories << Category.find(category_id.to_i)
end
redirect_to resource_path(post)
end
end
Remember to permit the attributes if you're using strong parameters as well (see zarazan answer above :D)
References taken from http://rails.hasbrains.org/questions/369

Make semantic_errors render the exact error-message

I have a model Camping which has_many Images. At least one image is required on Camping:
class Camping < ActiveRecord::Base
attr_accessible :images_attributes
has_many :images
validates_presence_of :images, :message => "At least one image is required"
accepts_nested_attributes_for :images, :allow_destroy => true
end
Then, in active_admin, which uses formtastic, I render the error message At least one image is required, with f.semantic_errors:
ActiveAdmin.register Camping do
form :html => { :multipart => true } do |f|
f.semantic_errors :images
#....
f.inputs "Images" do
f.has_many :images do |img|
#....
end
end
#....
end
end
This renders as:
Images At least one image is required.
How can I make it render: At least one image is required?
changing the f.semantic_errors :images into 'f.semantic_errors (removing :images) makes it render nothing; no error at all.
Note: The API documentation seems to imply that Formtastic always adds the :attribute name to the error; but I am not entirely sure how this code works.
If you want to use such custom messages you can add error messages that are related to the object’s state as a whole, instead of being related to a specific attribute
Change this
validates_presence_of :images, :message => "At least one image is required"
to something like
validate :should_have_images
def should_have_images
errors.add(:base, "At least one image is required") if images.blank?
end
If you want to use such custom messages you can add new method to Formtastic::Helpers::ErrorsHelper As follows
create new file at config/initializers/errors_helper.rb
Place following code to file
module Formtastic
module Helpers
module ErrorsHelper
def custom_errors(*args)
return nil if #object.errors.blank?
messages = #object.errors.messages.values.flatten.reject(&:blank?)
html_options = args.extract_options!
html_options[:class] ||= 'errors'
template.content_tag(:ul, html_options) do
messages.map do |message|
template.content_tag(:li, message)
end.join.html_safe
end
end
end
end
end
In activeadmin form use
f.custom_errors instead of f.semantic_errors *f.object.errors.keys

Error in the view page when I am doing updating the product

I am getting an error when I am upadting the product ,the error is coming in the view page .it is "Object reference is not set to an instance of an object".
Please tell me why is the error coming.
category_id:
<%= Html.TextBox("category_id", Model.category_id ) %>
<%= Html.ValidationMessage("category_id", "*") %>
Thankx in advance
Ritz
What product are you referring to? You need to provide more details, along with the code sample that is leading to the problem
Mainly it occurs because you would referencing an object for which an instance has not been set.
For example:
object obj = null;
obj.GetHashCode(); // will result in a object reference not set exception

Resources