I have a basic file upload with carrierwave:
uploaders/image_uploader.rb:
class ImageUploader < CarrierWave::Uploader::Base
include CarrierWave::RMagick
storage :file
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
end
models/event.rb:
class Event < ActiveRecord::Base
...
mount_uploader :picture, ImageUploader
end
I can upload an image with a form in the app (not the admin part) and it works fine. I see the image path in the picture field in ActiveAdmin.
But I cannot change the picture field directly in ActiveAdmin. I tried to create a new event with an image, or change an existing event. If an image was present, it stayed the same. If there were no image previously, no image were added. In short, I can view the picture field in ActiveAdmin, but I cannot change it. This is the case only for the picture field (I can change the other fields)
Note: No upload starts when I submit the form (I don't see the uploading xx% in the bottom left of chrome). I also tried other browers, same behaviour. I get no errors in the rails server console.
admin/events.rb:
ActiveAdmin.register Event do
permit_params :user_id, :category_id, :name, :date, :description, :text, :picture
# tried adding this, form still works, but image still doesn't work.
form multipart: true do |f|
f.inputs "Event details" do
f.input :category_id
f.input :name
f.input :description
f.input :picture, as: :file
end
f.actions
end
end
Why can't I change the picture field in ActiveAdmin ?
The problem was the same as in this question: File upload with Activeadmin Rails using paperclip
Changing admin/events.rb to this made the upload work:
ActiveAdmin.register Event do
permit_params :user_id, :category_id, :name, :date, :description, :text, :picture
form :html => { :enctype => "multipart/form-data" } do |f| # <--- changed
f.inputs "Event details" do
...
end
f.actions
end
end
Issue #3577 was open for this on GitHub and a PR was merged earlier today.
Related
I'm using the sign-up and login that we built with the rails tutorial as a base for a Reddit clone that I’m making. As it stands the application is functioning properly apart from the user_id in comments table is blank when I make a comment, the link_id is present and correct so I can make comments on a link. The user_id in links table is also present and correct.
I'm fairly certain that the error i've made is in the create action of comments_controller.rb but it could also be my original migration. What's confusing me (as a novice) is I had this working in it's current form once before with rails 4.1.8 and device. However, using this approach with rails 4.2.1 using the rails tutorial as a base, it doesn't work. I'm a bit new here so I hope i've formulated the post correctly and given enough information so somebody could give me some pointers as to the problem
Comment Controller
before_action :logged_in_user, only: [:create, :destroy]
def create
#link = Link.find(params[:link_id])
#comment = #link.comments.create(params[:comment].permit(:link_id, :body))
#comment.user = User.find(current_user.id)
redirect_to link_path(#link)
end
def destroy
#link = Link.find(params[:link_id])
#comment = #link.comments.find(params[:id])
#comment.destroy
redirect_to link_path(#link)
end
private
def logged_in_user
unless logged_in?
flash[:danger] = "Please log in."
redirect_to login_url
end
end
Form
app/views/links/show.html.erb
<h2 class="comment-count"><%= pluralize(#link.comments.count, "comment") %></h2>
<%= render #link.comments %>
<%= form_for([#link, #link.comments.build]) do |f| %>
<%= render 'comments/fields', f: f %>
<%= f.submit "Save Comment", class: 'btn btn-primary margin-bottom-10' %>
<% end %>
Partials
app/views/comments/_comment.html.erb
<p class="comment_body"><%= comment.body %></p>
<p class="comment_time"><%= time_ago_in_words(comment.created_at) %> Ago </p>
app/views/comments/_fields.html.erb
<%= render 'shared/comment_error_messages' %>
<%= f.label :body %>
<%= f.text_area :body, class: 'form-control' %>
Routes
config/routes.rb
resources :links do
member do
put "like", to: "links#upvote"
put "dislike", to: "links#downvote"
end
resources :comments
end
Models
app/models/link.rb
belongs_to :user
has_many :comments, dependent: :destroy
app/models/comment.rb
belongs_to :user
belongs_to :link
validates :body, presence: true
app/models/user.rb
has_many :links, dependent: :destroy
Migration
class CreateComments < ActiveRecord::Migration
def change
create_table :comments do |t|
t.integer :link_id
t.text :body
t.references :user, index: true, foreign_key: true
t.timestamps null: false
end
add_index :comments, :link_id
end
end
Hopefully that’s a good enough post and I’ve included everything you need so somebody can help me out, It's a rookie error but i can't see it. thanks in advance.
Regards
As it stands, you are currently creating a comment without saving user_id for it. Try the below code
#comments_controller.rb
def create
#link = Link.find(params[:link_id])
#comment = #link.comments.new(params[:comment].permit(:link_id, :body))
#comment.user = User.find(current_user.id)
#comment.save
redirect_to link_path(#link)
end
I have a Rails 4 app using Active Admin 1.0.0.pre1 in conjunction with pundit 0.3.0 for authorization which has worked flawlessly thus far, but I'm having trouble figuring out a good way automatically customize forms based on a user's role.
Given these models:
ActiveAdmin.register AdminUser do
permit_params do
Pundit.policy(current_admin_user, resource).permitted_attributes
end
form do |f|
f.inputs "Admin Details" do
f.input :role, as: :select, collection: [:manager, :admin]
f.input :email, as: :email
f.input :password
f.input :password_confirmation
end
f.actions
end
end
class AdminUserPolicy < ApplicationPolicy
def permitted_attributes
attributes = [:email, :password, :password_confirmation]
attributes += [:role] if user.has_role? :super_admin
attributes
end
end
I'd like for the role input to be automatically removed from the form.
One option would be something along the lines of:
permitted_attributes = Pundit.policy(current_admin_user, resource).permitted_attributes
form do |f|
f.inputs "Admin Details" do
f.input :role if permitted_attributes.include? :role
f.input :email
f.input :password
f.input :password_confirmation
end
f.actions
end
but, that approach requires the developer to remember which attributes should be checked, seems prone to forgetfulness and isn't exactly DRY. Perhaps, I am going about this the wrong way? All suggestions welcome.
Intercepting ActiveAdminForm by prepending a module that overrides input with a check against the Pundit policy seems to work well. Here is the implementation I went with:
# /lib/active_admin/permitted_active_admin_form.rb
module PermittedActiveAdminForm
def permitted_attributes
policy = Pundit.policy(current_admin_user, resource)
policy.respond_to?(:permitted_attributes) ? policy.permitted_attributes : []
end
def input(*args)
super(*args) if permitted_attributes.include? args[0]
end
end
# /config/initializers/active_admin.rb
module ActiveAdmin
module Views
class ActiveAdminForm < FormtasticProxy
prepend PermittedActiveAdminForm
end
end
end
# /app/admin/admin_user.rb
ActiveAdmin.register AdminUser do
permit_params do
resource ||= AdminUser
Pundit.policy(current_admin_user, resource).permitted_attributes
end
form do |f|
f.inputs "Admin Details" do
f.input :role, as: :select, collection: [:manager, :admin]
f.input :email, as: :email
f.input :password
f.input :password_confirmation
end
f.actions
end
end
Thanks to Andrey Deineko for starting me down the right path.
I know pundit, not active_admin. With that in mind, using the code you provided, I'll just throw an idea out there.
whitelist = Pundit.policy(current_admin_user, resource).permitted_attributes
fields = %i( role email password password_confirmation )
form do |f|
f.inputs "Admin Details" do
(fields & whitelist).each do |field|
f.input field
end
end
f.actions
end
I am creating a website using a rails and I would like to share the model. I followed The tutorial for creating an article. In the ArticlesController is index, show, new, edit, create, update and destroy. I figured I would use this as the data entry part of my app. Then I was going to create a PageController that has home, news, videos, music and events. Here is my set up:
here is my Article model
class Article < ActiveRecord::Base
has_attached_file :image, styles: { large:"700x700>", medium:"300x300>", thumb:"150x150#"}
validates_attachment_content_type :image, content_type: /\Aimage\/.*\Z/
validates :title, presence: true,
length: { minimum: 5 }
belongs_to :page
end
here is my page model
class Page < ActiveRecord::Base
has_many :article
end
here is my page controller
class PageController < ApplicationController
def home
#page = Page.includes(:articles)
end
def news
end
def videos
end
def music
end
def events
end
end
here is my home view
<h1>Page#home</h1>
<p>Find me in app/views/page/home.html.erb</p>
<%= #page.articles.each do |article| %>
<%= article.title %>
<%= article.content %>
<%= article.image %>
<% end %>
here is the error I get
undefined method `articles' for #<ActiveRecord::Relation []>
not clear onwhats going on. Any help would be appreciated
From the limited information you posted, I am assuming the best thing for you to do is create an association. Pages should has_many articles and articles should belong_to a page. http://guides.rubyonrails.org/association_basics.html
After that is setup, your controller can be set up as follows:
#page = Page.includes(:articles)
This will load your pages and its related articles in a single SQL query, then you can call
#page.articles.each |article|
puts article.title
puts article.content
puts article.image
end
You can now access all the information and use it as you please.
I can't understand why permit_params wont work with custom create action.
For example lets take basic AdminUser resource.
By default all is working fine. We have:
ActiveAdmin.register AdminUser do
permit_params :email, :password, :password_confirmation
form do |f|
f.inputs "Admin Details" do
f.input :email
f.input :password
f.input :password_confirmation
end
f.actions
end
end
But as soon we add custom create for some reasons permit_params wont work anymore.
ActiveAdmin.register AdminUser do
permit_params :email, :password, :password_confirmation
form do |f|
f.inputs "Admin Details" do
f.input :email
f.input :password
f.input :password_confirmation
end
f.actions
end
controller do
def create
AdminUser.create(params[:admin_user])
do_some_magic_stuff_here
redirect_to backend_admin_users_path, notice: 'Custom create'
end
end
end
I got error "ActiveModel::ForbiddenAttributesError" in line "AdminUser.create(params[:admin_user])"
Tried many possible solutions and only one worked for me, but i really don't like this:
def create
AdminUser.create(params[:admin_user].permit(:email, :password, :password_confirmation))
do_some_magic_stuff_here
redirect_to admin_admin_users_path, notice: 'Custom create'
end
I can't understand why i can't get to work default way as it should work:
def admin_user_params
params.require(:admin_user).permit(:email, :password, :password_confirmation)
end
Can someone explain me please what is happening here? Any nice way to have custom actions work with permit_params?
permit_params is just part of the AA DSL that defines a method called permitted_params, which in turn is called from the create and update actions. Try this:
permit_params :email, :password, :password_confirmation
controller do
def create
#admin_user = AdminUser.create(permitted_params)
do_some_magic_stuff_here
redirect_to backend_admin_users_path, notice: "Custom create"
end
end
permit_params is really just a simpler form of the old, but still valid way of enabling strong parameters:
controller do
def permitted_params
params.permit admin_user: [:email, :password, :password_confirmation]
end
end
Been struggling with the same problem here. The most strange thing is that it works on nitrous.io box but on my production server it doesn't. I've checked and I'm using the same rails 4.2.0 version.
Regards
Fak
I have two associated models in my Rails 4 app: product.rb and image.rb. The Image model allows attached files using the Paperclip gem.
Images belong_to a Product, and a product has_many Images.
I would like to use the Product's new view to create and attach an image when I create a product. Each time I try, the parameters associated with the Paperclip image do not get saved, and end up nil.
Here are the models:
Product.rb
class Product < ActiveRecord::Base
validates :name, :part_number, presence: true
has_many :images, dependent: :destroy
belongs_to :category
accepts_nested_attributes_for :images, allow_destroy: true
end
Image.rb
class Image < ActiveRecord::Base
belongs_to :product
has_attached_file :image
end
Looking through past Stack Overflow questions I've found some relevant questions and answers, but none that seem to help my particular situation. So far I'm able to submit the file with the correct attributes, but it doesn't save them to the database.
ProductsController#create
def create
#product = Product.new(product_params)
end
def product_params
params.require(:product).permit(:name,
:category_id,
:part_number,
images_attributes: [:image])
end
ProductsController#new
def new
#product = Product.new
#categories = # irrelevant to question
end
products/new.html.haml
= form_for #product, :html =>
= f.label :name
= f.text_field :name
= f.label :part_number
= f.text_field :part_number
= f.label :category_id
= f.select :category_id, #ca
= f.fields_for :image do |ff|
= ff.label :image
= ff.file_field :image
= f.submit('Create Product')
Looking at the parameters I can tell that the correct attributes are being passed on:
Example parameters:
{"utf8"=>"✓",
"authenticity_token"=>"jGNy/TasHzP0EcWDFzZ3XH5/fpxb6vD+ncQ2PZSQ3/I=",
"product"=>{"name"=>"bar",
"part_number"=>"foo",
"category_id"=>"30",
"image"=>{
"image"=>#<ActionDispatch::Http::UploadedFile:0x007fc82f58e0e0
#tempfile=#<Tempfile:/var/folders/04/23d9grkj5fv3wkj2t8858kx40000gn/T/RackMultipart20131029-64949-1ldkz4g>,
#original_filename="FPE230_b.jpg",
#content_type="image/jpeg",
#headers="Content-Disposition: form-data; name=\"product[image][image]\"; filename=\"FPE230_b.jpg\"\r\nContent-Type: image/jpeg\r\n">}},
"commit"=>"Create Product"}
However, the image is not actually being saved to the database. How can I rectify this?
EDIT
Looking more closely at the logs, I see that I'm getting an "unpermitted parameters: image" error. This is even after adding images_attributes: [:image] to my product_params method.
I was able to get a setup similar to yours working with the following changes:
In ProductsController#create, instead of building the image separately, let the nested attributes handle it and just do:
#product = Product.new(product_params)
And allow the nested parameters (I figured out the image_attributes: [:image] from this question):
def product_params
params.require(:product).permit(:name, :part_number, images_attributes: [:image])
end
This is what my parameters look like in the logs for a create request:
{
"utf8"=>"✓",
"authenticity_token"=>"7EsPTNXu127itgp4fbohu672/L4XnSwLEkrqUGec3pY=",
"product"=>{
"name"=>"whatever",
"part_number"=>"12345",
"images_attributes"=>{
"0"=>{
"image"=>#<ActionDispatch::Http::UploadedFile:0x007feb0c183b08
#tempfile=#<Tempfile:/var/folders/6k/16k80dds0ddd6mhvs5zryh3r0000gn/T/RackMultipart20131031-51205-emaijs>,
#original_filename="some-image.png",
#content_type="image/png",
#headers="Content-Disposition: form-data; name=\"product[images_attributes][0][image]\"; filename=\"ponysay.png\"\r\nContent-Type: image/png\r\n">
}
}
},
"commit"=>"Create"}
And I see an insert into products and an insert into images.
If that doesn't work, could you post your ProductsController#new and your new product form?
EDIT AFTER YOUR EDIT:
I have 3 different things in my app/views/products/new.html.erb and ProductsController#new that might be affecting your results:
In the form_for, I have multipart: true as in the paperclip documentation:
<%= form_for #product, :url => products_path, :html => { :multipart => true } do |f| %>
Because Product has_many :images, in my form I have fields_for :images instead of fields_for :image:
<%= f.fields_for :images do |i| %>
<%= i.file_field :image %>
<% end %>
This fields_for doesn't show anything on the page unless in the ProductsController#new I build an image; does your Product.new do this by any chance?
def new
#product = Product.new
#product.images.build
end
Are there any particular reasons for these differences you have? Does your code work if you change it to match mine?