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/
Related
this is based on some dev.to articles here https://dev.to/diegocasmo/using-postgres-enum-type-in-rails-30mo
and here https://dev.to/amplifr/postgres-enums-with-rails-4ld0
and the same guy's article here https://medium.com/#diegocasmo/using-postgres-enum-type-in-rails-799db99117ff
If you follow the advice above, you are advised to create a Rails schema migration for your Postgres backed schema by using CREATE TYPE xyz_setting AS ENUM directly on Postgres, and then use that to create your new field as an ENUM (a postgres enum)
Unfortunately, this approach has the downside of breaking the db/schema.rb file.
I think the problem is that the native Postgres types are not supported by the Rails core.
I can reproduce the behavior on Rails 5.17, 5.2.2.4, and 6.0.3
if I do...
class AddXyzToUsers < ActiveRecord::Migration[5.2]
def up
execute <<-DDL
CREATE TYPE xyz_setting AS ENUM (
'apple', 'bananna', 'cherry'
);
DDL
add_column :users, :xyz, :xyz_setting
end
def down
remove_column :users, :xyz
execute "DROP type xyz_setting;"
end
end
then my schema file is messed up, specifically, the schema users table doesn't get output whatseover, and instead in its place is this message
Could not dump table "users" because of following StandardError
Unknown type 'xyz_setting' for column 'xyz'
Custom enum types in PostgreSQL (Rails 7+)
Rails 7 added support for custom enum types in PostgreSQL.
So now, a migration can be written as follows:
# db/migrate/20131220144913_create_articles.rb
def up
create_enum :article_status, ["draft", "published"]
create_table :articles do |t|
t.enum :status, enum_type: :article_status, default: "draft", null: false
end
end
# There's no built in support for dropping enums, but you can do it manually.
# You should first drop any table that depends on them.
def down
drop_table :articles
execute <<-SQL
DROP TYPE article_status;
SQL
end
It is also worth mentioning, when you use create_enum, the enum definitions and enum columns will be presented in schema.rb.
Sources:
Pull Request.
Rails Guides.
Rails API.
Rails 7 adds better support for custom enum types in PostgreSQL by Saeloun.
Rails doesn't support custom PG types out of the box.
As stated by Diego Castillo you can use a sql schema which will handle those types.
However, if you want to keep using a ruby schema there's activerecord-postgres_enum, a gem that provides support for PostgreSQL enum data types.
In Rails 7 if you are using PostgreSQL you can now do:
rails generate model Post title:string body:text post_type:enum
Your migration can be like:
class CreatePosts < ActiveRecord::Migration[7.0]
def change
create_enum :post_option, ["draft", "private", "published"]
create_table :posts do |t|
t.string :title
t.text :body
t.enum :post_type, enum_type: "post_option", default: "draft", null: false
t.timestamps
end
add_index :posts, :post_type
end
end
Your schema would look like:
ActiveRecord::Schema[7.0].define(version: 2022_06_04_221707) do
...
create_enum "post_option", ["draft", "private", "published"]
...
create_table "posts", force: :cascade do |t|
t.string "title", default: ""
t.text "body", default: ""
t.enum "post_type", default: "draft", null: false, enum_type: "post_option"
t.string "image", default: ""
t.index ["post_type"], name: "index_posts_on_post_type"
end
end
Then, on your model you need to add:
enum :post_type, draft: "draft", private: "private", published: "published"
For Rails 7 Postgres enum support is now built-in
I like #crysicia's answer a lot but to be more precise for the next developer, for Rails 6 you have the choice of either:
using activerecord-postgres_enum
SWITCHING your Rails app to SQL schema (assuming you are using the native Rails schema at db/schema.rb) which instead produces db/structure.sql and will write your schema in native SQL of course.
The #2 approach is frowned upon by the Rails-DB separation purists, of course, but as-is this entire implementation anyway since I don't know of other Dbs that support the enum anyway (there may be).
So basically if you want to keep db/schema.rb I'd recommend using the activerecord-postgres_enum gem
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.
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)
I'm writing a little Ruby on Rails CMS, and I want to make a generator that would create models inheriting from the pre-built CMS data model. For example, I have a Entry model in my CMS, and I want to create a Post model that would be child of this model. This is the source code:
db/migrations/*create_mycms_entries.rb:
class CreateMyCmsEntries < ActiveRecord::Migration[5.0]
def change
create_table :my_cms_entries do |t|
t.string :type, index: true
t.string :title
t.string :slug, index: true
t.json :payload
t.integer :user_id, index: true
t.string :author_name
t.datetime :published_at
t.timestamps null: false
end
end
end
entry.rb:
module MyCms
class Entry < ActiveRecord::Base
scope :published, -> { where('published_at <= ?', Time.zone.now) }
def self.content_attr(attr_name, attr_type = :string)
content_attributes[attr_name] = attr_type
define_method(attr_name) do
self.payload ||= {}
self.payload[attr_name.to_s]
end
define_method('#{attr_name}='.to_sym) do |value|
self.payload ||= {}
self.payload[attr_name.to_s] = value
end
end
def self.content_attributes
#content_attributes ||= {}
end
end
end
and, at my blog side, post.rb:
class Post < MyCms::Entry
content_attrs :body, :text
# Rest of the stuff...
end
I want the final command look something like this:
$ rails generate entry Post body:text
But I'm not quite sure I know how to implement it.
If you want to create custom model generator then you can use Thor (https://github.com/erikhuda/thor) which rails team has documented here
http://guides.rubyonrails.org/generators.html
First start by typing this command:
bin/rails g generator entry
So you are triggering generator to generate generator :). You will get something like this after running your command
create lib/generators/entry
create lib/generators/entry/entry_generator.rb
create lib/generators/entry/USAGE
create lib/generators/entry/templates
Then what you can do is just copy the code that ActiveRecord has for creating models. Inside your templates you will have this file model.rb like here
https://github.com/rails/rails/blob/master/activerecord/lib/rails/generators/active_record/model/templates/model.rb
You will see that it has something like this:
class <%= class_name %> < <%= parent_class_name.classify %>
class_name is a variable that you pass to your generator, like in your example Post. And you can define it like this inside your entry_generator
argument :class_name, type: :string, default: "Post"
I would definitely recommend that you look at this file since the rails generator has everything you need...you would just customize it for your specific need:
https://github.com/rails/rails/blob/master/activerecord/lib/rails/generators/active_record/model/model_generator.rb
In generator you have a class that invokes the template. Here is another video from Ryan Bytes that explains creating generator on custom layout which you can find it useful for your CMS.
http://railscasts.com/episodes/218-making-generators-in-rails-3?view=asciicast
Good luck
What you are trying to do is single-table inheritance (STI) and Rails has the support for that. Basically you need column type in your entries table which would store the class name within your hierarchy. You don't need to use the parent attribute as it seems to be in your example. See more in Rails docs or blogs, e.g. this one.
Hi I'm new at programming but I try to make my own service
I'm using cloud9 Ide, ruby on rails and sqlite3
Anyway I'll parse data of a dictionary and I'm about to design database like this(just for example)
[col-1] [col-2] [col-3]
[row-1] fruit apple [a,p,p,l,e]
[row-2] fruit kiwi [k,i,w,i]
...
[row-50] flower lily [l,i,l,y]
[row-51] flower rose [r,o,s,e]
...
3 column and thousands of rows
To give you more details, when an user types "fruit" in text area I want to show word list from "apple" to "kiwi"!!
I learned about storing 'string' that only users submit like this
class CreateFans < ActiveRecord::Migration
def change
create_table :fans do |t|
t.string :username
t.timestamps null: false
end
end
end
But I really don't know how to store my own data
I want to know how to add column and rows and storing local data, not user input!
Actually, I studied yesterday reading .xlsx file and show in ruby on rails through gem 'roo' but I don't know how to use this properly in database. and I want to know there is alternatives...
Thanks for reading my question and I appreciate if you give me advices :)
You can add columns to databases with migrations.
The columns don't have to be only from user input.
for example you could have a migration...
class CreateMyWord < ActiveRecord::Migration
def change
create_table :my_words do |t|
t.string :genre
t.string :word
t.string :letters
t.timestamps null: false
end
end
end
When you define your model you specify that the attribute letters is actually an array...
class MyWord < ActiveRecord::Base
serialize :letters
end
serialize will automatically convert an array to a string representation when storing the record, and will automatically convert it back when retrieving the record.
You can then populate the table yourself in your seeds.db file which you can execute with the command rake db:seed
the seeds db would possibly look like...
my_initial_words = [
['fruit', 'apple', ['a','p','p','l','e'],
['fruit', 'kiwi', ['k','i', 'w', 'i'],
...
]
my_iniital_words.each do |word_data|
MyWord.create(genre: word_data[0], word: word_data[1], letters: word_data[2])
end
Note that if the letters of the word always match the word, you don't really need a column letters in the database, just have a method in the model that creates the letters array for you when you need it.
class MyWord < ActiveRecord::Base
def letters
word.split('')
end
end