How to seed a Rails 3.1 app with scoped mass assignment - ruby-on-rails-3

How does Rails 3.1 (RC4) and scoped mass assignment expect us to work with seeds.rb when loading a list of data.
For example. I normally have something like:
City.create([
{ :name => 'Chicago' },
{ :name => 'Copenhagen' },
...
])
Which creates over 100+ cities. this doesn't work anymore since the City model has a scoped mass assignment :as => :admin.
As far as I know, the .create() method does not allow us to throw in :as => :admin.
Only .new() and .update_attributes() allows us to do this with :as => :admin.
So doing something like (below) is cumbersome (especially for 100+ records):
city1 = City.new({ :name => 'Chicago' }, :as => :admin)
city1.save
city2 = City.new({ :name => 'Copenhagen' }, :as => :admin)
city2.save
Any thoughts on this?

You can do the following:
City.create([
{ :name => 'Chicago' },
{ :name => 'Copenhagen' },
...
], :without_protection => true)
This completely overrides the mass assignment protection - so be sure to only use this in say the seeds.

Related

Thinking Sphinx Sort Order doesn't work as expected.

I have a column in the join(middle) table. I want to search on that column that is position
here is my index file
ThinkingSphinx::Index.define :restaurant, :with => :active_record, :delta => ThinkingSphinx::Deltas::DelayedDelta do
indexes schools.school_name, :sortable => true, :as => :school_name
indexes schools.branch_name, :sortable => true, :as => :branch_name
indexes contact_info.restaurant_name, :sortable => true, :as => :restaurant_name
indexes delivery_info.delivery_charges, :as => :delivery_charges
indexes restaurant_schools.position, :as => :restaurant_position, :sortable => true
has restaurant_info.is_pick_up, :as => :pick_up, :facet => true
has delivery_info.is_delivery, :as => :delivery, :facet => true
has schools.id, :as => :school_id, :facet => true
has restaurant_categories.id, :as => :restaurant_category_ids, :facet => true
has restaurant_info.min_order, :as => :min_order, :type => :float
has avg_rating, :as => :rating, :type => :integer
has ranking, :as => :ranking, :type => :integer
has delivery_info.delivery_estimated_time, :as => :delivery_eta, :type => :integer
set_property :min_infix_len => 1
end
When i do query like:
#restaurants = Restaurant.search :with => {:school_id => school_ids }
#restaurants = #restaurants.search :order => :restaurant_position
Its not giving me records as it should be.
Please advice what should i fix the get the accurate results.
A few things to note here.
Firstly: your restaurant_position field is a collection of many values (if restaurant_schools is a has_many or has_and_belongs_to_many association, which the plural name suggests). This means it actually ends up being a string of values concatenated together (with space characters as the separator). e.g. "1 4 7 2"
Secondly: even if you changed it to an attribute, it would be a multi-value attribute. Sorting against a multi-value attribute doesn't make sense (should the average of all values be used? The smallest? The largest? The sum?).
And finally: Perhaps you're hoping the filter you're providing (on school_id) to link into the sorting logic? Sphinx is not a relational database, nor does it have any concept of hashes/dictionaries, so there's no connection between each restaurant_position value and the corresponding school they may be associated with in your database.
If you do want that connection, then it's best to have a Sphinx index on the model which has one school and one position (I'm guessing that's RestaurantSchool). From there, you can pull in relevant fields and attributes via associations, but you can also search/sort with something like this:
RestaurantSchool.search :with => {:school_id => school_ids}, :order => :position

Uploading to Rackspace Cloud Files with paperclip and fog

