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.
Related
We inherited a rails project (the whole thing is based on elasticsearch). Thus, the application lists all the documents meeting the provided search criteria by a user. Imagine a facet or so, once you've selected i.e. a specific range of dates it gives you the documents that were created at that time.
We have been currently working on expanding its functionality accordingly:
Our priority is to utilize the elastic query such that all
matched documents by that query could be multiply altered (in
our case, we've been trying to hide all the documents). Then we want to send the query to appropriate rake task that would take care of it.
After the button responsible for mass hiding is clicked the controller's create method gets called, thereby creating a mass_hiding record in database (for convenience we keep a track of hidings which would allow us to revert the mass action afterwards).
def create
mh = current_user.mass_hidings.build(params[:mass_hiding])
mh.save!
mass_hide(mh.query_params)
redirect_to search_documents_path(mass_hide.search_parameters)
end
def mass_hide(query)
search = factic.create_restrictions_search(MultiJson.load(query.to_json))
Resque.enqueue(Document::Jobs::HideDocuments, nil, search.to_scrollable.build_query)
end
However, the line 3 of the create method mass_hide(mh.query_params) triggers the following exception once it gets executed:
ArgumentError in Admin::MassHidingsController#create
wrong number of arguments (0 for 1)
Full trace can be found here.
Parameters:
{"utf8"=>"✓",
"authenticity_token"=>"6mZvRcp4HJuoBWMRToA2gPec9Wv8T82hiTJQ/STf1j/sDhQ+16mBW3QkRmhqlJIHKR0kvX/kqwQh205hp6RuDg==",
"mass_hiding"=>{"serialized_query_params"=>"{}",
"description"=>"test"},
"commit"=>"Hide documents"}
Further, here is the schema representation of mass_hiding as well as the appropriate model:
schema.rb
create_table "mass_hidings", force: :cascade do |t|
t.integer "user_id"
t.text "serialized_query_params"
t.string "description"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
mass_hiding.rb
class MassHiding < ActiveRecord::Base
attr_accessible :serialized_query_params, :description
belongs_to :user
def query_params=(params)
self.serialized_query_params = Oj.dump(params)
end
def query_params
Oj.load(self.serialized_query_params).with_indifferent_access
end
def self.find_or_initialize_by_user_and_query_params(user, query_params)
self.find_or_initialize_by_user_id_and_serialized_query_params(user.id, Oj.dump(query_params))
end
end
Thank you for your help in advance.
The problem is that you have defined this helper function:
def mass_hide(query)
But you are calling it with zero arguments.
First you call it with one argument, when you say mass_hide(mh.query_params). That's fine.
But then on the next line you also say mass_hide.search_parameters. To Ruby that means mass_hide().search_parameters. Perhaps you meant to write mh.search_parameters? I'm not sure. But mass_hide is the method that wants 1 param, and that's the callsite where you pass it 0.
I hope that helps!
I'm retroactively writing ActiveRecord migrations inside a quirky, legacy Rails app that did not follow convention so well.
The models already exist, but were not made with a generator so the tables and everything in the past were set up by hand.
I'm changing that, and I made a migration to start (I'm also switching db behind the app from MS SQL Server to Postgres).
The migration looks like this:
class CreateSuite < ActiveRecord::Migration
def change
create_table :suites do |t|
t.string :name
t.string :owner
t.string :resource_dependencies
t.datetime :requested_time
t.datetime :finished_time
t.string :status
...
end
end
end
The application, which we'll say is called foo is set as an active_record.table_name_prefix in the application.rb:
config.active_record.table_name_prefix = 'foo_'
After the migration, I want a table that is named 'suites' but instead I get 'foo_suites'. I do not want to change the prefix in application.rb since it's there for a reason (the application needs another table called 'foo_suites' but I'm going to tackle that with another migration file.)
How do I make this ActiveRecord::Migration create 'suites' instead of 'foo_suites'?
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)
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):
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!