Rails convention for table with just one row - ruby-on-rails

Is there any conventions of rails or a right way to create/manipulate a table that will contain just one row?
If not, what is the best way to do that?
I need a way to store configurations of the system.
Thanks.

Edited:
The rake db:seed command, basically execute whatever code you write in db/seeds.rb file of your application. Though can write any code in this file, by convention you should write code which populate your database with the basic data,
for example: when ever your deploy your application somewhere, and create a new database for it, you want that user with admin credential must be present there. So you will write the code which create that user in this file. Below is the sample code which will create a user and assign admin role to him.
puts "********Seeding Data Start************"
admin = User.create(:first_name => 'System', :last_name => 'Admin',
:email => 'systemadmin#sunpower.com', :password => 'sunpoweradmin',
:password_confirmation => 'sunpoweradmin', :source_system_id => 'systemadmin',
:source_system => 'LP',:entity_type => "Customer", :target_system => "OPENAM")
if admin.errors.blank?
puts "***User #{admin.first_name} #{admin.last_name} created ***"
admin.add_role :admin # add_role is method defined by rolify gem
puts "***admin role assigned to #{admin.first_name} #{admin.last_name}***"
else
puts "admin user failed to create due to below reasons:"
admin.errors.each do |x, y|
puts"#{x} #{y}" # x will be the field name and y will be the error on it
end
end
puts "********Seeding Data End************"
Now whenever you recreate your database, you just need to run below command to populate the database, with the basic data
$ rake db:seed RAILS_ENV=production
The correct order to setup database in production, with all the rake task available within db namespace is as below
$rake db:create RAILS_ENV=production
$rake db:migrate RAILS_ENV=production
$ rake db:seed RAILS_ENV=production
NOTE: You can replace the first two commands with $rake db:setup RAILS_ENV=production , it will run both create and migrate internally
OR
You could use the rails-settings-cached gem which is a fork of the rails-settings gem
Once setup, you'll be able to do things such as:
Setting.foo = 123
Setting.foo # returns 123
Hope this may help you or what you are looking for..

Related

Rails acts_as_tenant seed data

I'm using the gem 'acts_as_tenant' in a Rails 3 project.
I would like to seed new data every time a new Tenant is added - but only for the new Tenant.
Is there a way to pass a variable to rake db:seed?
Something like:
rake db:seed -tenant=5
Thanks for the help!
This worked:
$ TENANT=5 rake db:seed
In seed.rb:
statuscode = Statuscode.first_or_create(
:tenant_id => ENV['TENANT'],
:statuscode => 'Completed',
:closed => true
)

Figaro environment variables won't set for Heroku

