I am using activeadmin and it has formtastic built in as many of you who use it know. I have a model called Project that has a many to many association with ProjectResources.
My custom "edit" and "creation" form in active admin for Project looks like so.
form do |f|
f.inputs "Project" do
f.input :name, :input_html => { :readonly => true }
end
f.inputs "Resources" do
f.input :id, :label => "Selected Resources",
:as => :check_boxes,
:multiple => true,
:collection => ProjectResource.all,
:selected => #resources
end
f.buttons
end
My checkboxes render just fine and I don't get any errors at this point. The problem if you may have guessed is that when rendering the "edit" page I would like to show items in the checkbox area as "selected" if the Project has a ProjectResource as an association already.
Right now the checkboxes all show a deselected state. I am using the latest version of activeadmin and formtastic has the following versions installed. (2.2.0, 2.1.1, 2.1.0, 2.0.2, 1.2.4)
Not sure what version activeadmin uses at this point. My guess is the latest version.
For me, simple:
ActiveAdmin.register Subscription do
form do |f|
f.inputs do
f.input :users, as: :check_boxes
# other fields...
end
f.buttons
end
end
just works.
More Code:
-User class
class User < ActiveRecord::Base
has_and_belongs_to_many :users
attr_accessible :fields...
end
-Subscription Class
class Subscription < ActiveRecord::Base
has_and_belongs_to_many :subscriptions
attr_accessible :fields...
end
PS I am using ActiveAdmin 0.4.2 and Formtastic 2.0.2.
Related
I came back to the relatively "old book" Head First rails, which was published for Rails 2.3.
Now, going back again through those samples and using Rails 3 I came up with some questions.
Let's say that I'm adapting the sample for coconut airways and instead of flights and seats, I have a project and tasks.
The page shows a project description and below a list of tasks associated to that project. so far so good. now below that there is a form to create new task. This task needs a Task object and the project_id. here is when things do not work as before.
if you want to do it like the old style you will type:
<%= render :partial => "new_task",
:locals => {:task => Task.new(#project.id)} %>
well, this is showing the mass-assign error.
Then I tried to pass both as parameter:
<%= render :partial => "new_task",
:locals => {:task => Task.new, :project_id => #project.id} %>
and assign it in the partial
<%= f.hidden_field :project_id, :value => project_id %>
any hint?
EDITED:
class Task < ActiveRecord::Base
belongs_to :project
attr_accessible :title
end
class Project < ActiveRecord::Base
has_many :tasks
attr_accessible :description, :title
end
If you change your model's attr_accessible you can include these assignments to be made. For more information about attr_accessible and mass assignment see: Ruby on Rails API
I'm working on a rails (3.7.8) app and using active admin to manage resources for the ff models:
class AdminUser < ActiveRecord::Base
has_many :user_article_categories, :include => :article_categories
has_many :article_categories, :through => :user_article_categories,
:source => :admin_user
has_many :articles, :through => :user_article_categories,
:source => :admin_user
# ...
end
class UserArticleCategory < ActiveRecord::Base
belongs_to :admin_user
belongs_to :article_category
attr_accessible :admin_user_id, :article_category_id, :included
attr_accessor :included
after_find :set_included
private
def set_included
self.included = "1"
end
# ...
end
the "included" attribute was based on a solution presented here
class ArticleCategory < ActiveRecord::Base
has_many :user_article_categories, :include => :admin_users
has_many :admin_users, :through => :user_article_categories,
:source => :article_category
has_many :articles, :through => :user_article_categories,
:source => :article_category
# ...
end
but I seem not to get setting up (correctly) a form for admin_users, such that creating a new admin_user would have all article_categories displayed as a list of checkboxes
while a persisted admin_user for update would have all article_categories checkboxes displayed but wit all previously set article-categories checked, so that an update would remove unchecked checkboxes and add newly checked ones to what goes to the join-table
for admin/admin_users.rb I create the form as follows, this does not work, though it renders correctly, any help will be appreciated
form do |f|
if f.object.persisted? and current_admin_user.id == f.object.id
f.inputs "Admin Details" do
f.input :email
f.inputs :for => user_article_categories do |usr_art_catr|
usr_art_catr.input :article_category_id, :hidden
usr_art_catr.input :included
end
end
else
f.inputs "Admin Details" do
f.input :email
f.input :superuser, :label => "Super User Priveleges"
f.input :article_categories, :as => :check_boxes,
:collection => ArticleCategory.select("id, name")
end
end
f.buttons
end
Actually, to display a list of checkboxes of all article_categories and check all already checked article categories for a given admin_user on update.
Formtastic, when rendering the show form for the form's object, calls a method provided on the form object via
f.input :method_to_be_called, :as => :checkboxes
which formtastic would compare its result with a collection provided via
the
:collection => any_valid_ruby_object
but both should return the same kinds; array/array or hash/hash, whatever, to determine which checkboxes should be checked, by performing a difference on the two collections.
The method called by formtastic could be an instance method on admin_user that queries the join-table, to determine which checkboxes should be checked and builds an array of that from the related article_categories table or returns an empty array when there is none.
This allows formtastic do what is right, as least in this context. This solution makes the "included" attribute on user_article_categories (the join-table) redundant!
I'm trying to set up a polymorphic association for photo uploads which are processed using Carrierwave. I'm using Simple Form to build my forms. I feel like the association is correct so I'm wondering if my problem is just something with the form or controller.
Here are my associations:
property.rb:
class Property < ActiveRecord::Base
attr_accessible :image
...
has_many :image, :as => :attachable
...
end
unit.rb
class Unit < ActiveRecord::Base
attr_accessible :image
...
has_many :image, :as => :attachable
end
image.rb
class Image < ActiveRecord::Base
belongs_to :attachable, :polymorphic => true
mount_uploader :image, PhotoUploader
end
properties_controller.rb:
def edit
#property = Property.find params[:id]
#property.image.build if #property.image.empty?
end
def update
#property = Property.find params[:id]
if #property.update_attributes params[:property]
redirect_to admin_properties_path, :notice => 'The property has been successfully updated.'
else
render "edit"
end
end
Snippet from properties/_form.html.erb
<%= f.input :image, :label => 'Image:', :as => :file %>
Here is the error I get when submitting with an image attached:
undefined method `each' for #<ActionDispatch::Http::UploadedFile:0x00000102291bb8>
And here are the params:
{"utf8"=>"✓",
"_method"=>"put",
"authenticity_token"=>"lvB7EMdc7juip3gBZD3XhCLyiv1Vwq/hIFdb6f1MtIA=",
"property"=>{"name"=>"Delaware Woods",
"address"=>"",
"city"=>"",
"state"=>"",
"postal_code"=>"",
"description"=>"2 bedroom with large kitchen. Garage available",
"incentives"=>"",
"active"=>"1",
"feature_ids"=>[""],
"user_ids"=>[""],
"image"=>#<ActionDispatch::Http::UploadedFile:0x00000102291bb8 #original_filename="wallpaper-4331.jpg",
#content_type="image/jpeg",
#headers="Content-Disposition: form-data; name=\"property[image]\"; filename=\"wallpaper-4331.jpg\"\r\nContent-Type: image/jpeg\r\n",
#tempfile=#<File:/tmp/RackMultipart20120608-3102-13f3pyv>>},
"commit"=>"Update Property",
"id"=>"18"}
I'm looking everywhere for help on polymorphic associations and am getting nowhere. I've seen simple examples that look pretty straight forward. One thing I've noticed is that it seems like in a lot of the examples the has_many association in my case should be images and not image. However when I do that I get an error:
Can't mass-assign protected attributes: image
I've tried updating my form to use fields_for as I've seen in other blogs like so:
<%= f.input :image, :label => "Photo", :as => :file %>
<% f.simple_fields_for :images do |images_form| %>
<%= images_form.input :id, :as => :hidden %>
<%= images_form.input :attachable_id, :as => :hidden %>
<%= images_form.input :attachable_type, :as => :hidden %>
<%= images_form.input :image, :as => :file %>
<% end %>
All I know is I'm having a heck of a time getting this to work. I'm pretty new to Rails so even debugging it is difficult. It doesn't help that the debugger doesn't really work in 3.2 :(
Since your models have_many :images (it should be :images, not :image), you'll want to use nested_forms in your views. You should set up accepts_nested_attributes_for :images on the unit and property models and change the attr_accessible from :image to :image_attributes.
Check out http://railscasts.com/episodes/196-nested-model-form-part-1 for a good guide on getting going with it.
I'm using ActiveAdmin (0.4.0) with Rails (3.1.1).
I can't find a nice way/hack to handle multiple nested resources.
Considerer 3 models as:
class Program < ActiveRecord::Base
has_many :knowledges, :dependent => :destroy
end
class Knowledge < ActiveRecord::Base
belongs_to :program
has_many :steps, :dependent => :destroy
end
class Step < ActiveRecord::Base
belongs_to :knowledge
end
And the ActiveAdmin resources:
ActiveAdmin.register Program do
end
ActiveAdmin.register Knowledge do
belongs_to :program
end
ActiveAdmin.register Step do
belongs_to :knowledge
end
In routes.rb:
namespace :admin do
resources :programs do
resources :knowledges do
resources :steps
end
end
end
Here's the urls for the index of the programs, the knowledges and the steps :
http://localhost:3000/admin/programs
http://localhost:3000/admin/programs/1/knowledges
http://localhost:3000/admin/programs/1/knowledges/1/steps
No problem for the "Knowledge" admin but the "Step" admin don't keep the nested context.
For example, when I use filters in steps#index I'm redirected to:
http://localhost:3000/admin/knowledges/1/steps?params...
But it must have been:
http://localhost:3000/admin/programs/1/knowledges/1/steps?params...
Same problem when I create a new resource:
http://localhost:3000/admin/knowledges/1/steps/new
Instead of:
http://localhost:3000/admin/programs/1/knowledges/1/steps/new
Same problem with the breadcrumb... etc...
What I've tried so far in app/admin/steps.rb:
ActiveAdmin.register Step do
belongs_to :knowledge
config.clear_action_items!
action_item :only => :index do
link_to('Create Step', new_admin_program_knowledge_step_path(knowledge.program.id, knowledge.id))
end
index do
column :id
column :knowledge
column :title
column "Actions" do |step|
link_to("Voir", admin_program_knowledge_step_path(step.knowledge.program, step.knowledge, step), :class => "member_link show_link") +\
link_to("Editer", edit_admin_program_knowledge_step_path(step.knowledge.program, step.knowledge, step), :class => "edit_knowledge member_link edit_link", :id => "knowledge_#{dom_id(knowledge)}") +\
link_to("Supprimer", admin_program_knowledge_step_path(step.knowledge.program, step.knowledge, step), :class => "member_link delete_link", :method => :delete, :confirm => "Delete?")
end
end
filter :id
filter :title
filter :subtitle
filter :stage_type
filter :order_by
filter :created_at
filter :updated_at
form :partial => "form"
end
And in app/views/admin/steps/_form.html.erb I must use the activeadmin formbuilder:
<%= semantic_form_for(resource, :url => admin_program_knowledge_steps_path(resource.knowledge.program, resource.knowledge), :builder => ActiveAdmin::FormBuilder) do |f|
f.inputs "Step" do
f.input :knowledge, :as => :hidden
f.form_buffers.last << f.template.content_tag(:li, f.template.content_tag(:label, "Knowledge")+f.template.content_tag(:p, f.object.knowledge.title))
f.input :title
f.input :order_by
end
f.buttons
end %>
Well... I'm stuck.
How to handle this nicely? Any clues appreciated...
Well, the solution is pretty simple...
https://github.com/josevalim/inherited_resources
ActiveAdmin.register Step do
controller do
nested_belongs_to :program, :knowledge
end
end
Does anyone know if it is possible (and, if so, what the syntax is) for using a nested resource with the best_in_place gem?
My routes.rb looks something like this
resources :users do
resources :goals
end
I would like to edit the :description field of the goal, but the code in my view for
<%= best_in_place [#user, #goal], :description %>
gives a NoMethodError saying
undefined method `description' for #<Array:0x20e0d28>
Using
<%= best_in_place #goal, :description %>
give me an undefined method error also because there is no goal_path
I can get the gem to work for #user (the non nested resource) field without problems.
I'm running Rails 3.1.1, Ruby 1.9.2, best_in_place 1.0.4
I figured it out.
I needed to set the path option in the call like so
<%= best_in_place #goal, :description, :path => user_goal_path %>
It works like a champ now!
Add path and the objects to the path:
<%= best_in_place #goal, :description, :path => user_goal_path(#user,#goal) %>
Somehow the simple path solution of bknoles didn't work for me.
Now above method is deprecated.
According to latest Documentation use ":url" instead of ":path" like below in the example
<%= best_in_place #goal, :description, :url => user_goal_path %>
Cheers!
Thank you, #bknoles. Your answer definitely helped me reach a similar solution of my own. Here's my implementation:
#widget.rb
class Widget < ActiveRecord::Base
validates_presence_of :name
has_many :gadgets
attr_accessible :name, :description
end
#gadget.rb
class Gadget < ActiveRecord::Base
belongs_to :widget
attr_accessible :name, :widget_id, :id
end
#gadgets_controller.rb
def update
#gadget=#widget.gadgets.find(params[:id])
if #gadget.update_attributes(params[:gadget])
respond_to do |format|
format.html
format.json { respond_with_bip(#gadget) }
end
else
respond_to do |format|
format.html { render :action => "edit" }
format.json { respond_with_bip(#gadget) }
end
end
end
#views/gadgets/_gadget.html.haml
%tr{ :name => "gadget_", :id => gadget.id }
%td= gadget.created_at.localtime.strftime("%B %d, %l:%M%p")
%td.big=best_in_place gadget, :name, :path => [#widget, gadget]
%td.delete{:style => 'text-align:center;'}
=check_box_tag "gadget_ids[]", gadget.id, false, :class => "checkbox"
You can checkout the entire project on github if you want to see more of the code.
https://github.com/hernamesbarbara/ajax-rails-full-crud
Best,
Austin