Rails Admin With Dragonfly - Edit. No file present - ruby-on-rails

Using Rails Admin with Dragonfly. However when I have created a new post with an attachment connected :ob to dragonfly and wants to edit it. It sais "No file chosen". As it doesn't pick up that there is already a file present?
In my rails_admin I have done this.
edit do
field :name
field :information
field :ob, :dragonfly
field :document_categories
end
Here's my model:
class Document < ActiveRecord::Base
has_and_belongs_to_many :document_categories
after_commit :generate_versions, on: :create
dragonfly_accessor :ob
validates :name, :ob, presence: true
def generate_versions
DocumentWorker.perform_async(self.id)
end
def convertable_image?
unless self.try(:ob).nil?
self.try(:ob).mime_type.include?("image") || self.try(:ob).mime_type.include?("pdf")
else
return false
end
end
def respond_with_type
case self.try(:ob).mime_type.split("/")[1]
when "vnd.ms-powerpoint" , "vnd.openxmlformats-officedocument.presentationml.presentation", "application/vnd.openxmlformats-officedocument.presentationml.template"
"powerpoint"
when "application/vnd.ms-excel" , "vnd.openxmlformats-officedocument.spreadsheetml.sheet"
"excel"
when "application/msword" , "vnd.openxmlformats-officedocument.wordprocessingml.document"
"word"
else
self.try(:ob).mime_type.split("/")[1]
end
end
default_scope{order("name ASC")}
end
Here's my schema:
create_table "documents", force: :cascade do |t|
t.string "name"
t.string "ob"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "ob_uid"
t.string "ob_name"
t.text "information"
end
Is there anything else that I need to do in order for it to pick up the file?
https://github.com/sferik/rails_admin
https://github.com/markevans/dragonfly

I managed to reproduce your issue using the configuration you provided and the fix that worked for me turned out to be incredibly simple: just remove the ob column from the documents table.
Explanation: by default, Dragonfly stores the attached documents on disk (in a file store) to the directory specified in the Dragonfly initializer. In the database, Dragonfly stores only the name and UID of the documents. In your case it's the ob_uid and ob_name columns that you correctly added to your schema.
So, unless you configured some custom store for the documents, I assume you use the default file store and the ob column is not needed. In fact, it confuses the rails_admin's dragonfly support code in such a way that, indeed, the edit page incorrectly show "No file chosen" all the time.
Adding an image after the fix (for simplicity, I removed the document_categories association from both the model and the edit action in rails_admin):

Related

How to seed data with ActionText has_rich_text?

In my model, I have:
class Listing < ApplicationRecord
...
has_rich_text :description
...
end
In my seeds.rb:
#listing = Listing.new(
title: 'CODE VEIN',
price: 59.99 * 100,
description: "<p>#{Faker::Lorem.paragraphs(number: 30).join(' ')}</p>",
seller_id: seller.id,
release_date: Date.parse('Sep 26, 2019'),
status: :active,
esrb: 'MATURE'
)
Listing.description comes up nil, causing my NOT NULL constraint to error.
I've debugged with pry, and tried #listing.description.body= text or #listing.description.body = ActionText::Content.new(text), both still cause the listing#description to be nil.
This is an API Only project, but I use Trix RTE in the front-end react app. Is there a specific method to seed rich_text columns?
ActionText stores the actual contents in a seperate action_text_rich_texts table which uses a polymorphic assocation to link back to the model that its attached to.
# This migration comes from action_text (originally 20180528164100)
class CreateActionTextTables < ActiveRecord::Migration[6.0]
def change
create_table :action_text_rich_texts do |t|
t.string :name, null: false
t.text :body, size: :long
t.references :record, null: false, polymorphic: true, index: false
t.timestamps
t.index [ :record_type, :record_id, :name ], name: "index_action_text_rich_texts_uniqueness", unique: true
end
end
end
The JavaScript component of ActionText (which is really the whole point) automatically sends AJAX requests when the user user interacts with Trix to create/update the row in the action_text_rich_texts table even before you have saved the record you're creating.
When you then submit the form you're actually submitting the id to the row on the action_text_rich_texts table and not the contents. Then when you save your model it updates the corresponding row on action_text_rich_texts with the record_type and record_id from the model. Its a pretty awkward solution that is built around the idea of never having to add columns to your model.
I don't really see the point in using ActionText in an API as the whole point is to add a quick and dirty Trix implementation to classical rails apps. You really should be able to solve this with just a single text column instead. Especially as that will let you access the contents without joining.
There must be something else going on with your code. Maybe if you share your migration and the complete Listing class file it might be easier to spot what's going on.
Here are a few steps to make sure you got it right:
Create a brand new rails app (you can delete it later):
rails new testrichtext -d mysql --api
Create the db
cd testrichclient
rake db:create
Create the model
rails g model listing description:text
Change your newly created migration file to make sure the column is not null:
class CreateListings < ActiveRecord::Migration[6.0]
def change
create_table :listings do |t|
t.text :description, null: false
t.timestamps
end
end
end
Run the migration
rake db:migrate
Now you should be able to log in into the console, and create a new listing with something as the description:
rails c
And inside console:
l = Listing.new(description: "<p>Something nice</p>")
l.save!
Listing.first.description
As you can see, this is enough to save/seed a new listing with rich text. So anything you may have going on there should be something you're causing somewhere else, by adding a validation differently, or callbacks. Hard to say without looking at the entire file
I found this to work for me:
15.times do
Post.create!(title: Faker::Book.unique.title)
end
then
Post.all.each do |post|
ActionText::RichText.create!(record_type: 'Post', record_id: post.id, name: 'content', body: Faker::Lorem.sentence)
end
To read:
Post.first.content.body.to_plain_text
or:
Post.first.content.body.to_trix_html
...as stated above by OP.
Source:
https://linuxtut.com/rails6-input-the-initial-data-of-actiontext-using-seed-9b4f2/