I generated a skeleton application using Rails Composer and included Figaro. It runs successfully locally. Before I modify it, I am pushing it down to Heroku. However, the heroku run rake db:seed failed. I've come to find out that the app/config/application.yml is .gitignored. So, I need to use rake figaro:heroku to set the environment variables before I run heroku run rake db:seed. But, the rake Figaro:heroku is failing as follows:
D:\BitNami\rubystack-2.0.0-11\projects\myapp>rake figaro:heroku
! Usage: heroku config:set KEY1=VALUE1 [KEY2=VALUE2 ...]
! Must specify KEY and VALUE to set.
This looks like it is just ignoring my app/config/application.yml and asking for line directed input to me, but I don't know. Again, the application runs successfully locally, so that application.yml should be correct. Here it is:
MANDRILL_USERNAME: valid.address#gmail.com
MANDRILL_APIKEY: a.valid.apikey
ADMIN_NAME: Admin Name
ADMIN_EMAIL: valid.address#gmail.com
ADMIN_PASSWORD: validpassword
ROLES: [admin, user, VIP]
The failure occurs in seeds when I issue heroku run rake db:seed. The file is:
puts 'ROLES'
YAML.load(ENV['ROLES']).each do |role|
Role.find_or_create_by_name(role)
puts 'role: ' << role
end
puts 'DEFAULT USERS'
user = User.find_or_create_by_email :name => ENV['ADMIN_NAME'].dup, :email => ENV['ADMIN_EMAIL'].dup, :password => ENV['ADMIN_PASSWORD'].dup, :password_confirmation => ENV['ADMIN_PASSWORD'].dup
puts 'user: ' << user.name
user.confirm!
user.add_role :admin
It fails on the first access to variable role because ENV['ROLES'] is uninitialized. It would be initialized by application.yml, and is locally, but it is .gitignored. Thus, the need for rake Figaro:heroku to succeed.
This seems so simple, especially since it runs smoothly locally. OBTW, I have tried application.yml as shown and with the strings double-quoted but it doesn't seem to make a difference in any case so...
Ideas? Thanks...
I understand from the path you're mentioning that this is a Windows question. Problem is that the arrays are not correctly dealt with on Windows. Workaround I once made is to override the "vars" method of Heroku in a rake file in lib/tasks, like
module Figaro
module Tasks
class Heroku # < Struct.new(:app)
def vars
Figaro.env(environment).map { |key, value|
if value.start_with? "["
value = "'#{value.gsub('"', '')}'"
elsif value.include? " "
value = "'#{value}'"
end
"#{key}=#{value}"
}.sort.join(" ")
end
end
end
end
I'd surmise the problem will likely be with Figaro's processing of your different variable types:
MANDRILL_USERNAME: "valid.address#gmail.com"
MANDRILL_APIKEY: "a.valid.apikey"
ADMIN_NAME: "Admin Name"
ADMIN_EMAIL: "valid.address#gmail.com"
ADMIN_PASSWORD: "validpassword"
ROLES: ["admin", "user", "VIP"]
Try removing any spaces & ensuring you only send KEY: "VALUE" to Figaro. Your spaces are basically going to cause the system to misinterpret it

Ruby Script to create new model value

Project is the model name and I want to do something like:
Project.create(:name => 'projectname', :identifier => 'projectidentifier')
This should be done in the terminal through a ruby script. I am not going to use rails console to create it nor use seeds.rb in a db file to migrate this as rake db:seed.
Can someone help. Thanks
The easiest way would be using rails runner (which essentially loads rails):
rails runner your_script.rb
The line of code would be a content of that script.
What about a rake task?
on lib/tasks, create a file named data.rake, and the content:
namespace :data
desc "Create project data"
task create_project_data: :environment do
Project.create(name: 'projectname', identifier: 'projectidentifier')
end
end
And you can run it as any rake task
rake data:create_project_data
And it will also appear when you list your rake tasks
rake -T

FactoryGirl screws up rake db:migrate process

