Rails 3 Custom Validation against DB-Entries - ruby-on-rails-3

I have currently a website which lets every user register, but I want to give out codes, so that only users with a special code can register. I already worked with validation, but I really need your help for doing this.
At first, I have my form which lets the user register and where the user can input the code.
Then I have the User Model, which should containt the validation checks:
validates :registration_codes, :presence => true, ??? => ???
I can get my reg_codes in any form, because I haven't created them yet. Maybe I will just update them manually and hardcode or maybe I will make a model. I don't know. So, what I just need is the validation check which should do something like this:
:registration_code should be code1 or code2 or code3
I have even tried to make a custom method, but I didn't find out how to forward the form input to my method.
Thanks for any help!

I wrote an custom method, which I call by:
validate :validate_regcode
And then I just search in the DB for the code and check if the result is empty:
def validate_regcode
regcode_feed = Code.where("regcode = ?", regcode)
if regcode_feed.empty?
errors.add(:regcode, "Ihr Registrierungscode ist leider ungültig.")
end
end
So, at all, it's really simple if you know the way to do it. Maybe there's something even simpler, but I like my way :)

Related

rails user input with <script>, stored, and displayed

I have an application that collect user input and store to DB and show back to user.
One user entered "alert(1)" into the name field and saved it into DB.
Whenever the name is displayed, the page will be broken.
I know how to fix that input only with validation for input, and h() for output.
However, I have so many input fields and so many outputs that accept users' text.
Is there any simple way to prevent this happening(i.e. overriding params method, etc)?
I also want to know how you expert guys are dealing with this problem?
As of Rails 3, my understanding was that embedded ruby code was html escaped by default. You don't need to use h() to make it that way. That is, if you use <%= "<script>a=1/0;</script>" %> in a view, the string is going to be made html safe, and so the script doesn't execute. You would have to specifically use raw() or something similar to avoid it - which you should naturally not do unless you're really confident about the contents.
For output, Rails 3 automatically html-encode all text unless I use raw() method.
For input, How about making a common validator and apply to all fields that are text or string? Is it desirable?
http://api.rubyonrails.org/classes/ActiveModel/Validator.html
class MyValidator < ActiveModel::Validator
def validate(record)
record.class.columns.each do |c|
if c.type==:text || c.type == :string
record.errors.add c.type, "script tag is not allowed" if c[/<script[^>]*>/]
end
end
end
end

Make URL be title of post

Currently my URL's appear as www.website.com/entries/1, I'd like to make them appear as www.website.com/title-of-entry. I've been messing around with routes and have been able to get the entry title to display in the URL, but Rails is unable to find the entry without supplying an ID. If I send the ID along with the parameters, the URL appears as www.website.com/title-of-entry?=1. Is there anyway I can pass the ID without having it appear in the URL as a parameter? Thanks!
Like most things, there's a gem for this.
FriendlyID.
Installation is easy and you'll be up and running in minutes. Give it a whirl.
Ususally you'll want to to save this part in the database title-of-entry (call the field slug or something`). Your model could look something like this:
class Entry < ActiveRecord::Base
before_validation :set_slug
def set_slug
self.slug = self.title.parameterize
end
def to_param
self.slug
end
end
Now your generated routes look like this: /entries/title-of-entry
To find the corresponding entries you'll have to change your controller:
# instad of this
#entry = Entry.find(params[:id]
# use this
#entry = Entry.find_by_slug(params[:id])
Update
A few things to bear in mind:
You'll have to make sure that slug is unique, otherwise Entry.find_by_slug(params[:id]) will always return the first entry with this slug it encounters.
Entry.find_by_slug(params[:id]) will not raise a ActiveRecord::RecordNotFound exception, but instead just return nil. Consider using Entry.find_by_slug!(params[:id]).
If you really want your routes to look like this /title-of-entry, you'll probably run into problems later on. The router might get you unexpected results if a entry slug looks the same as another controller's name.

Using RSpec, how can I test that a method is called with instance of a class but with specific values on specific attributes?

I want to write a test like the following:
account = Account.find(1)
#controller.should_receive(:authorize!).with(:create, instance_of(User, :account_id => account.id))
(exact example on testing the cancan gem on a controller of mine)
I know that the part :account_id => account.id is invalid.
My question goes here:
How can I call the instance_of but at the same time test the attributes of the instance to have specific values?
I hope that this is clear. Otherwise, let me know, how can I make it more clear.
Thanks in advance
Panayotis
What are you trying to test? That the controller loads the proper instance and the passes the proper instance to :authorize!? If yes, then something like :
Account.should_receive(:find).returns(account))
#controller.should_receive(:authorize!).with(account)
would do the job
You may use a block for more control on the expected arguments, more info:
Argument matchers
To expand on the accepted answer, it is possible to use argument matchers to do the following:
expect(controller).to receive(:authorize!).with do |symbol, received_user|
expect(symbol).to eq :create
expect(received_user).to be_a User
expect(received_user.account).to eq account
end

What's a good way to insert a resource id into the params of another resource?

I'm really new to programming, so I'm having trouble explaining this -- please forgive.
I have a Document model and a Note model in my rails app. A note belongs to a document, and a document has many notes -- the foreign key in the notes table is document_id.
On my document show page, I have a form for a note which uses a :content attribute as a text_area field.
What I'd like to do is pass the document's id into the note params so the note would have both the :content the user submits alng with the :document_id based on the document_path.
Currently I'm adding the :document_id into the note's params hash using a hidden_field form helper, and sending the whole thing to the NotesController, but I hope there's a cleaner / perhaps easier way.
If this makes sense, can someone suggest a better way to do this? Thank you.
In your routes have something like
resources :documents do
resources :notes
end
Then you should be adding a note via this route
/documents/5/notes/new
Then in your NotesController have
def create
#document = Document.find(params[:document_id])
#note = #document.notes.build(params[:note])
if #note.save
# Blah
else
# Blah
end
end
(In no way has this been tested - but it gives you an idea of how to do it in a RESTFUL style without hidden fields)

How do I send multiple params in my rails3 form controller

I'm trying to send a number of virtual attributes from my form but keep running in to an error about not being able to convert symbol to integer.
My controller's got this in it:
#user = User.generate_batch(params[:user][:username_l][:quantity])
And in my model:
def self.generate_batch(username_l, quantity)
What am I doing wrong and where can I read up on this??
S
For one thing, generate_batch has 2 arguments and you provide only one, and in the wrong place I believe.
For future reference, when passing multiple params, I needed to do the following. I hope it helps someone else.
#user = User.generate_batch(params[:user][:username_l],params[:user][:quantity])