ruby on rails I need to build an object from api data

I want to create an object from data API. At first, the user will have to enter his immaticulation number. Once registration typed him return the following data in the view show
vehicles_controller:
#vehicle = Vehicle.new
#vehicles = []
vehicle_number = params['immatricule'].capitalize
vehicles.each do |vehicule|
data_api = CarRegistrationFrance.Lookup(#{"vehicle_number"},"username","password")
Api_data response:
=> {"Description"=>"RENAULT CLIO IV", "RegistrationYear"=>"2017", "CarMake"=>{"CurrentTextValue"=>"RENAULT"}, "CarModel"=>{"CurrentTextValue"=>"CLIO IV"}, "EngineSize"=>{"CurrentTextValue"=>"4"}, "FuelType"=>{"CurrentTextValue"=>"DIESEL"}, "MakeDescription"=>{"CurrentTextValue"=>"RENAULT"}, "ModelDescription"=>{"CurrentTextValue"=>"CLIO IV"}, "Immobiliser"=>{"CurrentTextValue"=>""}, "IndicativeValue"=>{"CurrentTextValue"=>0}, "DriverSide"=>{"CurrentTextValue"=>""}, "BodyStyle"=>{"CurrentTextValue"=>"BERLINE 5 PORTES"}, "RegistrationDate"=>"2017-10-30","ExtendedData"=>{"anneeSortie"=>"2017", "boiteDeVitesse"=>"", "carburantVersion"=>"D", "carrosserieVersion"=>"", "classeSra"=>"K", "libVersion"=>"1.5 DCI 90 EDITION ONE EDC", "libelleModele"=>"CLIO IV", "marque"=>"RE", "modele"=>"88", "produit"=>"", "puissance"=>"4", "version"=>"", "cleCarrosserie"=>"", "groupeSra"=>"30", "nbPlace"=>"5", "datePremiereMiseCirculation"=>"30102017", "questionBatterie"=>"", "electrique"=>"", "genre"=>"", "typeVehicule"=>"", "numSerieMoteur"=>"VF15RBJ0D58888591", "valeurANeufSRA"=>"", "niveauRisqueVol"=>"", "protectionConstructeur"=>"", "puissanceDyn"=>"", "segmentVeh"=>""}}
#vehicles << data_api
vehicle.description => data_api["Description"]
vehicle.annee => data_api["RegistrationYear"]
def vehicle_params
params.require(:voiture).permit(:immatricule, :description, :annee)
end
Once the user enters his registration numbers I want to join
data_api ["Description"] << vehicle ["description"]
attach the data to the attribute of the vehicle object
data_api ["RegistrationYear"] << vehicle ["year"]
/user[:id]/vehicle/new its an example
<%= form_tag("/vehicle", method: "post") do %>
<%= label_tag(:immatricule, "") %>
<%= text_field_tag(:immatricule) %>
<%= submit_tag("create") %>
/user[:id]/vehicle/show it an example
<%= #vehicle.api_data["Description"] %>
<%= #vehicle.api_data["RegistrationYear"] %>
enter your immatricule number
post immatricule of vehicle user to api_data
create objet vehicle from response api_data
render show view
I've tried several operations but I can not find a solution.
So this sort of feels like you coming from a background without being CRUD (Create, Read, Update, Delete) aware ... based on your not listing the controllers etc that you are working to achieve this stuff (crucial to any response to answer your question).
Based on the status of the question 2/22 # 06:18am -600 here is some quick notes ...
You are going to want to do this walk-thru for getting started - RailsGuides.
Second, I think from your URL you listed - you have a nested route & are using a matching nested model. The answer changes which controller/action/routing I am suggesting - so make sure to clarify if you aren't before you try to understand this answer ...
All of these are guess work as there are details of your implementation we are missing (route.rb file, if this is a script you as admin are calling or each user is running the update themselves, if this stuff works at all).
Once finished the question you meant to ask should be ...
"Which controller & controller action should I use to update the registration information?" (Commonly shown as controller#action)
The CRUD answer is the update (rails calls it Edit to display view & update to execute).
The reason your question throwing people off is that the Rails Way (CRUD) already has basic code for a controller and action for that controller action to update the field. You shouldn't have to create an object yourself - all data objects that are permanent should be Rails model objects.
In your case Vehicle model in the app/models/vehicle.rb would be my guess. You might choose to nest the route for that in the config/routes.rb file as ...
Rails.application.routes.draw do
resources :users do
resources :vehicle
...
Which would give you a route/url of "/{:user_id}/{:vehicle_id}/{controller action}".
This assumes ...
A user coming to your application on the web or network
They sign up or in
Display the info from the API (I'm not sure if your are looking to feed this info back to that API & that is why you need the object - but assuming you are not)
After the user#show controller pulls vehicle model pulls the info from the API
Your controller will redirect them to the CRUD read action (Rails calls this Show). It's also already coded in the controller action for update.
In your case this would likely be ... User#show, which would have accepts_nested_attributes_for :RegistrationYear and maybe the :Description in the User model, referring to the fields in the Vehicle model you already have working.
For the other case ... you are simply wrapping another API which is getting updated and your rails application isn't holding anything ...
You need a user entity or authentication ... maybe you are getting an omni_auth or other security login token from the API you referenced ... so your steps ...
Either login in handled or you create/ login the user
Your User#Show should either have a link to the Vehicle#Update or the User#Show view should include that form with field with the user & vehicle id's ... which are filled in already as the the controller executed that API query pull all the information & have the two fields to be updated.
The submit button should in a normal rails app be a link to another controller#action which would just execute the API's update interface instead of stashing the info into your own db ... though you could easily put that API interface call in the controller#action responsible for showing the form.
I suggest you do a standard object file if you are just wrapping the API with your own rails app ...
# depending on where you put this you might need to load it yourself
app/lib/other_api_connection.rb
# rails prefers this format as part of ruby & it's class autoloading
class OtherAPI < CarRegistrationFrance
attr_accessor :registration, :description
def initialize(search_immat, user, pass, api_url = {whatever currently})
...
#user = user
#pass = pass
#record = look_up
#api_url = api_url
end
def look_up(search_immat)
...
Lookup("#{search_immat}", #user, #pass)
end
def update_api
begin
... {you haven't shown us the update API url} ...
rescue {some error from api}
return "{some error message}"
end
end
end
So ... you have the API handler object now ...
For use you call it in the controller#action ... lets say User#Show, which submit redirects to User#Update or Vehicle#Update
class Vehicle < ActionController::Base
...
def update
...
# normal stuff probably needs to be deleted if you aren't saving to your application db THEN updating API (aka just wrapping an API - which I'm assuming you are doing since you haven't said otherwise & it's less work).
# also you could pass the object as a parameter in the submit link - but that's not really CRUD per say
#user = {whatever user is}
api = OtherAPI.new(user, pass)
# you might have to permit this as parameter to pull it out
#response_code = api.update_api(:RegistrationYear, :Description) # or whole vehicle record if the API requires
if #response_code == {whatever valid code is from that API documentation}
format.html { redirect_to #vehicle, notice: 'Vehicle was successfully updated.' }
else
format.html { render :edit }
format.json { render json: #vehicle.errors, status: :unprocessable_entity }
end
... rest of controller actions
end
Note - I suggested making an API interface class/object because you can then call the code from either controller or action & only have to make the changes in one place if the api url is changed etc ... but you might have to include OtherAPI at the top of each controller code.
hello Thanks for your help
i using devise to authentificate user
my shemas database:
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.float "longitude"
t.float "latitude"
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.inet "current_sign_in_ip"
t.inet "last_sign_in_ip"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "username"
t.string "avatar_file_name"
t.string "avatar_content_type"
t.bigint "avatar_file_size"
t.datetime "avatar_updated_at"
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
create_table "vehicles", force: :cascade do |t|
t.string "immatricule"
t.string "description"
t.string "marque"
t.string "date_circulation"
t.string "fuel_type"
t.bigint "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["user_id"], name: "index_vehicles_on_user_id"
end
add_foreign_key "vehicles", "users"
my model users:
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable, :trackable
has_many :vehicles
my model vehicles:
class Vehicle < ApplicationRecord
belongs_to :user
end
i need this routes:
user_vehicles GET /users/:user_id/vehicles(.:format) vehicles#index
POST /users/:user_id/vehicles(.:format) vehicles#create
new_user_vehicle GET /users/:user_id/vehicles/new(.:format) vehicles#new
edit_user_vehicle GET /users/:user_id/vehicles/:id/edit(.:format) vehicles#edit
user_vehicle GET /users/:user_id/vehicles/:id(.:format) vehicles#show
PATCH /users/:user_id/vehicles/:id(.:format) vehicles#update
PUT /users/:user_id/vehicles/:id(.:format) vehicles#update
DELETE /users/:user_id/vehicles/:id(.:format) vehicles#destroy
but i'm using devise
in my controller i need to build
vehicles with response api i need to save data in my database
from number immatricule
in form new vehicles users enter number_immatricule
"immatricule" = form new vehicles[:immatricule] users
form get data_api
def build_vehicle_user_from_api_data
"description" == data_api["description"]
"marque" == data_api["CarMake"]
"date_circulation" == data_api["RegistrationDate"]
"fuel_type" == data_api["fuel_type"]
end
I'm looking for how to do that in my controller users or vehicles

Ruby on Rails 5 strong parameters

I'm having some troubles with a project I'm working on. Be warned I consider myself very much a beginner/novice at all this still :)
To keep things short and sweet, I'm using Rails & active admin to build up an admin interface where i can perform CRUD operations on my database models, which is all working great. However I recently decided I wanted to add another field to one of my models, a "description" field, so generated a migration, ran rake db:migrate and updated my list of allowed params in my controller & active admin resource.
My problem is data is not saved for this new "description" field - wether its via creating a new entry or updating an existing one. I can see the output in the terminal confirms it is being filtered out by strong params; returning Unpermitted parameter: :Description However i am under the impression i have set up my strong params correctly, so I'm unsure if i have set up my permit params properly or what else i can do.
Using Rails 5.1.0 & will post code below.
class CellsController < InheritedResources::Base
def index
end
private
def cell_params
params.require(:cell).permit(:name, :description)
end
end
#database schema for my cell model
create_table "cells", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.text "Description"
end
#Active Admin resource
ActiveAdmin.register Cell do
permit_params :name, :description
end
Again, greatly appreciate any help as I'm sure I've overlooked something, happy to provide any other information that is required :)
Thankyou!
To me it looks like the description param is not accepted because the model only has a Description column (with a capitalised D). To fix that, either change each params.permit(:description) to params.permit(:Description) or just rename the column inside a new migration:
def change
rename_column :cells, :Description, :description
end
I recommend renaming the column as it will avoid any trouble with the column in the future.

Add Rows to a SQL Table in Ruby on Rails

How do I add data to a table in Rails?
So far I have created a Rails app that pulls in data from an API. Next, I have ran the command
rails generate model order
and I have /db/migrate/timestamp_create_orders.rb
class CreateOrders < ActiveRecord::Migration
def change
create_table :orders do |t|
t.string :email, null: false
t.string :order_date, null: false
t.string :total_price, null: false
t.string :order_number, null: false
t.string :cust_name, null: false
t.string :zip_code, null: false
t.timestamps null: false
end
end
end
Next, I believe I need to run db:migrate and that will create the table.
My question is, how do I add data to this table? I want the user to visit the app, it pulls in the data, and stores it in this table.
I have found conflicting advice..
Should I just use the advice from here
Order.create(:email=>'fake#fake.com',:order_data=>"...
But other advise seems to say not to do this here and here. Though they are all pretty old
You do not create database entries in migrations, you usually create schema or specify changes in the schema in migration files. You use seeds for creating seed data in the database.
To create new data in database through rails you can use either create or new method but you need to save the data as mentioned in other posts in your links when you are using new method.
While creating or migrating a new database table, table row is not automatically added. You need to add them manually. One way to populate the newly created database table is using seeds.rb file which is located in your application db folder. You can add Faker gem to your application for creating fake table attribute elements. An example using faker:
(1..3).each do # it'll create 3 new order
Order.create(email: Faker::Internet.email, order_date: Faker::Date.between(2.days.ago, Date.today))
end
Then run rake db:seed in your project folder console.
If you have some validation in your order.rb file, then you can create new instance of that order and then save it like:
order = Order.new(....)
order.save(validate: false)

Trying to rename Devise Model name in ruby on rails

We had 2 ruby on rails apps that one was using json outputs from the other. But we decided to integrate them which ran into a lot of issues.
The issue now is, the writer of one system used to 'devise' gem for all user authentication and registration, which was fine. But when we had to integrate them it caused problems, because the other system also had a model named users, which was not used for this purpose.
And it would be A LOT easier to just rename the devise user model to something like "site-user" which im currently trying.
Than re-name the other model.
I tried renaming everything that relates to devise in all the files to siteuser instead of user but still getting errors. Anyone have any advice on this. If i can just get this devise user to use a different model name than "User" i will be able to make a lot of progress but this is proving quite the annoyance.
Current error is
NoMethodError in Devise::Sessions#new - highlighting the line with "if user_signed_in"
<li>
<%= link_to t('nav.support'), 'http://banana.sweatervest.net/' %>
</li>
<%- if user_signed_in? -%>
<%- if controller_name != 'dashboard' -%>
<li>
<%= link_to t('nav.dashboard'), :dashboard %>
Why not uninstall it and then reinstall the model.
First:
rails destroy devise User
then:
rails generate devise whateveryourmodelnamehere
Much easier than trying to rename everything, only because I've been there ;)
I actually took the long route (? 1 hour work) to rename my Devise model I had named Admin some decade ago. I wanted it to be User.
(Previous rails version 4, into my latest rails version 7, devise 4.7)
Note that you might have got yourself wrapped a lot more into the naming than I did so buyers of this solution beware! For instance I had not indexes on any of my tables (which I will do now for goodness sake). Devise itself doesn't really write the model name into stuff so it's mostly digging into your own past.
My step by step that worked for me:
I - start a new clean git branch. You will suffer unless you are able to oversee what you are doing next.
II - Renaming all cases of admin -> user. (~34 files affected)
Using search/replace (case sensitive) in my editor:
lowcases of admin -> user (also look for admins -> users that got missed)
uppercase Admin -> User
Manually rename some files like the model: admin.rb -> user.rb
III - Create some migrations to create new users table and change admin_id to user_id in those tables affected:
Take the create_table body from schema.rb and wrap that into a migration, using the new name of the devise model, mine ended up like:
class AddUsersTable < ActiveRecord::Migration[5.2]
def change
create_table :users do |t|
t.string "email", limit: 255, default: "", null: false
t.string "encrypted_password", limit: 255, default: "", null: false
t.string "reset_password_token", limit: 255
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip", limit: 255
t.string "last_sign_in_ip", limit: 255
t.datetime "created_at"
t.datetime "updated_at"
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
end
end
And next a migration to change what other tables need to update the foregin key
class RenameAdminIdsToUser < ActiveRecord::Migration[5.2]
def change
rename_column(:batches, :admin_id, :user_id)
rename_column(:offices, :admin_id, :user_id)
end
end
IV - copy data from old table to the new.
In my case I'm using postgres, but the SQL will probably work with most SQL-based DBs. Here I logged into my postgres-db and run the following sql:
INSERT INTO users (SELECT * FROM admins);
(This query can also be put in a migration which is a bit cleaner.)
V - if you are setting up a new rails like me - going from rails 5 to 7, also make sure to copy settings from devise.rb, like pepper token keys to match the data you have in your old table.
After these steps my rails app was moving on with User instead of Admin as if nothing happened!

Resources