I am doing TDD/BDD in Ruby on Rails 3 with Rspec (2.11.0) and FactoryGirl (4.0.0). I have a factory for a Category model:
FactoryGirl.define "Category" do
factory :category do
name "Foo"
end
end
If I drop, create then migrate the database in the test enviroment I get this error:
rake aborted!
Could not find table 'categories'
This problem occurs because FactoryGirl expects the tables to already exist (for some odd reason). If I remove the spec folder from my rails app and do db:migrate, it works. Also if I mark factory-girl-rails from my Gemfile as :require => false it also works (then I have to comment that require in order to run rspec).
I found some information about this problem here: https://github.com/thoughtbot/factory_girl/issues/88
Is there something wrong that I'm doing? How can I "pass by" the FactoryGirl stage in the db:migration task?
I think you need to have factory girl definition like that in Gemfile:
gem 'factory_girl_rails', :require => false
And then you just require it in your spec_helper.rb like that:
require 'factory_girl_rails'
This is the way I'm always using this gem. You don't need to require it in other places than spec_helper.rb. Your current desired approach is just wrong.
A simple fix to this issue is to delay evaluation of any models in your factories by wrapping them in blocks. So, instead of this:
factory :cake do
name "Delicious Cake"
frosting Frosting.new(:flavor => 'chocolate')
filling Filling.new(:flavor => 'red velvet')
end
Do this (notice the curly braces):
factory :cake do
name "Delicious Cake in a box"
frosting { Frosting.new(:flavor => 'chocolate') }
filling { Filling.new(:flavor => 'red velvet') }
end
If you have a lot of factories this may not be feasible, but it is rather straightforward. See also here.
Information from: http://guides.rubyonrails.org/testing.html
When you do end up destroying your testing database (and it will happen, trust me),
you can rebuild it from scratch according to the specs defined in the development
database. You can do this by running rake db:test:prepare.
The rake db:migrate above runs any pending migrations on the development environment
and updates db/schema.rb. The rake db:test:load recreates the test database from the
current db/schema.rb. On subsequent attempts, it is a good idea to first run db:test:prepare, as it first checks for pending migrations and warns you appropriately.
rake db:test:clone Recreate the test database from the current environment’s database schema
rake db:test:clone_structure Recreate the test database from the development structure
rake db:test:load Recreate the test database from the current schema.rb
rake db:test:prepare Check for pending migrations and load the test schema
rake db:test:purge Empty the test database.
You shouldn't need to do any of that.. I think the issue is that your argument to FactoryGirl.define..
try this.
FactoryGirl.define do
factory :category do
name "Foo"
end
end
That should work fine, and does not screw up my migrations or load.. Today, I had to fix an issue where I was referencing a model constant from my factory directly and had to put it in a block to fix things.
FactoryGirl.define do
factory :category do
# this causes unknown table isseus
# state Category::Active
# this does not.
state { Category::Active }
end
end

prepopulating admin user in database with authlogic rails plugin

I've been using the Authlogic rails plugin. Really all I am using it for is to have one admin user who can edit the site. It's not a site where people sign up accounts. I'm going to end up making the create user method restricted by an already logged in user, but of course, when I clear the DB I can't create a user, so I have to prepopulate it somehow. I tried just making a migration to put a dump of a user I created but that doesn't work and seems pretty hacky. What's the best way to handle this? It's tricky since the passwords get hashed, so I feel like I have to create one and then pull out the hashed entries...
Rails 2.3.4 adds a new feature to seed databases.
You can add in your seed in db/seed.rb file:
User.create(:username => "admin", :password => "notthis", :password_confirmation => "notthis", :email => "admin#example.com")
Then insert it with:
rake db:seed
for production or test
RAILS_ENV="production" rake db:seed
RAILS_ENV="test" rake db:seed
My favorite feature in 2.3.4 so far
If you are using >= Rails 2.3.4 the new features include a db/seeds.rb file. This is now the default file for seeding data.
In there you can simple use your models like User.create(:login=>"admin", :etc => :etc) to create your data.
With this approach rake db:setup will also seed the data as will rake db:seed if you already have the DB.
In older projects I've sometimes used a fixture (remeber to change the password straight away) with something like users.yml:
admin:
id: 1
email: admin#domain.com
login: admin
crypted_password: a4a4e4809f0a285e76bb6b35f97c9323e912adca
salt: 7e8455432de1ab5f3fE0e724b1e71500a29ab5ca
created_at: <%= Time.now.to_s :db %>
updated_at: <%= Time.now.to_s :db %>
rake db:fixtures:load FIXTURES=users
Or finally as the other guys have said you have the rake task option, hope that helps.
Most used approach is to have a rake task that is run after deployment to host with empty database.
Add a rake task:
# Add whatever fields you validate in user model
# for me only username and password
desc 'Add Admin: rake add_admin username=some_admin password=some_pass'
task :add_admin => :environment do
User.create!(:username=> ENV["username"], :password=> ENV["password"],:password_confirmation => ENV["password"])
end

Resources