Can't figure out how to do this? and couldn't find much help from anywhere else!
I have set up the paperclip and fog like this;
config/initializers/fog.rb
connection = Fog::Storage.new({
:provider => 'Rackspace',
:rackspace_username => '',
:rackspace_api_key => ''
})
environment.rb;
Paperclip::Attachment.default_options.update({
:path => ":attachment/:id/:timestamp_:style.:extension",
:storage => :fog,
:fog_credentials => {
:provider => 'Rackspace',
:rackspace_username => '',
:rackspace_api_key => '',
:persistent => false
},
:fog_directory => '',
:fog_public => true
})
I am using file_field to get an image and then posting it to my controller. This gets me something like this in;
"pic"=>{"image"=>#<ActionDispatch::Http::UploadedFile:0x007f90ac06a6c8 #original_filename="3245-1920x1200.jpg", #content_type="image/jpeg", #headers="Content-Disposition: form-data; name=\"cloth[pic][image]\"; filename=\"3245-1920x1200.jpg\"\r\nContent-Type: image/jpeg\r\n", #tempfile=#<File:/tmp/RackMultipart20130104-5386-103laem>>}
What I can't understand is that how do I go about actually saving this file to cloud files using something like this;
file = directory.files.create(
:key => 'resume.html',
:body => File.open("/path/to/my/resume.html"),
:public => true
)
EDIT
Relevant Models;
class Cloth
include Mongoid::Document
has_many :pics
class Pic
include Mongoid::Document
include Mongoid::Paperclip
belongs_to :cloth
has_mongoid_attached_file :image, :styles => { :medium => "300x300>", :thumb => "100x100>" }
And in the controller this is how I am currently creating pic based on above params;
#cloth = Cloth.new
#cloth.pics.create!(params[:cloth][:pic])
Let's step back and look at the problem from different perspective. Can you see if the following script will upload an image to your container:
require 'fog'
service = Fog::Storage.new({
:provider => 'Rackspace',
:rackspace_username => YOUR_USERNAME,
:rackspace_api_key => YOUR_API_KEY
})
container = service.directories.new(:key => YOUR_CONTAINER_NAME)
container.files.create :key => 'my-pix.jpg', :body => File.open PATH_TO_FILE
Update the uppercase parameters with the appropriate variables and let me know what happens. Hopefully this will help narrow down the problem.
Paperclip and ActiveRecord should automatically handle the file upload for you. Here is a good quick start explaining the process:
https://github.com/thoughtbot/paperclip#quick-start
If you are still having issues, can you provide me with the relevant controller and model code?

Active admin and money

I am using active admin with the money - https://github.com/RubyMoney/money gem. I have some attributes handled by the money gem.
The money gem stores values in cents. When i create an entry with active admin, the correct value is created in DB (5000 for 50.00).
However when i edit an entry, the value is multiplied by 100, meaning that AA display 5000 for an original input of 50.00. If i edit anything with a money attribute, it will multiply by 100. At creation, the value goes through money logic, but at edition, somehow active admin skip that part displaying cents instead of the final monetary value.
Is there a way to use the money gem with active admin?
example :
form :html => { :enctype => "multipart/form-data"} do |f|
f.inputs "Products" do
......
f.has_many :pricings do |p|
p.input :price
p.input :_destroy, :as => :boolean,:label=>"Effacer"
end
f.actions :publish
end
Model :
# encoding: utf-8
class Pricing < ActiveRecord::Base
belongs_to :priceable, :polymorphic => true
attr_accessible :price
composed_of :price,
:class_name => "Money",
:mapping => [%w(price cents), %w(currency currency_as_string)],
:constructor => Proc.new { |cents, currency| Money.new(cents || 0, currency || Money.default_currency) },
:converter => Proc.new { |value| value.respond_to?(:to_money) ? value.to_money : raise(ArgumentError, "Can't convert #{value.class} to Money") }
end
Rails callbacks are very handy for creating a solution to this kind of issue.
I would just use and after_update callback.
Example:
# encoding: utf-8
class Pricing < ActiveRecord::Base
after_update :fix_price
belongs_to :priceable, :polymorphic => true
attr_accessible :price
composed_of :price,
:class_name => "Money",
:mapping => [%w(price cents), %w(currency currency_as_string)],
:constructor => Proc.new { |cents, currency| Money.new(cents || 0, currency || Money.default_currency) },
:converter => Proc.new { |value| value.respond_to?(:to_money) ? value.to_money : raise(ArgumentError, "Can't convert #{value.class} to Money") }
def fix_price
self.price = (self.price/100)
end
end
My problem came from my usage of Money :
composed_of :price,
:class_name => "Money",
:mapping => [%w(price_cents cents), %w(currency currency_as_string)],
:constructor => Proc.new { |price_cents, currency| Money.new(price_cents || 0, currency || Money.default_currency) },
:converter => Proc.new { |value| value.respond_to?(:to_money) ? value.to_money : raise(ArgumentError, "Can't convert #{value.class} to Money") }
I renamed my price in DB by price_cents, and i put it in the class where it was needed in the money declaration. I was using cent where i should have used price, and even then having the money object and the field in DB using the same name doesn't seem to work. In the end the problem was not related to Active Admin.

Rails 3.1 validates uniqueness of nested attributes for polymorphic association

Given the following models:
##Invoice.rb
has_many :line_items, :as => :line_itemable
accepts_nested_attributes_for :line_items
##LineItem.rb
belongs_to :line_itemable, :polymorphic => true
validates :employee_id, :presence => true, :uniqueness => { :scope => [ :line_itemable_id, :line_itemable_type ] }
How would I go about validating the following new invoice
i = Invoice.new
i.line_items << [ LineItem.new( :employee_id => 1 ), LineItem.new( :employee_id => 1 ) ]
i.valid?
The invoice should not be valid because the line_items employee_id's are the same and yet no error is thrown and the line_items are added to the database. If the Invoice is an existing record the validations do work.
Any ideas? Is this a bug?
To prevent bad data I have added the following index but would like to have the proper rails validations
add_index :line_items, [ :employee_id, :line_itemable_type, :line_itemable_id ], :unique => true, :name => 'index_line_item_employee_id'
I would like to code exactly as you did, but the only way that I find to bypass this was to write a custom validate in the Invoice class. This solution has a drawback that the problematic fields doesn't get highlighted.

why am I getting a 'no route matches' error in Rails 3?

I have in my haml:
= link_to("Calls Today", todo_path)
And in my routes.rb:
match "todo/today" => "todo#show_date"
match "todo/today/campaign/:id" => "todo#show_date", :as => "todo"
My understanding is that 'todo_path' should find todo controller and show_date.
This route :
match "todo/today/campaign/:id" => "todo#show_date", :as => "todo"
Expects an id parameter. Therefore, your link_to should be like :
= link_to("Calls Today", todo_path(:id => your_id))